Merge pull request 'Release 1.3 "Bugfix"' (#158) from compatibility into production-compatible

Reviewed-on: MineClone5/MineClone5#158
This commit is contained in:
kay27 2022-02-02 00:02:37 +00:00
commit 61c87c7e1a
7 changed files with 93 additions and 105 deletions

View File

@ -84,7 +84,7 @@ function image:encode()
end end
function image:save(filename) function image:save(filename)
local f = assert(io.open(filename, "w")) local f = assert(io.open(filename, "wb"))
f:write(self.data) f:write(self.data)
f:close() f:close()
end end

View File

@ -184,7 +184,7 @@ local function set_interact(player, interact)
local privs = minetest.get_player_privs(player_name) local privs = minetest.get_player_privs(player_name)
if privs.interact ~= interact then if privs.interact ~= interact then
local meta = player:get_meta() local meta = player:get_meta()
if meta:get_int("ineract_revoked") ~= 1 then if meta:get_int("interact_revoked") ~= 1 then
privs.interact = interact privs.interact = interact
minetest.set_player_privs(player_name, privs) minetest.set_player_privs(player_name, privs)
end end

View File

@ -1133,57 +1133,6 @@ if string.len(mg_flags_str) > 0 then
end end
minetest.set_mapgen_setting("mg_flags", mg_flags_str, true) minetest.set_mapgen_setting("mg_flags", mg_flags_str, true)
-- Takes an index of a biomemap table (from minetest.get_mapgen_object),
-- minp and maxp (from an on_generated callback) and returns the real world coordinates
-- as X, Z.
-- Inverse function of xz_to_biomemap
--[[local function biomemap_to_xz(index, minp, maxp)
local xwidth = maxp.x - minp.x + 1
local zwidth = maxp.z - minp.z + 1
local x = ((index-1) % xwidth) + minp.x
local z = ((index-1) / zwidth) + minp.z
return x, z
end]]
local dragon_spawn_pos = false
local dragon_spawned, portal_generated = false, false
local function spawn_ender_dragon()
local obj = minetest.add_entity(dragon_spawn_pos, "mobs_mc:enderdragon")
if not obj then return false end
local dragon_entity = obj:get_luaentity()
dragon_entity._initial = true
dragon_entity._portal_pos = pos
return obj
end
local function try_to_spawn_ender_dragon()
if spawn_ender_dragon() then
dragon_spawned = true
return
end
minetest.after(2, try_to_spawn_ender_dragon)
minetest.log("warning", "[mcl_mapgen_core] WARNING! Ender dragon doesn't want to spawn at "..minetest.pos_to_string(dragon_spawn_pos))
end
if portal_generated and not dragon_spawned then
minetest.after(10, try_to_spawn_ender_dragon)
end
function mcl_mapgen_core.generate_end_exit_portal(pos)
if dragon_spawn_pos then return false end
dragon_spawn_pos = vector.add(pos, vector.new(3, 11, 3))
mcl_structures.call_struct(pos, "end_exit_portal", nil, nil, function()
minetest.after(2, function()
minetest.emerge_area(vector.subtract(dragon_spawn_pos, {x = 64, y = 12, z = 5}), vector.add(dragon_spawn_pos, {x = 3, y = 3, z = 5}), function(blockpos, action, calls_remaining, param)
if calls_remaining > 0 then return end
minetest.after(2, try_to_spawn_ender_dragon)
end)
end)
end)
portal_generated = true
end
-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc. -- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
-- Also perform some basic node replacements. -- Also perform some basic node replacements.

View File

@ -12,6 +12,31 @@ local p0 = {
local schematic = modpath .. "/schematics/mcl_structures_end_exit_portal.mts" local schematic = modpath .. "/schematics/mcl_structures_end_exit_portal.mts"
local dragon_spawn_pos = false
local dragon_spawned, portal_generated = false, false
local function spawn_ender_dragon()
local obj = minetest.add_entity(dragon_spawn_pos, "mobs_mc:enderdragon")
if not obj then return false end
local dragon_entity = obj:get_luaentity()
dragon_entity._initial = true
dragon_entity._portal_pos = p0
return obj
end
local function try_to_spawn_ender_dragon()
if spawn_ender_dragon() then
dragon_spawned = true
return
end
minetest.after(2, try_to_spawn_ender_dragon)
minetest.log("warning", "Ender dragon doesn't want to spawn at "..minetest.pos_to_string(dragon_spawn_pos))
end
if portal_generated and not dragon_spawned then
minetest.after(10, try_to_spawn_ender_dragon)
end
local function place(pos, rotation, pr) local function place(pos, rotation, pr)
mcl_structures.place_schematic({pos = pos, schematic = schematic, rotation = rotation, pr = pr}) mcl_structures.place_schematic({pos = pos, schematic = schematic, rotation = rotation, pr = pr})
end end
@ -28,6 +53,10 @@ mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context)
if minp.z > END_EXIT_PORTAL_POS_Z then return end if minp.z > END_EXIT_PORTAL_POS_Z then return end
if maxp.z < END_EXIT_PORTAL_POS_Z then return end if maxp.z < END_EXIT_PORTAL_POS_Z then return end
dragon_spawn_pos = vector.add(p0, vector.new(3, 11, 3))
portal_generated = true
try_to_spawn_ender_dragon()
local p = table.copy(p0) local p = table.copy(p0)
for y = y2, y1, -1 do for y = y2, y1, -1 do

View File

@ -339,9 +339,7 @@ function mcl_structures.call_struct(pos, struct_style, rotation, pr, callback)
if not rotation then if not rotation then
rotation = "random" rotation = "random"
end end
if struct_style == "witch_hut" then if struct_style == "boulder" then
return mcl_structures.generate_witch_hut(pos, rotation)
elseif struct_style == "boulder" then
return mcl_structures.generate_boulder(pos, rotation, pr) return mcl_structures.generate_boulder(pos, rotation, pr)
elseif struct_style == "end_exit_portal" then elseif struct_style == "end_exit_portal" then
return mcl_structures.generate_end_exit_portal(pos, rotation, pr, callback) return mcl_structures.generate_end_exit_portal(pos, rotation, pr, callback)
@ -387,27 +385,6 @@ function mcl_structures.generate_boulder(pos, rotation, pr)
return minetest.place_schematic(newpos, path, rotation) -- don't serialize schematics for registered biome decorations, for MT 5.4.0, https://github.com/minetest/minetest/issues/10995 return minetest.place_schematic(newpos, path, rotation) -- don't serialize schematics for registered biome decorations, for MT 5.4.0, https://github.com/minetest/minetest/issues/10995
end end
local function hut_placement_callback(p1, p2, size, orientation, pr)
if not p1 or not p2 then return end
local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree")
for i = 1, #legs do
while minetest.get_item_group(mcl_mapgen.get_far_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
legs[i].y = legs[i].y - 1
minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2})
end
end
end
function mcl_structures.generate_witch_hut(pos, rotation, pr)
local path = modpath.."/schematics/mcl_structures_witch_hut.mts"
mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, hut_placement_callback, pr)
end
function mcl_structures.generate_ice_spike_large(pos, rotation)
local path = modpath.."/schematics/mcl_structures_ice_spike_large.mts"
return minetest.place_schematic(pos, path, rotation or "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0
end
function mcl_structures.generate_end_exit_portal(pos, rot, pr, callback) function mcl_structures.generate_end_exit_portal(pos, rot, pr, callback)
local path = modpath.."/schematics/mcl_structures_end_exit_portal.mts" local path = modpath.."/schematics/mcl_structures_end_exit_portal.mts"
return mcl_structures.place_schematic(pos, path, rot or "0", {["mcl_portals:portal_end"] = "air"}, true, nil, callback) return mcl_structures.place_schematic(pos, path, rot or "0", {["mcl_portals:portal_end"] = "air"}, true, nil, callback)

View File

@ -1,5 +1,6 @@
local flights_kick_threshold = 10 local enable_anticheat = true
local suffocations_kick_threshold = 1 local kick_cheaters = false
local kick_threshold = 10
local after = minetest.after local after = minetest.after
local get_connected_players = minetest.get_connected_players local get_connected_players = minetest.get_connected_players
@ -8,24 +9,34 @@ local get_objects_inside_radius = minetest.get_objects_inside_radius
local get_player_by_name = minetest.get_player_by_name local get_player_by_name = minetest.get_player_by_name
local kick_player = minetest.kick_player local kick_player = minetest.kick_player
local set_node = minetest.set_node local set_node = minetest.set_node
local find_nodes_in_area = minetest.find_nodes_in_area
local ceil = math.ceil local ceil = math.ceil
local floor = math.floor local floor = math.floor
local distance = vector.distance local distance = vector.distance
local window_size = 10 local window_size = 8
local detection_interval = 1.7 local detection_interval = 1.6
local step_seconds = detection_interval / window_size local step_seconds = detection_interval / window_size
local joined_players = {} local joined_players = {}
local function update_settings()
enable_anticheat = minetest.settings:get_bool("enable_anticheat", true)
kick_cheaters = minetest.settings:get_bool("kick_cheaters", false)
kick_threshold = tonumber(minetest.settings:get("kick_threshold") or 10)
minetest.after(10, update_settings)
end
update_settings()
local function update_player(player_object) local function update_player(player_object)
if not player_object then return end if not player_object then return end
local name = player_object:get_player_name() local name = player_object:get_player_name()
if not name then return end if not name then return end
local pos = player_object:get_pos() local pos = player_object:get_pos()
local x, y, z = floor(pos.x), floor(pos.y-0.1), floor(pos.z) local x, z = floor(pos.x), floor(pos.z)
local feet_y, head_y = floor(pos.y-0.1), floor(pos.y + 1.49)
if mcl_playerplus.elytra then if mcl_playerplus.elytra then
local elytra = mcl_playerplus.elytra[player_object] local elytra = mcl_playerplus.elytra[player_object]
@ -34,19 +45,16 @@ local function update_player(player_object)
end end
end end
local air = get_node({x = x , y = y , z = z }).name == "air" local air = #find_nodes_in_area({x = x, y = feet_y, z = z}, {x = x + 1, y = feet_y + 1, z = z + 1}, "air") == 8
and get_node({x = x , y = y , z = z + 1}).name == "air" and #get_objects_inside_radius({x = pos.x, y = pos.y - 0.6, z = pos.z}, 1.3) > 1
and get_node({x = x , y = y + 1, z = z }).name == "air"
and get_node({x = x , y = y + 1, z = z + 1}).name == "air" local noclip = #find_nodes_in_area({x = x, y = head_y, z = z}, {x = x + 1, y = head_y + 1, z = z + 1}, "group:opaque") == 8
and get_node({x = x + 1, y = y , z = z }).name == "air"
and get_node({x = x + 1, y = y , z = z + 1}).name == "air"
and get_node({x = x + 1, y = y + 1, z = z }).name == "air"
and get_node({x = x + 1, y = y + 1, z = z + 1}).name == "air"
local player_data = { local player_data = {
pos = pos, pos = pos,
velocity = player_object:get_velocity() or player_object:get_player_velocity(), velocity = player_object:get_velocity() or player_object:get_player_velocity(),
air = air air = air,
noclip = noclip,
} }
if joined_players[name] then if joined_players[name] then
@ -68,6 +76,7 @@ local function check_player(name)
if not data[0] then return end if not data[0] then return end
local always_air = true local always_air = true
local always_noclip = true
local falling = data[0].velocity.y < 0 local falling = data[0].velocity.y < 0
for i = 0, window_size - 1 do for i = 0, window_size - 1 do
local derivative = data[i] local derivative = data[i]
@ -76,6 +85,7 @@ local function check_player(name)
return return
end end
always_air = always_air and derivative.air always_air = always_air and derivative.air
always_noclip = always_noclip and derivative.noclip
falling = falling or derivative.velocity.y < 0 falling = falling or derivative.velocity.y < 0
end end
if always_air and not falling then if always_air and not falling then
@ -84,26 +94,39 @@ local function check_player(name)
data.flights = 1 data.flights = 1
else else
data.flights = data.flights + 1 data.flights = data.flights + 1
if data.flights >= flights_kick_threshold then end
kick_player(name, "flights") if kick_cheaters and kick_threshold and kick_threshold > 0 and data.flights >= kick_threshold then
end kick_player(name, "flights")
return
end end
local obj_player = minetest.get_player_by_name(name) local obj_player = minetest.get_player_by_name(name)
if not obj_player then if not obj_player then
kick_player(name, "flights") return
end end
local velocity = obj_player:get_velocity() or obj_player:get_player_velocity() local velocity = obj_player:get_velocity() or obj_player:get_player_velocity()
local pos = obj_player:get_pos() local pos = obj_player:get_pos()
local x, y, z = floor(pos.x), floor(pos.y), floor(pos.z) local x, y, z = floor(pos.x), floor(pos.y), floor(pos.z)
while ( get_node({x = x , y = y, z = z }).name == "air" while #find_nodes_in_area({x = x, y = y, z = z}, {x = x + 1, y = y, z = z + 1}, "air") == 4 do
and get_node({x = x , y = y, z = z + 1}).name == "air"
and get_node({x = x + 1, y = y, z = z }).name == "air"
and get_node({x = x + 1, y = y, z = z + 1}).name == "air"
) do
y = y - 1 y = y - 1
end end
obj_player:set_velocity({x = velocity.x, y = -10, z = velocity.z})
obj_player:set_pos({x = x, y = y + 0.5, z = z}) obj_player:set_pos({x = x, y = y + 0.5, z = z})
obj_player:set_velocity({x = 0, y = 0, z = 0})
obj_player:set_acceleration({x = 0, y = 0, z = 0})
end
if always_noclip then
-- noclip detected
local obj_player = minetest.get_player_by_name(name)
if not obj_player then
return
end
local pos = obj_player:get_pos()
local x, y, z = floor(pos.x), floor(pos.y+1.49), floor(pos.z)
while #find_nodes_in_area({x = x, y = y, z = z}, {x = x + 1, y = y + 1, z = z + 1}, "group:opaque") >= 7 do
y = y + 1
end
obj_player:set_pos({x = x, y = y + 0.5, z = z})
obj_player:set_velocity({x = 0, y = 0, z = 0})
obj_player:set_acceleration({x = 0, y = 0, z = 0})
end end
end end
@ -117,9 +140,11 @@ local function remove_player(player_object)
end end
local function step() local function step()
for _, player in pairs(get_connected_players()) do if enable_anticheat then
update_player(player) for _, player in pairs(get_connected_players()) do
check_player(player:get_player_name()) update_player(player)
check_player(player:get_player_name())
end
end end
after(step_seconds, step) after(step_seconds, step)
end end
@ -161,7 +186,7 @@ minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack
data.suffocations = data.suffocations + 1 data.suffocations = data.suffocations + 1
end end
end end
if data.suffocations >= suffocations_kick_threshold then if data.suffocations >= kick_threshold then
kick_player(name, "choker") kick_player(name, "choker")
end end
end) end)

View File

@ -157,6 +157,14 @@ fix_doubleplants (Mcimport double plant fixes) bool true
# Allow players to create Minecraft-like maps. # Allow players to create Minecraft-like maps.
enable_real_maps (Enable Real Maps) bool true enable_real_maps (Enable Real Maps) bool true
[Anticheat]
# Enable anticheats
enable_anticheat (Enable Anticheat) bool true
# Kick cheaters
kick_cheaters (Kick Cheaters) bool false
# Cheat kicking threshold
kick_threshold (Cheat Kicking Threshold) int 10
[Debugging] [Debugging]
# If enabled, this will show the itemstring of an item in the description. # If enabled, this will show the itemstring of an item in the description.
mcl_item_id_debug (Item ID Debug) bool false mcl_item_id_debug (Item ID Debug) bool false