From 7603217477b02940b56297c8d743e4174350bdaf Mon Sep 17 00:00:00 2001 From: mckaygerhard Date: Mon, 7 Aug 2023 04:35:22 -0400 Subject: [PATCH] governing - anticheat - anticrack - client detector - administrator mod --- README.md | 2 + mods/governing/LICENSE.txt | 49 ++ mods/governing/README.md | 131 +++++ mods/governing/anticheats.lua | 926 ++++++++++++++++++++++++++++++++ mods/governing/anticracker.lua | 250 +++++++++ mods/governing/antispawn.lua | 65 +++ mods/governing/commands.lua | 144 +++++ mods/governing/depends.txt | 4 + mods/governing/geoip.lua | 145 +++++ mods/governing/governing.png | Bin 0 -> 970 bytes mods/governing/init.lua | 202 +++++++ mods/governing/mod.conf | 2 + mods/governing/settingtypes.txt | 4 + 13 files changed, 1924 insertions(+) create mode 100644 mods/governing/LICENSE.txt create mode 100644 mods/governing/README.md create mode 100644 mods/governing/anticheats.lua create mode 100644 mods/governing/anticracker.lua create mode 100644 mods/governing/antispawn.lua create mode 100644 mods/governing/commands.lua create mode 100644 mods/governing/depends.txt create mode 100644 mods/governing/geoip.lua create mode 100644 mods/governing/governing.png create mode 100644 mods/governing/init.lua create mode 100644 mods/governing/mod.conf create mode 100644 mods/governing/settingtypes.txt diff --git a/README.md b/README.md index c305af5..16ff40b 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ To download you can play this game with the following minetest engines: * fireflies as `fireflies` [mods/fireflies](mods/fireflies) https://github.com/Ezhh/fireflies/blob/master/license.txt * Skandarella * Wilhelmines Marinara as `marinara` [mods/marinara](mods/marinara) https://git.minetest.io/minenux/minetest-mod-marinara forked compatible version +* mckaygerhard + * Governing dictatorchip as `governing` [mods/governing](mods/governing) https://gitlab.com/minenux/minetest-mod-governing ## Licensing diff --git a/mods/governing/LICENSE.txt b/mods/governing/LICENSE.txt new file mode 100644 index 0000000..2981de8 --- /dev/null +++ b/mods/governing/LICENSE.txt @@ -0,0 +1,49 @@ +License of source code +---------------------- + +Copyright (C) 2023 mckaygerhard CC-BY-SA-NC 4.0 + +Copyright (C) 2023 mckayshirou CC-BY-SA-NC 4.0 + +It applies CC-BY-SA-NC 4.0 unless you ask to request permission +with special conditions. The ipcheck idea, the mod inclusion, +can be distributed if the URL of repo are not altered when promotes. + + +CC-BY-SA-NC 4.0 +=============== + + Attribution-ShareAlike 4.0 Unported (CC BY-SA 4.0) + http://creativecommons.org/licenses/by-sa/4.0/ + +You are free to: + +* Share — copy and redistribute the material in any medium or format +* Adapt — remix, transform, and build upon the material + +The licensor cannot revoke these freedoms as long as you follow +the license terms. + +Under the following terms: + +* Attribution — You must give appropriate credit, provide a link to +the license, and indicate if changes were made. You may do so in any +reasonable manner, but not in any way that suggests the licensor +endorses you or your use. +* NonCommercial — You may not use the material for commercial purposes. +* ShareAlike — If you remix, transform, or build upon the material, +you must distribute your contributions under the same license as the +original. +* No additional restrictions — You may not apply legal terms or technological +measures that legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in +the public domain or where your use is permitted by an applicable exception +or limitation. + +No warranties are given. The license may not give you all of the permissions +necessary for your intended use. For example, other rights such as publicity, +privacy, or moral rights may limit how you use the material. + diff --git a/mods/governing/README.md b/mods/governing/README.md new file mode 100644 index 0000000..ca6c10c --- /dev/null +++ b/mods/governing/README.md @@ -0,0 +1,131 @@ +minetest mod governing +====================== + +ADMIN mod, light version of various mods and extra tool for manage server + +Information +----------- + +@mckaygerhard PICCORO's improvement administration combo and commands for minetest + +This mod attempts to be an improvement administration combo, but minimized +as a light version of some other tools like geoip, names-per-ip, antigrif, antihack, +etc etc etc + +![](governing.png) + +## Technical info +----------------- + +This mod must be named `governing` and provides administrarion tools and +procedures to manage server. + +This mod features powerfully anticheat tools, mostly mixture of many others, +and are able to detect the modified clients. + +Repository : https://git.minetest.io/minenux/minetest-mod-governing + +> **Note:** this mod requires that the server have compiled with extra information enabled + +#### Configurations + +| config param | type | value | req | default/min/mx | example or description | +| --------------------- | ------ | ---------- | --- | --------------- | -------------------------------- | +| secure.http_mods | string | governing | yes | none set | geoip,governing | +| secure.trusted_mods | string | governing | yes | none set | auth_rx,governing | +| governing.checkapikey | string | `` | yes | none set | 177cd4797a4949c4b1114d2e4ab9af11 | +| anticheat.timestep | int | 15 | no | 15 / 10 / 300 | How many time will run checks in seconds | +| anticheat.timeagain | int | 15 | no | 15 / 10 / 300 | How many seconds checks again (to compare) on a suspected player | +| anticheat.moderators | string | admin | yes | admin,singleplayer | Comma separated list name players that can watch and check stats | +| beowulf.dfdetect.enable_kick | boot | false | no | false | will kick the cheater when performs detections | + +The `governing.checkapikey` string is requested by registering a free (or paid) +account at https://vpnapi.io/ and **if not configured, will be used a simple geoip request**. + +1. its powered by [VPNapi.io IP VPN & Proxy Detection API](https://vpnapi.io/api-documentation) +2. but if apykey is not set, its powered by [IP Location Finder by KeyCDN](https://tools.keycdn.com/geo) + +> Warning: anticheat its a WIP from rnd's anticheat mod with beowulf mod fusioned + +#### Commands + +| command & format | permission | description function | observations | +| --------------------- | --------- | ----------------------- | ----------------------- | +| `/killme` | interact | kill yourselft | no matter if killme mod is present or not | +| `/govip ` | governing | complete ip player info | Will require keyapi configuration set | +| `/geoip ` | geoip | simple ip player info | no matter if geoip mod is present or not | +| `/cstats` | moderator | to see latest detected cheater | its not a privilegie, use config settings | +| `/cdebug` | moderator | to see even suspected cheats to be verified later | its not a privilegie, use config settings | +| `/satiation` | server | manipulates the satiation of a player | only provide if our mod its present, the original mod already has it | +| `/cchk ` | moderator | checks for a cheater player | it send a msh rare to the cheater | + +#### privs + +* `geoip` can make a geoip query, no matter if geoip mod is present or missing +* `governing` can run administration command like ip check + +> Warning: currently moderator its not a privs.. its a list of players names, its a WIP from rnd's anticheat mod with beowulf mod fusioned + +#### Api + +Currently only geoip functions are exposed, we later exposed antcheat also + +```lua +-- lookup command +governing.checkip("213.152.186.35", function(result) + -- see "Check ip information data" +end) + +-- overrideable callback on player join +governing.joinplayer_callback = function(playername, result) + -- see "Check ip information result data" +end +``` + +Check IP information on data: + +```json +{ + "ip": "8.8.8.8", + "security": { + "vpn": false, + "proxy": false, + "tor": false, + "relay": false, + }, + "location": { + "city": "", + "region": "", + "country": "United States", + "continent": "North America", + "region_code": "", + "country_code": "US", + "continent_code": "NA", + "latitude": "37.7510", + "longitude": "-97.8220", + "time_zone": "America/Chicago", + "locale_code": "en", + "metro_code": "", + "is_in_european_union": false + }, + "network": { + "network": "8.8.8.0/24", + "autonomous_system_number": "AS15169", + "autonomous_system_organization": "GOOGLE" + } +} +``` + +## LICENSE + +* Copyright (C) 2023 mckaygerhard CC-BY-SA-NC 4.0 +* Copyright (C) 2023 mckayshirou CC-BY-SA-NC 4.0 +* Copyright 2016-2017 rnd LGPL v3 for anticheat code of minetest 0.4 engines +* Copyright 2021-2023 BuckarooBanzay MIT for beowulf code of mt-mods + +It applies CC-BY-SA-NC 4.0 unless you ask to request permission +with special conditions. The ipcheck idea, the mod inclusion, +can be distributed if the URL of repo are not altered when promotes. + +URL : https://git.minetest.io/minenux and http://minetest.org + diff --git a/mods/governing/anticheats.lua b/mods/governing/anticheats.lua new file mode 100644 index 0000000..cfbc0d3 --- /dev/null +++ b/mods/governing/anticheats.lua @@ -0,0 +1,926 @@ + +------------------------------------------------------------------------- +-- ANTI PRIVS detects if a custom client without interacting "zips" around the map +-- Copyright (c) 2021 mt-mods/BuckarooBanzay MIT +-- Copyright 2020-2023 improvements and few fixes, mckaygerhard CC-BY-SA-NC 4.0 +------------------------------------------------------------------------- + +-- per-player data +local player_data = {} + +local is_player = function(player) + -- a table being a player is also supported because it quacks sufficiently + -- like a player if it has the is_player function + local t = type(player) + return (t == "userdata" or t == "table") and type(player.is_player) == "function" +end + +-- obtain player data cheats, improved respect beowulf with missing checks and methods +local function get_player_data(name) + local player = minetest.get_player_by_name(name) + if not player_data[name] then + player_data[name] = { + fliyers = 0, -- number of checks for fly ( added only with governing) + strikes = 0, -- number of "strikes" (odd movements) + checked = 0, -- number of checks + pre_pos = player:get_pos() -- position track (missing in beowulf as bug) + } + end + return player_data[name] + -- WARNING pos its always current so checked must be after an interval using callbacks +end + +-- clear player data for cheats +local function track_player_clear(player) + if is_player(player) then + if player:get_player_name() then + player_data[player:get_player_name()] = nil + end + end +end + +-- store player data cheats strikes and checks +local function track_player(player) + if not is_player(player) then return end + local name = player:get_player_name() + local data = get_player_data(name) + local pos = player:get_pos() + + if data.pre_pos then + -- compare positions + local d = vector.distance(pos, data.pre_pos) + if d > 200 then + data.strikes = data.strikes + 1 + end + data.checked = data.checked + 1 + end + + if data.checked >= 10 then + -- check strike-count after 10 movement checks + if data.strikes > 8 then + -- suspicious movement, log it + -- TODO: if this doesn't yield any false-positives, add a kick/ban option + local msg = "suspicious movement detected for player: '" .. name .. "'" + minetest.log("action", "[governing][beowulf] " .. msg) + end + + -- reset counters + data.checked = 0 + data.strikes = 0 + end + + -- store current position + data.pre_pos = pos +end + +----------------------------------------------------------------------- +-- ANTI CRACKERS and CHEATERS by mckaygerhard based on beowulf +------------------------------------------------------------------------ + +-- luacheck: push no max line length +local df = { + "2.0", + "dragonfire", -- many based clients by example teamclient + "f8fd5c11b", -- Merge pull request #59 from PrairieAstronomer/readme_irrlicht_change + "c66ae6717", -- Add exact irrlichtmt version to the clone command + "296cce39d", -- Fix upstream merge issues + "350b6d175", -- Install lua_async dependency + "393c83928", -- Don't include client/game.h on server build + "ccd4c504d", -- Ship dragonfireclient with selected high-quality mods + "147aaf326", -- Fix build instructions + "b09fc5de5", -- Add spider + "d404517d2", -- Make LuaVoxelManipulator available to CSM API + "1ccf88e80", -- minetest.dig_node: Remove node + "950d2c9b3", -- Add ClientObjectRef:remove and return true in on_object_add callback to remove newly added object + "fb4815c66", -- Merge pull request #35 from arydevy/patch-1 + "f12288814", -- Merge pull request #42 from Minetest-j45/master + "f3082146c", -- remove irrlicht from lid dir (accident) + "a3925db22", -- add airjump and remove unused headers + "7824a4956", -- Merge pull request #1 from EliasFleckenstein03/master + "35445d24f", -- Make set_pitch and set_yaw more accurate by not rounding it to integers + "5131675a6", -- Add guards to stop server build fail + "96a37aed3", -- Add minetest.get_send_speed + "d08242316", -- Fix format + "ce0d81a82", -- Change default cheat menu entry height + "b7abc8df2", -- Add on_object_add callback + "4f613bbf5", -- Include tile definitions in get_node_def; Client-side minetest.object_refs table + "c86dcd0f6", -- Add on_object_hp_change callback and nametag images + "b84ed7d0b", -- Call on_object_properties_change callback when adding object to scene + "26cfbda65", -- Add on_object_properties_change callback + "6dc7a65d9", -- Add ClientObjectRef:set_properties + "7d7d4d675", -- Add ClientObjectRef.get_properties + "ea8fa30b6", -- Changed README.md to fit the dragonfire client + "c47eae316", -- Add table.combine to luacheckrc + "83d09ffaf", -- Complete documentation + "e0b4859e7", -- Add ClientObjectRef:remove + "63f7c96ec", -- Fix legit_speed + "5c06763e8", -- Add noise to client CSM API + "7613d9bfe", -- Update .wielded command to output the entire itemstring; add LocalPlayer:get_hotbar_size + "bc79c2344", -- CSM: Use server-like (and safe) HTTP API instead of Mainmenu-like + "166968232", -- Port formspec API from waspsaliva This API is inofficial and undocumented; invalid usage causes the game to crash. Use at own risk! + "e391ee435", -- Forcefully place items when minetest.place_node is used + "546ab256b", -- Update buildbot to new MineClone2 repo and set the game name to MineClone2 rather than mineclone2 + "d3780cefd", -- Attempt to fix SEGFAULT in push_inventory + "d1c84ada2", -- Merge minetest changes + "74f5f033e", -- Add Custom version string + "b2f629d8d", -- Logo improvements + "78b7d1019", -- Add dragonfire logo + "19e0528e3", -- Add minetest.get_nearby_objects + "47d0882cc", -- Fix line containing only whitespace + "4fedc3a31", -- Add minetest.interact + "dc67f669e", -- Make the Cheat Menu size configureable + "906845a87", -- Add minetest.registered_items and minetest.registered_nodes (Doesn't do anything yet) + "3a4325902", -- Fixed crash by adding legacy stuff to defaultsettings (for now) + "53c991c5f", -- Fixed crash due to missing entry in defaultsettings.cpp + "0c6e0c717", -- Reorganize categories + "e8faa2afb", -- Rework Range + "a4d914ba2", -- Make GitHub Actions Happy try 3 + "a34c61093", -- Make GitHub Actions Happy try 2 + "f783f5939", -- Make GitHub Actions Happy try 1 + "8b58465aa", -- Remove obsolete code from clientenvironment + "35c15567a", -- Update builtin/settingtypes.txt to the new philosophy + "0c9e7466e", -- New Cheat Philosophy + "a1e61e561", -- World Cheats improvements; Add BlockLava; Readd minetest.request_http_api for Compatibility + "56d536ea5", -- Update CheatDB URL again + "ce47003cc", -- Update defaults for ContentDB (->CheatDB) + "89995efee", -- CheatDB Support & Enable/Disable CSMs in Main Menu + "3df23e23c", -- Small AutoTool Fix + "8b3eaf5b0", -- Lua API: Particle callbacks; Add NoWeather + "0a285dd33", -- Remove NextItem + "4695222bc", -- Fix and Improve AutoTool + "5bead7daa", -- Added minetest.close_formspec + "f825cf0e3", -- Fixed Minimap position + "eaa8a5132", -- Fixed FastPlace and AutoPlace + "b4e475726", -- Added configureable Colors for PlayerESP and EntityESP + "549025f6a", -- EntityESP, EntityTracers, PlayerESP, PlayerTracers + "eb6aca8b4", -- Merged Minetest + "8de51dae9", -- Fixed crash when attempting to access nonexistant inventory from Lua API + "a65251a7a", -- Fixed glowing GenericCAOs being rendered completely back when Fullbright is enabled + "eaec3645b", -- Added ClientObjectRef:get_hp() + "fb4d54ee3", -- Added minetest.register_on_play_sound + "50629cc6a", -- Improved Scaffold + "3d74e17cc", -- Added AutoSlip (-> Credit to Code-Sploit) + "f9c632466", -- Added JetPack and AutoHit (-> Credits to Code-Sploit and cora) + "843239c0b", -- Added Speed/Jump/Gravity Override + "598e9bdbc", -- Update Credits + "7d327def8", -- Improved AutoSneak + "82216e147", -- LocalPlayer:set_physics_override; minetest.register_on_recieve_physics_override + "4dd5ecfc5", -- Added setpitch & setyaw commands; AutoSprint + "b65db98bd", -- Added OnlyTracePlayers + "e16bbc1fb", -- Merge pull request #14 from corarona/master + "1780adeea", -- lua-api: fix get/set_pitch + "3e7c5d720", -- Possibility to use cheat menu while pressing other keys + "0aa63aafc", -- Fixed warning + "9db80fc6f", -- Run Lint Script + "91ad0d049", -- Merge pull request #10 from corarona/master + "6bda686c0", -- MapBlockMesh Performance Improvement + "1bab49049", -- add LUA_FCT + "6efa8a758", -- add g/s pitch and make_screenshot in lua api + "46237330d", -- Several Enhancements + "60a9ff6ff", -- api-screenshot: change function name to make_screenshot + "1f56317d5", -- Added NodeESP + "75ecaa217", -- Fix and run the Lint autocorrect script + "6ccb5835f", -- Revert "Make Lint Happy" + "244713971", -- Added script that automaticall corrects lint style + "07e61e115", -- Fix github build problems #3 + "3af10766f", -- Fix github build problems #2 + "16d302c9a", -- Fix github build problems + "ad148587d", -- Make Lint Happy + "1145b05ea", -- Updated Credits + "c9221730d", -- Updated Cheat Menu Color Design + "1799d5aa9", -- Cheat Menu Improvements Change + "fba7dc216", -- Merge pull request #8 from realOneplustwo/master + "a7dc1135e", -- Added CheatHUD + "f1d9ac014", -- Moved Killaura to Lua; Added ForceField; Added Friendlist; Added ClientObjectRef:is_local_player(); Documented LocalPlayer:get_object() + "06b72069d", -- Fixed ColorChat + "62958bd60", -- Reverted accidental commit in wrong repo + "00d51fbd5", -- Armor textures support + "7cbe42b1d", -- Re-Added Chat Effects + "28f6a7970", -- lua api: add set/get_pitch + "4f9797b6e", -- lua api: add core.take_screenshot() + "8e9e76a50", -- Revert "Add Block Formspec Hack" + "6652d7ac2", -- Add Block Formspec Hack + "8bc7d49b3", -- Added Nuke + "62cf9b466", -- Fix compile error + "519f98c65", -- Merge pull request #3 from JosiahWI/ui_revamp + "f236476af", -- Fix errors in cheatMenu. + "7af3dee31", -- Merge pull request #2 from JosiahWI/ui_revamp + "ea88dde4b", -- Added Strip, AutoRefill, indexing for InventoryActions and Wield Index starts at 1 now + "7aff09ab2", -- Fix overindent! + "aea9b36ef", -- Improved Colours + "1ef72ad9c", -- Fix indentation style. + "586241008", -- Add missing return. + "b211e90ff", -- Prepare cheatMenu::draw function for easier UI changes. + "e22e334e9", -- Merge pull request #1 from JosiahWI/ui_revamp + "f605308ee", -- Improve drawEntry. + "130d476f6", -- Changed Cheat Menu UI + "f1ff05bf5", -- Added ThroughWalls, InventoryActions API and AutoTotem + "1a7d3d818", -- Extended ClientObjectRef; Improved CrystalPvP + "1e4f35492", -- This is the last try for lint... + "7e0f8fba0", -- Another Lint commit + "151e5782e", -- Lint is still not happy... + "28a560684", -- Added the API additions from waspsaliva + "c1aea404b", -- Lint is bitch + "3a718f12b", -- Make lint happy; Remove stupid redirector + "3b596a96e", -- Fixed Github build problems + "847198edb", -- Edited .gitignore properly; fixed armor invulnarability in the server code. + "bbcd24954", -- New Mod System + "80f416d51", -- Added AttachmentFloat + "cb1915efa", -- Added minetest.drop_selected_item(), Improved AutoEject + "43ee069db", -- Improved X-Ray, added AutoEject + "faa32610e", -- Added ESP, fixed Tracers, improved Jesus + "ee88f4b94", -- Improved Tracers + "c36ff3edb", -- Added AutoSneak and improved X-Ray MapBlock updating + "0a2c90f4c", -- Only draw tracers to objects that are not attached (that fixes tracers to armor) + "044a12666", -- Added Tracers, NoSlow and NoForceRotate; GUI Colors changed + "b9f8f0a23", -- The Robot Update + "af085acbd", -- Added Schematicas + "0730ed216", -- Delete my stupid test mod lol + "772c9629e", -- Unrestricted HTTP API for Client, Server and Main Menu + "9b1030cac", -- Added minetest.get_inventory(location) + "2321e3da4", -- Removed console output spammed by minetest.find_node_near + "90f66dad8", -- Removed experimental code + "8b4d27141", -- Fixed typo in clientmods/inventory/mod.conf + "d8b8c1d31", -- Added Documentation for Additional API + "6e6c68ba0", -- Added Chat Spam, Replace and settingtypes.txt for Clientmods + "79d0314d7", -- Update Buildbots + "770bde9c6", -- idk + "e245151c5", -- Improved World hacks + "19205f6b3", -- Improved World Hacks, added API functions + "73b89703f", -- Improved World hacks, added fill + "248dedaba", -- Added floationg water to BlockWater + "9dc3eb777", -- Fixed broken Chatcommands + "80371bc16", -- Added .listwarps + "1c29f21e0", -- Imporoved set_wield_index() to include camera update + "3bed0981d", -- UI Update; Added AutoTool + "622d54726", -- Added DestroyWater (:P anon) + "9019e18b9", -- Some Updates + "107dec6c0", -- Added Coords + "f1760622e", -- Added BrightNight + "2675bcca1", -- Added more cheats + "3d980cf57", -- Improved Xray and Fullbright + "f7a042223", -- Added cheat Menu + "344fddc17", -- Improved Killaura and Chat position + "678559bb6", -- removed leagcy clientmods + "9194165cf", -- Added autodig, moved chat + "064c25caa", -- Added EntitySpeed + "5a8610c2f", -- Added customizable keybindings, improved freecam, added special inventory keybind (by default ender inventory) + "83f59484d", -- Fixed 5.4.0-dev build + "ffe3c2ae0", -- Update to minetest 5.4.0-dev + "45aa2516b", -- Added settings + "f22339ed8", -- Removed fast killaura + "408e39a1d", -- Added Anti Knockback + "eee0f960b", -- Removed minetest.conf.old + "39d7567c1", -- Fixed Crash + "305e0e0d3", -- Auto disable smooth lighting when fullbright is active + "6796baec6", -- Defaultsettings + "5a2bf6634", -- Added Clientmods + "e610149c0", -- Initial Commit + "68f9263a2", -- Hacked Client + "90d885506", -- GalwayGirl Client +} + +--[[ +To update commit list: save commit logs for master branches of minetest in mt.log and dragonfire in df.log +$ git log --oneline origin/master > mt.log; git log --oneline dragonfire/master > df.log (both in same remo using git remote) + +Find and drop commits that seems to exist in both remotes, print rest of it: +$ sort -k3 <(awk '{print NR" "$0}' df.log mt.log mt.log) | uniq -uf2 | sort -nk1 | sed -r 's/^[^ ]+ ([^ ]+) (.*)$/\t"\1", -- \2/' + +Replace above entries with output +--]] + +local function dfver(stringversion) + -- loop into table of commmits and find the compared version + for _,v in ipairs(df) do + local pp = stringversion:find(v) + if pp then + return v + end + end +end + +------------------------------------------------------------------------- +-- ANTI CHEAT for MT4 and old MT5 engines by rnd +-- Copyright 2016 rnd LGPL v3 +-- Copyright 2020-2023 improvements and few fixes, mckaygerhard CC-BY-SA-NC 4.0 +------------------------------------------------------------------------- +local cheat = {}; +local version = "09/08/2017"; + +anticheatsettings = {}; +anticheatsettings.moderators = {} +anticheatsettings.CHEAT_TIMESTEP = tonumber(minetest.settings:get("governing.timestep")) or 15; -- check timestep all players +anticheatsettings.CHECK_AGAIN = tonumber(minetest.settings:get("governing.timeagain")) or 15; -- after player found in bad position check again after this to make sure its not lag, this should be larger than expected lag in seconds +anticheatsettings.STRING_MODERA = minetest.settings:get("governing.moderators") or "admin,singleplayer"; +-- moderators list, those players can use cheat debug and will see full cheat message +for str in string.gmatch(anticheatsettings.STRING_MODERA, "([^,]+)") do table.insert(anticheatsettings.moderators, str) end + + +local CHEAT_TIMESTEP = anticheatsettings.CHEAT_TIMESTEP; +local CHECK_AGAIN = anticheatsettings.CHECK_AGAIN; +cheat.moderators = anticheatsettings.moderators; + +bonemod = minetest.get_modpath("boneworld") + +anticheatdb = {}; -- data about detected cheaters + +cheat.suspect = ""; +cheat.players = {}; -- temporary cheat detection db +cheat.message = ""; +cheat.debuglist = {}; -- [name]=true -- who gets to see debug msgs + +cheat.scan_timer = 0; -- global scan of players +cheat.stat_timer = 0; -- used to collect stats + +cheat.nodelist = {}; + +cheat.timestep = CHEAT_TIMESTEP; +-- list of forbidden nodes +cheat.nodelist = {["default:stone"] = false, ["default:cobble"]= false, ["default:dirt"] = false, ["default:sand"]=false,["default:tree"]= false}; + + +local punish_cheat = function(name) + + local player = minetest.get_player_by_name(name); + local ip = tostring(minetest.get_player_ip(name)); + + if not player then return end + local text=""; local logtext = ""; + + if cheat.players[name].cheattype == 1 then + text = "#anticheat: ".. name .. " was caught walking inside wall"; + logtext = os.date("%H:%M.%S").." #anticheat: ".. name .. " was caught walking inside wall at " .. minetest.pos_to_string(cheat.players[name].cheatpos); + --player:set_hp(0); + elseif cheat.players[name].cheattype == 2 then + + local gravity = player:get_physics_override().gravity; if gravity<1 then return end + logtext= os.date("%H:%M.%S").." #anticheat: ".. name .. " was caught flying at " .. minetest.pos_to_string(cheat.players[name].cheatpos); + if cheat.players[name].cheatpos.y>5 then -- only above height 5 it directly damages flyer + text = "#anticheat: ".. name .. " was caught flying"; + --player:set_hp(0); + end + end + + if text~="" then + minetest.chat_send_all(text); + end + + if logtext~="" then + minetest.log("action", logtext); + cheat.message = logtext; + + anticheatdb[ip] = {name = name, msg = logtext}; + + cheat.players[name].count=0; -- reset counter + cheat.players[name].cheattype = 0; + + for namem,_ in pairs(cheat.moderators) do -- display full message to moderators + minetest.chat_send_player(namem,logtext); + end + end +end + +-- CHECKS + + +-- DETAILED NOCLIP CHECK +local check_noclip = function(pos) + local nodename = minetest.get_node(pos).name; + local clear=true; + if nodename ~= "air" then -- check if forbidden material! + clear = cheat.nodelist[nodename]; -- test clip violation + if clear == nil then clear = true end + end + + if not clear then -- more detailed check + local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, {"air"}); + if #anodes == 0 then return false end + clear=true; + end + return clear; +end + +-- DETAILED FLY CHECK +local check_fly = function(pos) -- return true if player not flying + local fly = (minetest.get_node(pos).name=="air" and minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name=="air"); -- prerequisite for flying is this to be "air", but not sufficient condition + if not fly then return true end; + + local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, {"air"}); + if #anodes == 18 then -- player standing on air? + return false + else + return true + end +end + + +local round = function (x) + if x > 0 then + return math.floor(x+0.5) + else + return -math.floor(-x+0.5) + end +end + +--main check routine +local check_player = function(player) + + local name = player:get_player_name(); + local privs = minetest.get_player_privs(name).kick;if privs then return end -- dont check moderators + + local pos = player:getpos(); -- feet position + pos.x = round(pos.x*10)/10;pos.z = round(pos.z*10)/10; -- less useless clutter + pos.y = round(pos.y*10)/10; -- minetest buggy collision - need to do this or it returns wrong materials for feet position: aka magic number 0.498?????228 + if pos.y<0 then pos.y=pos.y+1 end -- weird, without this it fails to check feet block where y<0, it checks one below feet + + local nodename = minetest.get_node(pos).name; + local clear=true; + if nodename ~= "air" then -- check if forbidden material! + clear = cheat.nodelist[nodename]; -- test clip violation + if clear == nil then clear = true end + end + + local fly = (nodename=="air" and minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name=="air"); -- prerequisite for flying, but not sufficient condition + + if cheat.players[name].count == 0 then -- player hasnt "cheated" yet, remember last clear position + cheat.players[name].clearpos = cheat.players[name].lastpos + end + + + -- manage noclip cheats + if not clear then -- player caught inside walls + local moved = (cheat.players[name].lastpos.x~=pos.x) or (cheat.players[name].lastpos.y~=pos.y) or (cheat.players[name].lastpos.z~=pos.z); + if moved then -- if player stands still whole time do nothing + if cheat.players[name].count == 0 then cheat.players[name].cheatpos = pos end -- remember first position where player found inside wall + + + if cheat.players[name].count == 0 then + minetest.after(CHECK_AGAIN+math.random(5), + function() + cheat.players[name].count = 0; + if not check_noclip(pos) then + punish_cheat(name)-- we got a cheater! + else + cheat.players[name].count = 0; -- reset + cheat.players[name].cheattype = 0; + end + end + ) + end + + if cheat.players[name].count == 0 then -- mark as suspect + cheat.players[name].count = 1; + cheat.players[name].cheattype = 1; + end + + end + end + + -- manage flyers + if fly then + + local fpos; + fly,fpos = minetest.line_of_sight(pos, {x = pos.x, y = pos.y - 4, z = pos.z}, 1); --checking node maximal jump height below feet + + if fly then -- so we are in air, are we flying? + + if player:get_player_control().sneak then -- player sneaks, maybe on border? + --search 18 nodes to find non air + local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, {"air"}); + if #anodes < 18 then fly = false end + end -- if at this point fly = true means player is not standing on border + + if pos.y>=cheat.players[name].lastpos.y and fly then -- we actually didnt go down from last time and not on border + + -- was lastpos in air too? + local lastpos = cheat.players[name].lastpos; + local anodes = minetest.find_nodes_in_area({x=lastpos.x-1, y=lastpos.y-1, z=lastpos.z-1}, {x=lastpos.x+1, y=lastpos.y, z=lastpos.z+1}, {"air"}); + if #anodes == 18 then fly = true else fly = false end + + if fly then -- so now in air above previous position, which was in air too? + + if cheat.players[name].count == 0 then cheat.players[name].cheatpos = pos end -- remember first position where player found "cheating" + + if cheat.players[name].count == 0 then + minetest.after(CHECK_AGAIN, + function() + cheat.players[name].count = 0; + if not check_fly(pos) then + punish_cheat(name)-- we got a cheater! + else + cheat.players[name].count = 0; + cheat.players[name].cheattype = 0; + end + end + ) + end + + if cheat.players[name].count == 0 then -- mark as suspect + cheat.players[name].count = 1; + cheat.players[name].cheattype = 2; + end + end + + end + + end + end + + cheat.players[name].lastpos = pos +end + + + +minetest.register_globalstep(function(dtime) + + cheat.scan_timer = cheat.scan_timer + dtime + + + -- GENERAL SCAN OF ALL PLAYERS + if cheat.scan_timer>cheat.timestep then + + + cheat.stat_timer = cheat.stat_timer + cheat.timestep; + -- dig xp stats every 2 minutes + if bonemod and cheat.stat_timer>120 then + cheat.stat_timer = 0; + local players = minetest.get_connected_players(); + for _,player in pairs(players) do + local pname = player:get_player_name(); + if cheat.players[pname].stats.state == 1 then -- only if dig xp loaded to prevent anomalous stats + if boneworld.digxp[pname] then + local deltadig = cheat.players[pname].stats.digxp; + cheat.players[pname].stats.digxp = boneworld.digxp[pname]; + deltadig = boneworld.digxp[pname]-deltadig; + cheat.players[pname].stats.deltadig = deltadig; + + if deltadig>cheat.players[pname].stats.maxdeltadig then + cheat.players[pname].stats.maxdeltadig = deltadig; + end + + if deltadig>2 then -- unnaturally high deltadig + local ip = tostring(minetest.get_player_ip(pname)); + local logtext = os.date("%H:%M.%S") .. " #anticheat: " .. pname .. " (ip " .. ip .. ") is mining resources too fast, deltadig " .. deltadig; + anticheatdb[ip] = {name = pname, msg = logtext}; + minetest.log("action", logtext); + end + + end + end + end + end + + + cheat.timestep = CHEAT_TIMESTEP + (2*math.random()-1)*2; -- randomize step so its unpredictable + cheat.scan_timer=0; + --local t = minetest.get_gametime(); + local players = minetest.get_connected_players(); + + for _,player in pairs(players) do + check_player(player); + end + + for name,_ in pairs(cheat.debuglist) do -- show suspects in debug + for _,player in pairs(players) do + local pname = player:get_player_name(); + if cheat.players[pname].count>0 then + minetest.chat_send_player(name, "name " .. pname .. ", cheat pos " .. minetest.pos_to_string(cheat.players[pname].cheatpos) .. " last clear pos " .. minetest.pos_to_string(cheat.players[pname].clearpos) .. " cheat type " .. cheat.players[pname].cheattype .. " cheatcount " .. cheat.players[pname].count ); + end + end + end + + + end +end) + +-- long range dig check + +local check_can_dig = function(pos, digger) + + local p = digger:getpos(); + if p.y<0 then p.y=p.y+2 else p.y=p.y+1 end -- head position + local dist = math.max(math.abs(p.x-pos.x),math.abs(p.y-pos.y),math.abs(p.z-pos.z)); + + + if dist>6 then -- here 5 + dist = math.floor(dist*100)/100; + local pname = digger:get_player_name(); + local logtext = os.date("%H:%M.%S") .. "#anticheat: long range dig " .. pname ..", distance " .. dist .. ", pos " .. minetest.pos_to_string(pos); + for name,_ in pairs(cheat.debuglist) do -- show to all watchers + minetest.chat_send_player(name,logtext) + minetest.log("warning", "[governing] "..logtext) + end + local ip = tostring(minetest.get_player_ip(pname)); + anticheatdb[ip] = {name = pname, msg = logtext}; + return false + end + + return true +end + +local set_check_can_dig = function(name) + local tabl = minetest.registered_nodes[name]; + if not tabl then return end + tabl.can_dig = check_can_dig; + minetest.override_item(name, {can_dig = check_can_dig}) + --minetest.register_node(":"..name, tabl); +end + +local function is_player(player) + if player then + if type(player) == "userdata" or type(player) == "table" then return true end + end + return false +end + +minetest.register_on_joinplayer(function(player) + + -- init stuff on player join + if not is_player(player) then return end + local name = player:get_player_name(); + if type(name) ~= "string" then return end + local pos = player:getpos(); + + -- no matter if are incomplete info, save most possible of and start recolection of stats + if cheat.players[name] == nil then + cheat.players[name]={count=0,cheatpos = pos, clearpos = pos, lastpos = pos, cheattype = 0}; -- type 0: none, 1 noclip, 2 fly + end + + -- try to fill some stats or retrieve previously + if cheat.players[name] and cheat.players[name].stats == nil then + cheat.players[name].stats = {maxdeltadig=0,deltadig = 0,digxp = 0, state = 0}; -- various statistics about player: max dig xp increase in 2 minutes, current dig xp increase + if bonemod then + minetest.after(4, -- load digxp after boneworld loads it + function() + if boneworld.xp then + cheat.players[name].stats.digxp = boneworld.digxp[name] or 0; + cheat.players[name].stats.state = 1; + end + end + ) --state 0 = stats not loaded yet + end + end + + -- check anticheat db for cheaters clients + -- =================================== + + local ip = tostring(minetest.get_player_ip(name)); + local info = minetest.get_player_information(name) + local msgiplevelone = ""; + local msgipleveltwo = ""; + + --check ip first try of info manually, later from player info + if anticheatdb[ip] then + msgiplevelone = "#anticheat: welcome back detected cheater, ip = " .. ip .. ", name " .. anticheatdb[ip].name .. ", new name = " .. name; + end; + --check names from stats + for ip,v in pairs(anticheatdb) do + if v.name == name then + msgiplevelone = "#anticheat: welcome back detected cheater, ip = " .. ip .. ", name = newname = " .. v.name; + break; + end + end + -- send detection msg before try to check info (cos info may be incomplete detection) + if msgiplevelone~="" then + minetest.after(1, function() + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgiplevelone); + end + end) + end + + -- rare case / simple sanity check, _should_ not happen ;) pretty rare but modified client that does not give info + if not info then + if not is_player(player) then + name = name .. " is a bot confirmed, also" + end + msgipleveltwo = "[governing] can't retrieve info, player '" .. name .. "' disappeared or seems craker" + minetest.after(2, function() + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgipleveltwo); + end + end) + minetest.log("warning", msgipleveltwo) + return + end + + -- prepare information report log, "version_string" is only available if the engine was compiled in debug mode (or patched accordingly) + local msgipleveltwo = "[governing] player '" .. name .. "' joined" .. + " from:" .. info.address .. + " protocol_version:" .. (info.protocol_version or "20?") .. + " formspec_version:" .. (info.formspec_version or "old") .. + " lang_code:" .. (info.lang_code or "") .. + " serialization_version:" .. (info.serialization_version or "20?") .. + " version_string:" .. (info.version_string or "not supported") + minetest.log("action", msgipleveltwo) + + local msgm = "#anticheat detected a cheater with ".. tostring(minetest.get_player_ip(name)).." named "..name + if info.version_string then + local dfv = dfver(info.version_string) + if dfv then + minetest.after(3, function() + minetest.chat_send_player(name, msgiplevelone); + if minetest.settings:get_bool("beowulf.dfdetect.enable_kick", false) then + minetest.kick_player(name, "Are you a cheater stupid user? change your cracked client for play") + end + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgm); -- advertise moderators + end + end) + minetest.log(msgm) + end + else + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgm); -- advertise moderators + end + minetest.log(msgm) + end + +end) + +minetest.register_chatcommand("cchk", { + privs = { + interact = true + }, + description = "cchk NAME, checks if player is cheating in this moment", + func = function(name, param) + local privs = minetest.get_player_privs(name).privs; + if not cheat.moderators[name] and not privs then return end + + local player = minetest.get_player_by_name(param); + if not player then return end + check_player(player); + + local ip = tostring(minetest.get_player_ip(param)); + local info = minetest.get_player_information(param) + local msgm = "#anticheat detected a cheater with "..ip.." named "..param + if info.version_string then + local dfv = dfver(info.version_string) + if dfv then + msgm = msgm.." using "..info.version_string + minetest.chat_send_player(param, "..... cheat"); + if minetest.settings:get_bool("beowulf.dfdetect.enable_kick", false) then + minetest.kick_player(param, "Are you a cheater stupid user? change your cracked client for play") + end + minetest.chat_send_player(name,msgm); -- advertise moderators + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgm); -- advertise moderators + end + minetest.log(msgm) + end + else + for namemd,_ in pairs(cheat.moderators) do + minetest.chat_send_player(namemd,msgm); -- advertise moderators + end + minetest.log(msgm) + end + + + local players = minetest.get_connected_players(); + for name,_ in pairs(cheat.debuglist) do -- show suspects in debug + for _,player in pairs(players) do + local pname = player:get_player_name(); + if cheat.players[pname].count>0 then + minetest.chat_send_player(name, "name " .. pname .. ", cheat pos " .. minetest.pos_to_string(cheat.players[pname].cheatpos) .. " last clear pos " .. minetest.pos_to_string(cheat.players[pname].clearpos) .. " cheat type " .. cheat.players[pname].cheattype .. " cheatcount " .. cheat.players[pname].count ); + end + end + end + end +}) + + +minetest.register_chatcommand("crep", { -- see cheat report + privs = { + interact = true + }, + description = "crep 0/1, 0 = default cheat report, 1 = connected player stats", + func = function(name, param) + local privs = minetest.get_player_privs(name).privs; + if not cheat.moderators[name] and not privs then return end + + if param == "" then + minetest.chat_send_player(name,"use: crep type, types: 0(default) cheat report, 1 connected player stats (".. version ..")"); + end + + param = tonumber(param) or 0; + + if param == 0 then -- show cheat report + local text = ""; + for ip,v in pairs(anticheatdb) do + if v and v.name and v.msg then + text = text .. "ip " .. ip .. " ".. v.msg .. "\n"; + end + end + if text ~= "" then + local form = "size [6,7] textarea[0,0;6.5,8.5;creport;CHEAT REPORT;".. text.."]" + minetest.show_formspec(name, "anticheatreport", form) + end + elseif param == 1 then -- show cheat stats + local text = ""; + local players = minetest.get_connected_players(); + for _,player in pairs(players) do + local pname = player:get_player_name(); + local ip = tostring(minetest.get_player_ip(pname)); + + + text = text .. "\nname " .. pname .. ", digxp " .. math.floor(1000*cheat.players[pname].stats.digxp)/1000 .. + ", deltadigxp(2min) " .. math.floor(1000*cheat.players[pname].stats.deltadig)/1000 .. ", maxdeltadigxp " .. math.floor(1000*cheat.players[pname].stats.maxdeltadig)/1000; -- .. " ".. string.gsub(dump(cheat.players[pname].stats), "\n", " "); + if anticheatdb[ip] then text = text .. " (DETECTED) ip ".. ip .. ", name " .. anticheatdb[ip].name end + end + if text ~= "" then + local form = "size [10,8] textarea[0,0;10.5,9.;creport;CHEAT STATISTICS;".. text.."]" + minetest.show_formspec(name, "anticheatreport", form) + end + end + -- suspects info + local players = minetest.get_connected_players(); + for _,player in pairs(players) do + local pname = player:get_player_name(); + if cheat.players[pname].count>0 then + minetest.chat_send_player(name, "name " .. pname .. ", cheat pos " .. minetest.pos_to_string(cheat.players[pname].cheatpos) .. " last clear pos " .. minetest.pos_to_string(cheat.players[pname].lastpos) .. " cheat type " .. cheat.players[pname].cheattype .. " cheatcount " .. cheat.players[pname].count ); + end + end + + end +}) + +minetest.register_chatcommand("cdebug", { -- toggle cdebug= display of stats on/off for this player + privs = { + interact = true + }, + func = function(name, param) + local privs = minetest.get_player_privs(name).privs; + if not cheat.moderators[name] and not privs then return end + + if cheat.debuglist[name] == nil then cheat.debuglist[name] = true else cheat.debuglist[name] = nil end; + + minetest.chat_send_player(name,"#anticheat: " .. version); + if cheat.debuglist[name]==true then + minetest.chat_send_player(name,"#anticheat: display of debug messages is ON"); + else + minetest.chat_send_player(name,"#anticheat: display of debug messages is OFF"); + end + end +}) + + +------------------------------------------------------------------------- +-- GOVERNONR custom action for features mod code improvements +-- minetest routines to implement the mod features +-- Copyright 2020-2023 mckaygerhard CC-BY-SA-NC 4.0 +------------------------------------------------------------------------- + +-- cleanup after the player leaves +minetest.register_on_leaveplayer(function(player) + if is_player(player) then + track_player_clear(player) + end +end) + + +-- list of nodes to enable damage if noclip or to check if player its diggin too fast +local node_list_check = {} + +-- TODO move this to a comma separted list in config, and adde the check below in node check for fly +if minetest.get_modpath("default") then + table.insert(node_list_check, "default:stone") + table.insert(node_list_check, "default:stone_with_iron") + table.insert(node_list_check, "default:stone_with_copper") + table.insert(node_list_check, "default:stone_with_coal") + table.insert(node_list_check, "default:stone_with_gold") + table.insert(node_list_check, "default:stone_with_mese") + table.insert(node_list_check, "default:stone_with_diamond") +end + +local function interval_fn() + if not governing.modbeowulf then + for _, player in ipairs(minetest.get_connected_players()) do + track_player(player) + end + end + if not governing.modanticheat then + for _, nodename in ipairs(node_list_check) do + set_check_can_dig(nodename); + end + end + + minetest.after(2, interval_fn) +end + +-- TODO: beowulf was pretty unneficient on large player servers.. cos only its made each 1 second and again each x inside function +if governing.is_50 then + minetest.register_on_mods_loaded(interval_fn ) +else + minetest.after(0.1, interval_fn) +end + +-- damaged if a player its making noclip, no matter if admin is doing +for _, nodename in ipairs(node_list_check) do + minetest.override_item(nodename, { + damage_per_second = 1 + }) + +end + + diff --git a/mods/governing/anticracker.lua b/mods/governing/anticracker.lua new file mode 100644 index 0000000..dd3e927 --- /dev/null +++ b/mods/governing/anticracker.lua @@ -0,0 +1,250 @@ +-- taken from https://github.com/S-S-X/dftest/blob/master/init.lua +local has_beerchat = minetest.get_modpath("beerchat") + +-- luacheck: push no max line length +local df = { + "dragonfire", -- many based clients by example teamclient + "f8fd5c11b", -- Merge pull request #59 from PrairieAstronomer/readme_irrlicht_change + "c66ae6717", -- Add exact irrlichtmt version to the clone command + "296cce39d", -- Fix upstream merge issues + "350b6d175", -- Install lua_async dependency + "393c83928", -- Don't include client/game.h on server build + "ccd4c504d", -- Ship dragonfireclient with selected high-quality mods + "147aaf326", -- Fix build instructions + "b09fc5de5", -- Add spider + "d404517d2", -- Make LuaVoxelManipulator available to CSM API + "1ccf88e80", -- minetest.dig_node: Remove node + "950d2c9b3", -- Add ClientObjectRef:remove and return true in on_object_add callback to remove newly added object + "fb4815c66", -- Merge pull request #35 from arydevy/patch-1 + "f12288814", -- Merge pull request #42 from Minetest-j45/master + "f3082146c", -- remove irrlicht from lid dir (accident) + "a3925db22", -- add airjump and remove unused headers + "7824a4956", -- Merge pull request #1 from EliasFleckenstein03/master + "35445d24f", -- Make set_pitch and set_yaw more accurate by not rounding it to integers + "5131675a6", -- Add guards to stop server build fail + "96a37aed3", -- Add minetest.get_send_speed + "d08242316", -- Fix format + "ce0d81a82", -- Change default cheat menu entry height + "b7abc8df2", -- Add on_object_add callback + "4f613bbf5", -- Include tile definitions in get_node_def; Client-side minetest.object_refs table + "c86dcd0f6", -- Add on_object_hp_change callback and nametag images + "b84ed7d0b", -- Call on_object_properties_change callback when adding object to scene + "26cfbda65", -- Add on_object_properties_change callback + "6dc7a65d9", -- Add ClientObjectRef:set_properties + "7d7d4d675", -- Add ClientObjectRef.get_properties + "ea8fa30b6", -- Changed README.md to fit the dragonfire client + "c47eae316", -- Add table.combine to luacheckrc + "83d09ffaf", -- Complete documentation + "e0b4859e7", -- Add ClientObjectRef:remove + "63f7c96ec", -- Fix legit_speed + "5c06763e8", -- Add noise to client CSM API + "7613d9bfe", -- Update .wielded command to output the entire itemstring; add LocalPlayer:get_hotbar_size + "bc79c2344", -- CSM: Use server-like (and safe) HTTP API instead of Mainmenu-like + "166968232", -- Port formspec API from waspsaliva This API is inofficial and undocumented; invalid usage causes the game to crash. Use at own risk! + "e391ee435", -- Forcefully place items when minetest.place_node is used + "546ab256b", -- Update buildbot to new MineClone2 repo and set the game name to MineClone2 rather than mineclone2 + "d3780cefd", -- Attempt to fix SEGFAULT in push_inventory + "d1c84ada2", -- Merge minetest changes + "74f5f033e", -- Add Custom version string + "b2f629d8d", -- Logo improvements + "78b7d1019", -- Add dragonfire logo + "19e0528e3", -- Add minetest.get_nearby_objects + "47d0882cc", -- Fix line containing only whitespace + "4fedc3a31", -- Add minetest.interact + "dc67f669e", -- Make the Cheat Menu size configureable + "906845a87", -- Add minetest.registered_items and minetest.registered_nodes (Doesn't do anything yet) + "3a4325902", -- Fixed crash by adding legacy stuff to defaultsettings (for now) + "53c991c5f", -- Fixed crash due to missing entry in defaultsettings.cpp + "0c6e0c717", -- Reorganize categories + "e8faa2afb", -- Rework Range + "a4d914ba2", -- Make GitHub Actions Happy try 3 + "a34c61093", -- Make GitHub Actions Happy try 2 + "f783f5939", -- Make GitHub Actions Happy try 1 + "8b58465aa", -- Remove obsolete code from clientenvironment + "35c15567a", -- Update builtin/settingtypes.txt to the new philosophy + "0c9e7466e", -- New Cheat Philosophy + "a1e61e561", -- World Cheats improvements; Add BlockLava; Readd minetest.request_http_api for Compatibility + "56d536ea5", -- Update CheatDB URL again + "ce47003cc", -- Update defaults for ContentDB (->CheatDB) + "89995efee", -- CheatDB Support & Enable/Disable CSMs in Main Menu + "3df23e23c", -- Small AutoTool Fix + "8b3eaf5b0", -- Lua API: Particle callbacks; Add NoWeather + "0a285dd33", -- Remove NextItem + "4695222bc", -- Fix and Improve AutoTool + "5bead7daa", -- Added minetest.close_formspec + "f825cf0e3", -- Fixed Minimap position + "eaa8a5132", -- Fixed FastPlace and AutoPlace + "b4e475726", -- Added configureable Colors for PlayerESP and EntityESP + "549025f6a", -- EntityESP, EntityTracers, PlayerESP, PlayerTracers + "eb6aca8b4", -- Merged Minetest + "8de51dae9", -- Fixed crash when attempting to access nonexistant inventory from Lua API + "a65251a7a", -- Fixed glowing GenericCAOs being rendered completely back when Fullbright is enabled + "eaec3645b", -- Added ClientObjectRef:get_hp() + "fb4d54ee3", -- Added minetest.register_on_play_sound + "50629cc6a", -- Improved Scaffold + "3d74e17cc", -- Added AutoSlip (-> Credit to Code-Sploit) + "f9c632466", -- Added JetPack and AutoHit (-> Credits to Code-Sploit and cora) + "843239c0b", -- Added Speed/Jump/Gravity Override + "598e9bdbc", -- Update Credits + "7d327def8", -- Improved AutoSneak + "82216e147", -- LocalPlayer:set_physics_override; minetest.register_on_recieve_physics_override + "4dd5ecfc5", -- Added setpitch & setyaw commands; AutoSprint + "b65db98bd", -- Added OnlyTracePlayers + "e16bbc1fb", -- Merge pull request #14 from corarona/master + "1780adeea", -- lua-api: fix get/set_pitch + "3e7c5d720", -- Possibility to use cheat menu while pressing other keys + "0aa63aafc", -- Fixed warning + "9db80fc6f", -- Run Lint Script + "91ad0d049", -- Merge pull request #10 from corarona/master + "6bda686c0", -- MapBlockMesh Performance Improvement + "1bab49049", -- add LUA_FCT + "6efa8a758", -- add g/s pitch and make_screenshot in lua api + "46237330d", -- Several Enhancements + "60a9ff6ff", -- api-screenshot: change function name to make_screenshot + "1f56317d5", -- Added NodeESP + "75ecaa217", -- Fix and run the Lint autocorrect script + "6ccb5835f", -- Revert "Make Lint Happy" + "244713971", -- Added script that automaticall corrects lint style + "07e61e115", -- Fix github build problems #3 + "3af10766f", -- Fix github build problems #2 + "16d302c9a", -- Fix github build problems + "ad148587d", -- Make Lint Happy + "1145b05ea", -- Updated Credits + "c9221730d", -- Updated Cheat Menu Color Design + "1799d5aa9", -- Cheat Menu Improvements Change + "fba7dc216", -- Merge pull request #8 from realOneplustwo/master + "a7dc1135e", -- Added CheatHUD + "f1d9ac014", -- Moved Killaura to Lua; Added ForceField; Added Friendlist; Added ClientObjectRef:is_local_player(); Documented LocalPlayer:get_object() + "06b72069d", -- Fixed ColorChat + "62958bd60", -- Reverted accidental commit in wrong repo + "00d51fbd5", -- Armor textures support + "7cbe42b1d", -- Re-Added Chat Effects + "28f6a7970", -- lua api: add set/get_pitch + "4f9797b6e", -- lua api: add core.take_screenshot() + "8e9e76a50", -- Revert "Add Block Formspec Hack" + "6652d7ac2", -- Add Block Formspec Hack + "8bc7d49b3", -- Added Nuke + "62cf9b466", -- Fix compile error + "519f98c65", -- Merge pull request #3 from JosiahWI/ui_revamp + "f236476af", -- Fix errors in cheatMenu. + "7af3dee31", -- Merge pull request #2 from JosiahWI/ui_revamp + "ea88dde4b", -- Added Strip, AutoRefill, indexing for InventoryActions and Wield Index starts at 1 now + "7aff09ab2", -- Fix overindent! + "aea9b36ef", -- Improved Colours + "1ef72ad9c", -- Fix indentation style. + "586241008", -- Add missing return. + "b211e90ff", -- Prepare cheatMenu::draw function for easier UI changes. + "e22e334e9", -- Merge pull request #1 from JosiahWI/ui_revamp + "f605308ee", -- Improve drawEntry. + "130d476f6", -- Changed Cheat Menu UI + "f1ff05bf5", -- Added ThroughWalls, InventoryActions API and AutoTotem + "1a7d3d818", -- Extended ClientObjectRef; Improved CrystalPvP + "1e4f35492", -- This is the last try for lint... + "7e0f8fba0", -- Another Lint commit + "151e5782e", -- Lint is still not happy... + "28a560684", -- Added the API additions from waspsaliva + "c1aea404b", -- Lint is bitch + "3a718f12b", -- Make lint happy; Remove stupid redirector + "3b596a96e", -- Fixed Github build problems + "847198edb", -- Edited .gitignore properly; fixed armor invulnarability in the server code. + "bbcd24954", -- New Mod System + "80f416d51", -- Added AttachmentFloat + "cb1915efa", -- Added minetest.drop_selected_item(), Improved AutoEject + "43ee069db", -- Improved X-Ray, added AutoEject + "faa32610e", -- Added ESP, fixed Tracers, improved Jesus + "ee88f4b94", -- Improved Tracers + "c36ff3edb", -- Added AutoSneak and improved X-Ray MapBlock updating + "0a2c90f4c", -- Only draw tracers to objects that are not attached (that fixes tracers to armor) + "044a12666", -- Added Tracers, NoSlow and NoForceRotate; GUI Colors changed + "b9f8f0a23", -- The Robot Update + "af085acbd", -- Added Schematicas + "0730ed216", -- Delete my stupid test mod lol + "772c9629e", -- Unrestricted HTTP API for Client, Server and Main Menu + "9b1030cac", -- Added minetest.get_inventory(location) + "2321e3da4", -- Removed console output spammed by minetest.find_node_near + "90f66dad8", -- Removed experimental code + "8b4d27141", -- Fixed typo in clientmods/inventory/mod.conf + "d8b8c1d31", -- Added Documentation for Additional API + "6e6c68ba0", -- Added Chat Spam, Replace and settingtypes.txt for Clientmods + "79d0314d7", -- Update Buildbots + "770bde9c6", -- idk + "e245151c5", -- Improved World hacks + "19205f6b3", -- Improved World Hacks, added API functions + "73b89703f", -- Improved World hacks, added fill + "248dedaba", -- Added floationg water to BlockWater + "9dc3eb777", -- Fixed broken Chatcommands + "80371bc16", -- Added .listwarps + "1c29f21e0", -- Imporoved set_wield_index() to include camera update + "3bed0981d", -- UI Update; Added AutoTool + "622d54726", -- Added DestroyWater (:P anon) + "9019e18b9", -- Some Updates + "107dec6c0", -- Added Coords + "f1760622e", -- Added BrightNight + "2675bcca1", -- Added more cheats + "3d980cf57", -- Improved Xray and Fullbright + "f7a042223", -- Added cheat Menu + "344fddc17", -- Improved Killaura and Chat position + "678559bb6", -- removed leagcy clientmods + "9194165cf", -- Added autodig, moved chat + "064c25caa", -- Added EntitySpeed + "5a8610c2f", -- Added customizable keybindings, improved freecam, added special inventory keybind (by default ender inventory) + "83f59484d", -- Fixed 5.4.0-dev build + "ffe3c2ae0", -- Update to minetest 5.4.0-dev + "45aa2516b", -- Added settings + "f22339ed8", -- Removed fast killaura + "408e39a1d", -- Added Anti Knockback + "eee0f960b", -- Removed minetest.conf.old + "39d7567c1", -- Fixed Crash + "305e0e0d3", -- Auto disable smooth lighting when fullbright is active + "6796baec6", -- Defaultsettings + "5a2bf6634", -- Added Clientmods + "e610149c0", -- Initial Commit + "68f9263a2", -- Hacked Client + "90d885506", -- GalwayGirl Client +} + +--[[ +To update commit list: save commit logs for master branches of minetest in mt.log and dragonfire in df.log +For example (assuming you have added dragonfire remote, adapt if not): +$ git log --oneline origin/master > mt.log; git log --oneline dragonfire/master > df.log + +Find and drop commits that seems to exist in both remotes, print rest of it: +$ sort -k3 <(awk '{print NR" "$0}' df.log mt.log mt.log) | uniq -uf2 | sort -nk1 | sed -r 's/^[^ ]+ ([^ ]+) (.*)$/\t"\1", -- \2/' + +Replace above entries with output +--]] +-- luacheck: pop + +local function dfver(s) + -- loop into table of commmits and find the compared version + for _,v in ipairs(df) do + if string.find(v) then + return v + end + end +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + local info = minetest.get_player_information(name) + local version = info.version_string + + if not version then + -- version not available + return + end + + local dfv = dfver(version) + if dfv then + local msg = "Unsupported client detected: " .. dfv .. " player: " .. name + minetest.log("action", "[beowulf] " .. msg) + if has_beerchat then + beerchat.send_on_channel("DF-Detect", beerchat.moderator_channel_name, msg) + end + +-- if minetest.settings:get_bool("beowulf.dfdetect.enable_kick", false) then +-- minetest.kick_player(name, "Unsupported client") +-- end + end + +end) diff --git a/mods/governing/antispawn.lua b/mods/governing/antispawn.lua new file mode 100644 index 0000000..473c4ff --- /dev/null +++ b/mods/governing/antispawn.lua @@ -0,0 +1,65 @@ +local PLAYERS_MSG = {} +local PLAYERS_FREQ = {} +local SPAM_SPEED = 5 +local SPAM_SPEED_MSECS = SPAM_SPEED * 1e6 +local SPAM_WARN = 5 +-- In seconds +local SPAM_KICK = SPAM_WARN + 5 +local RESET_TIME = 30 +-- Convert to microsecs +local RESET_TIME_MSECS = RESET_TIME * 1e6 +local WARNING_COLOR = minetest.get_color_escape_sequence"#FFBB33" +minetest.register_on_leaveplayer(function(player) + PLAYERS_MSG[player:get_player_name()] = nil + PLAYERS_FREQ[player:get_player_name()] = nil +end) +minetest.register_on_joinplayer(function(player) + PLAYERS_MSG[player:get_player_name()] = {} +end) +minetest.register_on_chat_message(function(name, message) + for msg, info in pairs(PLAYERS_MSG[name]) do + if minetest.get_us_time() - info[2] >= RESET_TIME_MSECS then PLAYERS_MSG[name][msg] = nil end + end + if PLAYERS_MSG[name][message] then + local amount = PLAYERS_MSG[name][message][1] + 1 + PLAYERS_MSG[name][message][1] = amount + PLAYERS_MSG[name][message][2] = minetest.get_us_time() + if amount >= SPAM_KICK then minetest.kick_player(name, "Kicked for spamming.") + elseif amount >= SPAM_WARN then + minetest.chat_send_player(name, WARNING_COLOR .. "Warning! You've sent the message '" .. message .. "' too often. Wait at least " .. RESET_TIME .. " seconds before sending it again.") + end + else PLAYERS_MSG[name][message] = { 1, minetest.get_us_time() } end + if not PLAYERS_FREQ[name] then + PLAYERS_FREQ[name] = { + 0, + 0, + minetest.get_us_time(), + 0 + } + return + end + local warns = PLAYERS_FREQ[name][4] + local amount = PLAYERS_FREQ[name][2] + local speed = PLAYERS_FREQ[name][1] + local delay = minetest.get_us_time() - PLAYERS_FREQ[name][3] + speed = (speed * amount + delay) / (amount + 1) + if amount >= SPAM_WARN then + if warns + 1 == SPAM_KICK - SPAM_WARN then minetest.kick_player(name, "Kicked for spamming.") + elseif speed <= SPAM_SPEED_MSECS then + minetest.chat_send_player(name, WARNING_COLOR .. "Warning! You are sending messages too fast. Wait at least " .. SPAM_SPEED .. " seconds before sending another message.") + warns = warns + 1 + speed = SPAM_SPEED_MSECS + amount = SPAM_WARN + else + speed = 0 + amount = 0 + warns = 0 + end + end + PLAYERS_FREQ[name] = { + speed, + amount + 1, + minetest.get_us_time(), + warns + } +end) diff --git a/mods/governing/commands.lua b/mods/governing/commands.lua new file mode 100644 index 0000000..40970f8 --- /dev/null +++ b/mods/governing/commands.lua @@ -0,0 +1,144 @@ +-- mod governor by mckaygerhard - commands module +-- Copyright 2020 + +---------------------------------------------------------------------------- +-- this program can be used free but cannot be used commertially or +-- modified for, licenced CC-BY-SA-NC 4.0 unless explicit permission + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +---------------------------------------------------------------------------- + + + + + +--[[ commands for killme implementation no matter of those mods ]] + +if not governing.modkillme and not governing.modcommand then + minetest.register_chatcommand("killme", { + description = "Kill player or yourselft to respawn", + func = function(name) + local player = minetest.get_player_by_name(name) + if player then + if minetest.settings:get_bool("enable_damage") and player:is_player() then + player:set_hp(0) + return true + else + for _, callback in pairs(minetest.registered_on_respawnplayers) do + if callback(player) then + return true + end + end + -- There doesn't seem to be a way to get a default spawn pos from the lua API + return false, "No static_spawnpoint defined" + end + else + -- Show error message if used when not logged in, eg: from IRC mod + return false, "You need to be online to be killed!" + end + end + }) +end + +--[[ end of commands for killme implementation no matter of those mods ]] + + + + + + +-- ----------------------------------------------------------------------------------------- + +--[[ commands for geoip and ip location information ]] + +if not governing.modgeoip then + minetest.register_chatcommand("geoip", { + params = "", + privs = {geoip=true}, + description = "Does a geoip lookup on the given player for governing", + func = function(name, param) + + if not param then return true, "usage: /geoip " end + if not minetest.get_player_ip then return true, "[geoip]: engine its too older, canot get ip of player." end + + local ip = minetest.get_player_ip(param) + if not ip then return true, "[geoip] no ip available! seems "..param.." does not provide such info!" end + + governing.lookup(ip, function(result) + local txt = format_result_geoip(result) + if not txt then return true, "[geoip]: "..param..":"..ip" error: "..(result.description or "unknown error") end + minetest.log("action", "[geoip] "..param..": "..txt) + minetest.chat_send_player(name, param..": "..txt) + end) + + end + }) +end + +minetest.register_chatcommand("govip", { + params = "", + privs = {governing=true}, + description = "Governing geoip lookup + net detection details on the given player", + func = function(name, param) + if not param then return true, "usage: /govip " end + if not minetest.get_player_ip then return true, "[governing]: engine its too older, canot get ip of player." end + local ip = minetest.get_player_ip(param) + if not ip then return true, "[governing] no ip available! seems "..param.." does not provide such info!" end + governing.checkip(ip, function(result) + local txt = format_result_checkip(result) + if not txt then return true, "[governing]: "..param..":"..ip" error: "..(result.description or "unknown error") end + minetest.log("action", "[governing] "..param..": "..txt) + minetest.chat_send_player(name, param..": "..txt) + end) + end +}) + +--[[ end of commands for geoip and ip location information ]] + + +--[[ commands for stamina or satiation based on existing mods ]] + +if not governing.modhbhunger then + if governing.modhudbars and not hb.redo then + minetest.register_chatcommand("satiation", { + privs = {["server"]=true}, + params = S("[] "), + description = S("Set satiation of player or yourself"), + func = function(name, param) + if minetest.settings:get_bool("enable_damage") == false then + return false, S("Not possible, damage is disabled.") + end + local targetname, satiation = string.match(param, "(%S+) (%S+)") + if not targetname then + satiation = param + end + satiation = tonumber(satiation) + if not satiation then + return false, S("Invalid satiation!") + end + if not targetname then + targetname = name + end + local target = minetest.get_player_by_name(targetname) + if target == nil then + return false, S("Player @1 does not exist.", targetname) + end + if satiation > hbhunger.SAT_MAX then + satiation = hbhunger.SAT_MAX + elseif satiation < 0 then + satiation = 0 + end + hbhunger.hunger[targetname] = satiation + hbhunger.set_hunger_raw(target) + return true + end, + }) + end +end + +--[[ end commands for stamina or satiation based on existing mods ]] + + diff --git a/mods/governing/depends.txt b/mods/governing/depends.txt new file mode 100644 index 0000000..afa6bd8 --- /dev/null +++ b/mods/governing/depends.txt @@ -0,0 +1,4 @@ +default? +mail? +boneworld? +hudbars? \ No newline at end of file diff --git a/mods/governing/geoip.lua b/mods/governing/geoip.lua new file mode 100644 index 0000000..d982fc1 --- /dev/null +++ b/mods/governing/geoip.lua @@ -0,0 +1,145 @@ +-- mod governor by mckaygerhard, geoip specific code +-- Copyright 2023 + +---------------------------------------------------------------------------- +-- this program can be used free but cannot be used commertially or +-- modified for, licenced CC-BY-SA-NC 4.0 unless explicit permission + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +---------------------------------------------------------------------------- + + +function format_result_geoip(result) + local txt = " Place: " + if result then + if result.status == "success" and result.data and result.data.geo then + if result.data.geo.ip then + if result.data.geo.ip == "127.0.0.1" then return txt .. " seems localhost " ..".. <_< ." end + end + if result.data.geo.continent_name then + if result.data.geo.continent_name ~= "" then txt = txt .. result.data.geo.continent_name .."," end + end + if result.data.geo.country_name then + if result.data.geo.country_name ~= "" then txt = txt .. result.data.geo.country_name .."," end + end + if result.data.geo.region_name then + if result.data.geo.region_name ~= "" then txt = txt .. result.data.geo.region_name .. "," end + end + if result.data.geo.city then + if result.data.geo.city ~= "" then txt = txt .. result.data.geo.city .."" end + end + if result.data.geo.timezone then + if result.data.geo.timezone ~= "" then txt = txt .. " Timezone: " .. result.data.geo.timezone end + end + if result.data.geo.asn then + if result.data.geo.asn ~= "" then txt = txt .. " ASN: " .. result.data.geo.asn end + end + if result.data.geo.isp then + if result.data.geo.isp ~= "" then txt = txt .. " ISP: " .. result.data.geo.isp end + end + if result.data.geo.ip then + if result.data.geo.ip ~= "" then txt = txt .. " IP: " .. result.data.geo.ip end + end + return txt + else + return false + end + else + return false + end +end + +function format_result_checkip(result) + local txt = " Place: " + local flg = "" + if result then + if result.message then + return result.message .. ".. <_< . if no key, use /geoip command" + end + if result.security then + if result.security.vpn then + if result.security.vpn ~= "true" then flg = flg .. "+VPN" end + end + if result.security.proxy then + if result.security.proxy ~= "true" then flg = flg .. "+PRX" end + end + if result.security.tor then + if result.security.tor ~= "true" then flg = flg .. "+TOR" end + end + if result.security.relay then + if result.security.tor ~= "true" then flg = flg .. "+REL" end + end + end + if result.location then + if result.location then + if result.location.continent ~= "" then txt = txt .. result.location.continent_name .."," end + end + if result.location.country then + if result.location.country ~= "" then txt = txt .. result.location.country .."," end + end + if result.location.region then + if result.location.region ~= "" then txt = txt .. result.location.region .. "," end + end + if result.location.city then + if result.location.city ~= "" then txt = txt .. result.location.city .." " end + end + if result.location.time_zone then + if result.location.time_zone ~= "" then txt = txt .. "Timezone: " .. result.location.time_zone end + end + end + if result.network then + if result.network.autonomous_system_number then + if result.network.autonomous_system_number ~= "" then txt = txt .. " ASN: " .. result.network.autonomous_system_number end + end + if result.network.autonomous_system_organization then + if result.network.autonomous_system_organization ~= "" then txt = txt .. " ISP: " .. result.network.autonomous_system_organization end + end + end + if result.ip then + if result.ip ~= "" then txt = txt .. " IP: " .. result.ip end + end + return flg .. txt + else + return false + end +end + + +governing.joinplayer_callback = function() end -- function(name, result) + + +--[[ init of call back on join of a player, ]] +minetest.register_on_joinplayer(function(player) -- query ip on join, record in logs and execute callback + if not player then return end + if not player:is_player() then return end + if not minetest.get_player_ip then return end + local name = player:get_player_name() + local ip = minetest.get_player_ip(name) + if not ip then return end + -- do log ip check: if not apikey then geoip from mod; if not mod then our own geoip + if governing.checkapikey ~= "" then + governing.checkip(ip, function(data) -- log, but TODO: record in storage log file + local txt = format_result_checkip(data) + if txt then minetest.log("warning", "[goberning/geoip] joined player, " .. name .. ":" .. ip .. "," .. txt) + else minetest.log("error", "[goberning/geoip] joined player, " .. name .. ":" .. ip .. ", seems fails") + end + governing.joinplayer_callback(name, data) -- execute callback + end) + else + if not governing.modgeoip then + governing.lookup(ip, function(data) -- log, but TODO: record in storage log file + local txt = format_result_checkip(data) + if txt then minetest.log("warning", "[goberning/geoip] joined player, " .. name .. ":" .. ip .. "," .. txt) + else minetest.log("error", "[goberning/geoip] joined player, " .. name .. ":" .. ip .. ", seems fails") + end + governing.joinplayer_callback(name, data) -- execute callback + end) + end + end +end) +--[[ end of call back on join of a player, ]] + + diff --git a/mods/governing/governing.png b/mods/governing/governing.png new file mode 100644 index 0000000000000000000000000000000000000000..434395468beb947393d342e17193605592024017 GIT binary patch literal 970 zcmV;*12z1KP)EX>4Tx04R}tkv&MmKpe$i(`rR34i*t{$WR5rf~bh2R-p(LO0CeUgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwR~IKm7b)?7NufoI2gm(*ckglc4iM^Prka6qK-DZG z6_1IT?5Y@iMJM_Zz$iqCnfhEZnSkf`x`&UicTt|@eeTcEqvT8m_(bAarW+RV2J!T! zrE}gV4zr@95T6r|8FWG7N3P2*zi}=&Ebz>*kxtDMhl#~P8_R9XiiS!&MI2F7jq-(z z%L?Z$&T6^Jn)l={4CSmKj!YVYmeGtK^f0C*2_sa7abLjV8(24YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2j>PB1Ti;6PIedo000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0004@NklVQlL~;tUoZk_4dBsGkN3$uz ziy+M!Le>O964OeOB{}fKv?$1epcKSJgjbP?FtWTW!bOgF+Dkblo2REQ*S%wab+uAN zbs&%fnS5JA>%YtQCSpa+B}Y7OF`dJg>!|TSQI&G^@}pIgropoc!znsn&w+Bu(xUft z%a@v!R*~%!@jZ^2YKTmcW4spGf9H%oFHO0gMllf+amwVIjhu2eG$J3vJfLTZ=~06x zsb`gHa-p+xjR!fa$ksxZnWslAn<7=D*78SFPpe(#Uabz~TiB+a#v-ccolQ`)5>l@d z=0VFv_6S=FT2hQq&fZ-WjhHH;2$f3F)Pj=dl%(vFlVXGSbGv>2-sLN_Dp~a{nUq*X zbg_)nPv4NqT0BS@RhB)89A1??dJvDsvqY%{@to)XrhQkcB5LV~^bc;M$a(!w8Fg6X sWNdME$*=;*wz41yf*=TjAc#D80CCfSYoGbQv;Y7A07*qoM6N<$f|5V1IsgCw literal 0 HcmV?d00001 diff --git a/mods/governing/init.lua b/mods/governing/init.lua new file mode 100644 index 0000000..6b534b4 --- /dev/null +++ b/mods/governing/init.lua @@ -0,0 +1,202 @@ +-- mod governor by mckaygerhard +-- Copyright 2020 + +---------------------------------------------------------------------------- +-- this program can be used free but cannot be used commertially or +-- modified for, licenced CC-BY-SA-NC 4.0 + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +---------------------------------------------------------------------------- + + +--[[ init - initialization of variables ]] + +local modname = "governing" -- name of the mod , need to be used later in namespace mod variable +local modpath = minetest.get_modpath("governing") -- path of the mod +local modstor = minetest.get_mod_storage() -- request of storage for the mod, if valid, otherwise false/nil +local worlddir = minetest.get_worldpath() -- path of the world were the mod is running, otherwise false/nil +local modmail = minetest.get_modpath("mail") -- path of the mail mod if available for sending messages internaly on private, otherwise false/nil +local modgeoip = minetest.get_modpath("geoip") -- if available, their commands wil be used, otherwise we provided +local moddefault = minetest.get_modpath("default") -- path of default mod if available, otherwise false/nil +local modkillme = minetest.get_modpath("killme") -- if killme is present as mod if available, otherwise we use own +local modcommand = minetest.get_modpath("game_commands") -- updated killme is present as mod if available, otherwise we use own +local modcreative = minetest.get_modpath("creative") -- if creative is available, otherwise false/nil +local modantispawn = minetest.get_modpath("antispam") -- if rnd1 anticheat mod is loaded, cos only wolrs with mt4 +local modanticheat = minetest.get_modpath("anticheat") -- if rnd1 anticheat mod is loaded, cos only wolrs with mt4 +local modbeowulf = minetest.get_modpath("beowulf") -- if rnd1 anticheat mod is loaded, cos only wolrs with mt4 +local modhudbars = minetest.get_modpath("hudbars") -- if the hudbars mod is loaded and working, from wuzzy +local modhbhunger = minetest.get_modpath("hbhunger") -- if the hudbars hunger mod is loaded and working, from wuzzy +local checkapikey = minetest.settings:get("governing.checkapikey") or "" -- need for geoip improved ip information, then geoip normal will be used + +local is_46 = minetest.has_feature("add_entity_with_staticdata") -- detect minetest engine 4.0.16 or mayor +local is_50 = minetest.has_feature("object_use_texture_alpha") -- detect mineitest engine more modern than 5.0.0 +local is_53 = minetest.has_feature("object_step_has_moveresult") -- detect mineitest engine more modern than 5.3.1 +local is_54 = minetest.has_feature("direct_velocity_on_players") -- detect mineitest engine more modern than 5.4.0 + +local httpapi = minetest.request_http_api and minetest.request_http_api() -- Only works at init time and must be called from the mod's main scope (not from a function). + +local creative_mode_cache = minetest.settings:get_bool("creative_mode") -- detection if game is running in main creative + +local S + +--[[ end - all local variables ]] + + + +--[[ init - translation boilerplace, currently some issues with intlib mod ]] + +if minetest.get_translator ~= nil then + S = minetest.get_translator(modname) -- 5.x translation function +else + if minetest.get_modpath("intllib") then + dofile(minetest.get_modpath("intllib") .. "/init.lua") + if intllib.make_gettext_pair then + gettext, ngettext = intllib.make_gettext_pair() -- new gettext method + else + gettext = intllib.Getter() -- old text file method + end + S = gettext + else -- boilerplate function + S = function(str, ...) + local args = {...} + return str:gsub("@%d+", function(match) + return args[tonumber(match:sub(2))] + end) + end + end +end + +--[[ end - translation boilerplace, currently some issues with intlib mod ]] + + + + +--[[ init - namespace of the mod and varible usages ]] + +governing = {} + +governing.is_46 = is_46 -- detect minetest engine 4.0.16 or mayor +governing.is_50 = is_50 -- detect mineitest engine more modern than 5.0.0 +governing.is_53 = is_53 -- detect mineitest engine more modern than 5.3.1 +governing.is_54 = is_54 -- detect mineitest engine more modern than 5.4.0 + +governing.S = S -- translations if available + +governing.httpapi = httpapi -- must be called early at the beggining to work +governing.modname = modname -- name of the mod +governing.modpath = modpath -- path of the mod +governing.modstor = modstor -- request of storage for the mod, otherwise false/nil +governing.worlddir = worlddir -- path of the world were the mod is running, otherwise false/nil +governing.modgeoip = modgeoip -- path of the geoip mod if available for sending messages internaly on private, otherwise false/nil +governing.modmail = modmail -- path of the mail mod if available for sending messages internaly on private, otherwise false/nil +governing.moddefault = moddefault -- path of default mod if available, otherwise false/nil +governing.modkillme = modkillme -- if killme is present as mod if available, otherwise we use own +governing.modcommand = modcommand -- if same killme and commands is present as mod if available, otherwise we use own +governing.modantispawn = modantispawn -- autodetect if older mod antispan by appguru are present +governing.modanticheat = modanticheat -- if rnd1 anticheat mod is present cos only works with mt4 +governing.modbeowulf = modbeowulf -- if beowulf anticheat mod is present cos only works with mt5 +governing.modhudbars = modhudbars -- if hudbars is present or the mproved hudbars redo +governing.modhbhunger = modhbhunger -- if hbhunger is present or the mproved hudbars redo +governing.checkapikey = checkapikey -- need for geoip improved ip information, then geoip normal will be used + +--[[ end - namespace of the mod and varible usages ]] + + + + +--[[ init privileges registrations ]] + +function governing.is_creative(name) + if creative then + return creative.is_creative(name) + else + return minetest.check_player_privs(name, {creative = true}) or creative_mode_cache + end +end + +minetest.register_privilege("governing", { + description = "can do geoip lookups on players for governing", + give_to_singleplayer = false +}) + +if not governing.modgeoip then + minetest.register_privilege("geoip", { + description = "governing: ip checks + lookups on players", + give_to_singleplayer = false + }) +end + +--[[ end privileges registrations ]] + + + +--[[ init http calls, must be only on main ]] + +function governing.lookup(ip, callback) + if not httpapi then + minetest.log("error", "[governing/geoip] mod not in the trusted http mods!") + return + end + httpapi.fetch( { + url = "https://tools.keycdn.com/geo.json?host=" .. ip, + extra_headers = { "User-Agent: keycdn-tools:https://minetest.org" }, + timeout = 5, + }, function(res) + if res.code == 200 then + local data = minetest.parse_json(res.data) + callback(data) + else + minetest.log("warning", "[governing/geoip] http request returned status: " .. res.code) + end + end) +end + +function governing.checkip(ip, callback) + if not httpapi then + minetest.log("error", "[governing] mod not in the trusted http mods!") + return + end + httpapi.fetch( { + url = "https://vpnapi.io/api/" .. ip .. "?key==" .. governing.checkapikey, + extra_headers = { "User-Agent: VenenuX-minenux:https://git.minetest.io/minenux" }, + timeout = 5, + }, function(res) + if res.code == 200 then + local data = minetest.parse_json(res.data) + callback(data) + else + minetest.log("warning", "[governing/ip] http request returned status: " .. res.code) + end + end) +end + +--[[ end http calls, must be only on main ]] + + + + + +--[[ include code files mod features ]] + +dofile(governing.modpath.."/geoip.lua") -- format the geoip responses managed by "callback(data)" + +dofile(governing.modpath.."/anticheats.lua") -- load anticheat mod that combined rnd + beowulf + fairplay + +dofile(governing.modpath.."/antispawn.lua") -- load antispawn chat features only if mod antispan is not loaded + +dofile(governing.modpath.."/commands.lua") -- must be at end. so relies on others functionalities + +--[[ end of include code files mod features ]] + + + + +--[[ log files and finished of mod loading ]] + +if governing.checkapikey == "" then minetest.log("warning", "[goberning] governing.checkapikey not set or empty, only basic geoip will work") end + +print("[MOD] governing mod loaded" ) + diff --git a/mods/governing/mod.conf b/mods/governing/mod.conf new file mode 100644 index 0000000..d8da15c --- /dev/null +++ b/mods/governing/mod.conf @@ -0,0 +1,2 @@ +name = governing +optional_depends = default, mail, boneworld, hudbars diff --git a/mods/governing/settingtypes.txt b/mods/governing/settingtypes.txt new file mode 100644 index 0000000..3a997a9 --- /dev/null +++ b/mods/governing/settingtypes.txt @@ -0,0 +1,4 @@ +governing.checkapikey (The string need for use the https://vpnapi.io/ ip informacion with geolocation) string +governing.timestep (How many time will run checks in seconds) int 15 10 300 +governing.timeagain (How many seconds checks again to compare if it is cheating the suspected player) int 120 10 300 +governing.moderators (Comma separated list of name players that will be not checked, without spaces) string