Repository navigation
Expand file tree
/
Copy pathworldborder.lua
More file actions
117 lines (99 loc) · 3.76 KB
/
Copy pathworldborder.lua
File metadata and controls
117 lines (99 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
local world_border_radius = tonumber(minetest.settings:get("civmisc_world_border_radius"))
if not world_border_radius then
world_border_radius = 1000
minetest.log(
"warning",
"[CivMisc] No world border radius specified, defaulting to "
.. tonumber(world_border_radius) .. "."
)
else
minetest.log(
"[CivMisc] World border radius set to "
.. tonumber(world_border_radius) .. "."
)
end
local Y_LIMIT_MAX = 250
local Y_LIMIT_MIN = -250
local zerozero = vector.new(0, 0, 0)
local function position_in_world_border(pos)
local pos_no_y = vector.new(pos.x, 0, pos.z)
return vector.distance(pos_no_y, zerozero) < world_border_radius
end
local function get_closest_position_in_world_border(pos)
local pos_no_y = vector.new(pos.x, 0, pos.z)
local normalized = vector.normalize(pos_no_y)
local new_pos = vector.multiply(normalized, world_border_radius)
-- Preserve the player's y position
new_pos.y = pos.y
return new_pos
end
local function position_in_y_limits(pos)
local pos_y = pos.y
return Y_LIMIT_MIN < pos_y and pos_y < Y_LIMIT_MAX
end
local function get_closest_position_in_y_limits(pos)
local new_pos = pos
new_pos.y = math.max(math.min(pos.y, Y_LIMIT_MAX - 1), Y_LIMIT_MIN + 1)
return new_pos
end
local timer = 0
minetest.register_globalstep(function(dtime)
-- check player position every 500ms
timer = timer + dtime
if timer >= 0.5 then
for _,player in ipairs(minetest.get_connected_players()) do
local pname = player:get_player_name()
local ppos = player:get_pos()
if not position_in_world_border(ppos) then
minetest.chat_send_player(pname, "You're at the world border.")
local new_pos = get_closest_position_in_world_border(ppos)
player:set_pos(new_pos)
end
if ppos.y < Y_LIMIT_MIN then
minetest.chat_send_player(pname, "You exceeded the y-level limits.")
local new_pos = get_closest_position_in_y_limits(ppos)
player:set_pos(new_pos)
end
end
timer = 0
end
end)
-- Don't allow block modification outside of the border.
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name, action)
if not position_in_world_border(pos) then
minetest.chat_send_player(name, "You can't modify blocks beyond the border.")
return true
end
if not position_in_y_limits(pos) then
minetest.chat_send_player(name, "You can't modify blocks at this y-level.")
return true
end
return old_is_protected(pos, name, action)
end
local boats_loaded = minetest.get_modpath("boats")
if boats_loaded then
minetest.log("WorldBorder is aware of the 'boats' plugin.")
local function adjust_boat_position(boat, new_pos)
boat.object:set_pos(new_pos)
local velocity = boat.object:get_velocity()
local acceleration = boat.object:get_acceleration()
boat.object:set_velocity(vector.multiply(velocity, -1))
boat.object:set_acceleration(vector.multiply(acceleration, -1))
end
-- Stop boats from exceeding the world border
local old_boat_on_step = minetest.registered_entities["boats:boat"].on_step
minetest.registered_entities["boats:boat"].on_step = function(self, dtime, ...)
old_boat_on_step(self, dtime, ...)
local pos = self.object:get_pos()
if not position_in_world_border(pos) then
local new_pos = get_closest_position_in_world_border(pos)
adjust_boat_position(self, new_pos)
end
if not position_in_y_limits(pos) then
local new_pos = get_closest_position_in_y_limits(pos)
adjust_boat_position(self, new_pos)
end
end
end
minetest.debug("[CivMisc] WorldBorder initialised.")