3 -- For a given position, returns a 2-tuple:
4 -- 1st return value: true if pos is in void
5 -- 2nd return value: true if it is in the deadly part of the void
6 function mcl_worlds
.is_in_void(pos
)
8 not ((pos
.y
< mcl_vars
.mg_overworld_max
and pos
.y
> mcl_vars
.mg_overworld_min
) or
9 (pos
.y
< mcl_vars
.mg_nether_max
and pos
.y
> mcl_vars
.mg_nether_min
) or
10 (pos
.y
< mcl_vars
.mg_end_max
and pos
.y
> mcl_vars
.mg_end_min
))
12 local void_deadly
= false
13 local deadly_tolerance
= 64 -- the player must be this many nodes “deep” into the void to be damaged
15 -- Overworld → Void → End → Void → Nether → Void
16 if pos
.y
< mcl_vars
.mg_overworld_min
and pos
.y
> mcl_vars
.mg_end_max
then
17 void_deadly
= pos
.y
< mcl_vars
.mg_overworld_min
- deadly_tolerance
18 elseif pos
.y
< mcl_vars
.mg_end_min
and pos
.y
> mcl_vars
.mg_nether_max
then
19 -- The void between End and Nether. Like usual, but here, the void
20 -- *above* the Nether also has a small tolerance area, so player
21 -- can fly above the Nether without getting hurt instantly.
22 void_deadly
= (pos
.y
< mcl_vars
.mg_end_min
- deadly_tolerance
) and (pos
.y
> mcl_vars
.mg_nether_max
+ deadly_tolerance
)
23 elseif pos
.y
< mcl_vars
.mg_nether_min
then
24 void_deadly
= pos
.y
< mcl_vars
.mg_nether_min
- deadly_tolerance
27 return void
, void_deadly
30 -- Takes an Y coordinate as input and returns:
31 -- 1) The corresponding Minecraft layer (can be nil if void)
32 -- 2) The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if it is in the void
33 -- If the Y coordinate is not located in any dimension, it will return:
35 function mcl_worlds
.y_to_layer(y
)
36 if y
>= mcl_vars
.mg_overworld_min
then
37 return y
- mcl_vars
.mg_overworld_min
, "overworld"
38 elseif y
>= mcl_vars
.mg_nether_min
and y
<= mcl_vars
.mg_nether_max
then
39 return y
- mcl_vars
.mg_nether_min
, "nether"
40 elseif y
>= mcl_vars
.mg_end_min
and y
<= mcl_vars
.mg_end_max
then
41 return y
- mcl_vars
.mg_end_min
, "end"
47 -- Takes a pos and returns the dimension it belongs to (same as above)
48 function mcl_worlds
.pos_to_dimension(pos
)
49 local _
, dim
= mcl_worlds
.y_to_layer(pos
.y
)
53 -- Takes a Minecraft layer and a “dimension” name
54 -- and returns the corresponding Y coordinate for
56 -- mc_dimension is one of "overworld", "nether", "end" (default: "overworld").
57 function mcl_worlds
.layer_to_y(layer
, mc_dimension
)
58 if mc_dimension
== "overworld" or mc_dimension
== nil then
59 return layer
+ mcl_vars
.mg_overworld_min
60 elseif mc_dimension
== "nether" then
61 return layer
+ mcl_vars
.mg_nether_min
62 elseif mc_dimension
== "end" then
63 return layer
+ mcl_vars
.mg_end_min
67 -- Takes a position and returns true if this position can have weather
68 function mcl_worlds
.has_weather(pos
)
69 -- Weather in the Overworld and the high part of the void below
70 return pos
.y
<= mcl_vars
.mg_overworld_max
and pos
.y
>= mcl_vars
.mg_overworld_min
- 64
73 -- Takes a position (pos) and returns true if compasses are working here
74 function mcl_worlds
.compass_works(pos
)
75 -- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below
76 local _
, dim
= mcl_worlds
.y_to_layer(pos
.y
)
77 if dim
== "nether" or dim
== "end" then
79 elseif dim
== "void" then
80 return pos
.y
<= mcl_vars
.mg_overworld_max
and pos
.y
>= mcl_vars
.mg_overworld_min
- 64
86 -- Takes a position (pos) and returns true if clocks are working here
87 mcl_worlds
.clock_works
= mcl_worlds
.compass_works
89 --------------- CALLBACKS ------------------
90 mcl_worlds
.registered_on_dimension_change
= {}
92 -- Register a callback function func(player, dimension).
93 -- It will be called whenever a player changes between dimensions.
94 -- The void counts as dimension.
95 -- * player: The player who changed the dimension
96 -- * dimension: The new dimension of the player ("overworld", "nether", "end", "void").
97 function mcl_worlds
.register_on_dimension_change(func
)
98 table.insert(mcl_worlds
.registered_on_dimension_change
, func
)
101 -- Playername-indexed table containig the name of the last known dimension the
103 local last_dimension
= {}
105 -- Notifies this mod about a dimension change of a player.
106 -- * player: Player who changed the dimension
107 -- * dimension: New dimension ("overworld", "nether", "end", "void")
108 function mcl_worlds
.dimension_change(player
, dimension
)
109 for i
=1, #mcl_worlds
.registered_on_dimension_change
do
110 mcl_worlds
.registered_on_dimension_change
[i
](player
, dimension
)
111 last_dimension
[player
:get_player_name()] = dimension
115 ----------------------- INTERNAL STUFF ----------------------
117 -- Update the dimension callbacks every DIM_UPDATE seconds
121 minetest
.register_on_joinplayer(function(player
)
122 last_dimension
[player
:get_player_name()] = mcl_worlds
.pos_to_dimension(player
:get_pos())
125 minetest
.register_globalstep(function(dtime
)
126 -- regular updates based on iterval
127 dimtimer
= dimtimer
+ dtime
;
128 if dimtimer
>= DIM_UPDATE
then
129 local players
= minetest
.get_connected_players()
131 local dim
= mcl_worlds
.pos_to_dimension(players
[p
]:get_pos())
132 local name
= players
[p
]:get_player_name()
133 if dim
~= last_dimension
[name
] then
134 mcl_worlds
.dimension_change(players
[p
], dim
)