2022-03-28 18:06:30 +02:00
--TODO: Add advancement
2021-05-29 16:12:33 +02:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2019-03-07 23:40:43 +01:00
2017-02-20 21:14:10 +01:00
mcl_compass = { }
2015-06-29 19:55:56 +02:00
2017-08-17 21:26:09 +02:00
local compass_frames = 32
2021-05-23 00:17:12 +02:00
--Not sure spawn point should be dymanic (is it in mc?)
--local default_spawn_settings = minetest.settings:get("static_spawnpoint")
2015-06-29 19:55:56 +02:00
2017-08-17 21:26:09 +02:00
-- Timer for random compass spinning
local random_timer = 0
2022-03-28 18:06:30 +02:00
local random_timer_trigger = 0.5 -- random compass spinning tick in seconds. Incr ease if there are performance problems
2017-08-17 21:26:09 +02:00
local random_frame = math.random ( 0 , compass_frames - 1 )
2022-03-28 18:06:30 +02:00
function mcl_compass . get_compass_image ( pos , dir , x , y , z )
2021-05-03 11:22:47 +02:00
-- Compasses do not work in certain zones
2022-03-28 18:06:30 +02:00
if mcl_worlds.compass_works ( pos ) and x ~= nil and y ~= nil and z ~= nil then
local _ , dim = mcl_worlds.y_to_layer ( y )
local _ , playerdim = mcl_worlds.y_to_layer ( pos.y )
if dim == playerdim then --Check if player and compass target are in the same dimension, above check is just if the diemension is valid for the non lodestone compass
local spawn = { x = x , y = y , z = z }
local ssp = minetest.setting_get_pos ( " static_spawnpoint " )
if ssp and x == 0 and y == 0 and z == 0 then
spawn = ssp
if type ( spawn ) ~= " table " or type ( spawn.x ) ~= " number " or type ( spawn.y ) ~= " number " or type ( spawn.z ) ~= " number " then
spawn = { x = 0 , y = 0 , z = 0 }
end
2021-05-03 11:22:47 +02:00
end
2022-03-28 18:06:30 +02:00
local angle_north = math.deg ( math.atan2 ( spawn.x - pos.x , spawn.z - pos.z ) )
if angle_north < 0 then angle_north = angle_north + 360 end
local angle_dir = - math.deg ( dir )
local angle_relative = ( angle_north - angle_dir + 180 ) % 360
return math.floor ( ( angle_relative / 11.25 ) + 0.5 ) % compass_frames
else
return random_frame
2021-05-03 11:22:47 +02:00
end
else
2022-03-28 18:06:30 +02:00
if x ~= 0 and y ~= 0 and z ~= 0 and x ~= nil and y ~= nil and x ~= nil then
local _ , dim = mcl_worlds.y_to_layer ( y )
local _ , playerdim = mcl_worlds.y_to_layer ( pos.y )
if dim == playerdim then --already explained that very same if statement above
local spawn = { x = x , y = y , z = z }
local ssp = minetest.setting_get_pos ( " static_spawnpoint " )
if ssp and x == 0 and y == 0 and z == 0 then
spawn = ssp
if type ( spawn ) ~= " table " or type ( spawn.x ) ~= " number " or type ( spawn.y ) ~= " number " or type ( spawn.z ) ~= " number " then
spawn = { x = 0 , y = 0 , z = 0 }
end
end
local angle_north = math.deg ( math.atan2 ( spawn.x - pos.x , spawn.z - pos.z ) )
if angle_north < 0 then angle_north = angle_north + 360 end
local angle_dir = - math.deg ( dir )
local angle_relative = ( angle_north - angle_dir + 180 ) % 360
return math.floor ( ( angle_relative / 11.25 ) + 0.5 ) % compass_frames
else
return random_frame
end
else
return random_frame
end
2021-05-03 11:22:47 +02:00
end
end
2015-06-29 19:55:56 +02:00
minetest.register_globalstep ( function ( dtime )
2017-08-17 21:26:09 +02:00
random_timer = random_timer + dtime
if random_timer >= random_timer_trigger then
random_frame = ( random_frame + math.random ( - 1 , 1 ) ) % compass_frames
random_timer = 0
end
2021-03-16 17:35:46 +01:00
for i , player in pairs ( minetest.get_connected_players ( ) ) do
2015-06-29 19:55:56 +02:00
local function has_compass ( player )
2021-03-16 17:35:46 +01:00
for _ , stack in pairs ( player : get_inventory ( ) : get_list ( " main " ) ) do
2015-06-29 19:55:56 +02:00
if minetest.get_item_group ( stack : get_name ( ) , " compass " ) ~= 0 then
return true
end
end
return false
end
if has_compass ( player ) then
2019-02-01 06:33:07 +01:00
local pos = player : get_pos ( )
2015-06-29 19:55:56 +02:00
2021-03-16 17:43:32 +01:00
for j , stack in pairs ( player : get_inventory ( ) : get_list ( " main " ) ) do
2022-03-28 18:06:30 +02:00
x = stack : get_meta ( ) : get_string ( " x " ) -- i know i could write the pos in meta, but i like this method more, and it is basicly the same, since else there would be one table with 3 values, and i have 3 values on their own
y = stack : get_meta ( ) : get_string ( " y " )
z = stack : get_meta ( ) : get_string ( " z " )
x = tonumber ( x )
y = tonumber ( y )
z = tonumber ( z )
if x == nil or y == nil or z == nil then --checking if the compass has lodestone meta
compass_image = mcl_compass.get_compass_image ( pos , player : get_look_horizontal ( ) , 0 , 0 , 0 ) --no lodestone meta
else
checkblock = { x = x , y = y , z = z }
local function get_far_node ( pos ) --function that tries to read node normally, and does it even if its unloaded https://dev.minetest.net/minetest.get_node
local node = minetest.get_node ( pos )
if node.name == " ignore " then
minetest.get_voxel_manip ( ) : read_from_map ( pos , pos )
node = minetest.get_node ( pos )
end
return node
end
if get_far_node ( checkblock ) . name == " mcl_compass:lodestone " then --check if lodestone still exists
compass_image = mcl_compass.get_compass_image ( pos , player : get_look_horizontal ( ) , x , y , z )
compass_image = compass_image .. " _lodestone "
else -- lodestone got destroyed
compass_image = random_frame .. " _lodestone "
end
end
2017-08-17 21:26:09 +02:00
if minetest.get_item_group ( stack : get_name ( ) , " compass " ) ~= 0 and
minetest.get_item_group ( stack : get_name ( ) , " compass " ) - 1 ~= compass_image then
2020-11-01 14:23:43 +01:00
local itemname = " mcl_compass: " .. compass_image
stack : set_name ( itemname )
player : get_inventory ( ) : set_stack ( " main " , j , stack )
2015-06-29 19:55:56 +02:00
end
end
end
end
end )
2017-01-09 02:03:09 +01:00
local images = { }
2017-08-17 21:26:09 +02:00
for frame = 0 , compass_frames - 1 do
2017-07-20 22:04:15 +02:00
local s = string.format ( " %02d " , frame )
table.insert ( images , " mcl_compass_compass_ " .. s .. " .png " )
2017-01-09 02:03:09 +01:00
end
2015-06-29 19:55:56 +02:00
2021-05-29 16:12:33 +02:00
local doc_mod = minetest.get_modpath ( " doc " )
2017-03-20 18:12:05 +01:00
2017-01-09 03:26:00 +01:00
local stereotype_frame = 18
2015-06-29 19:55:56 +02:00
for i , img in ipairs ( images ) do
local inv = 1
2017-01-09 03:26:00 +01:00
if i == stereotype_frame then
2015-06-29 19:55:56 +02:00
inv = 0
end
2021-05-23 00:17:12 +02:00
local use_doc , longdesc , tt
2022-03-28 18:06:30 +02:00
--Why is there no usage help? This should be fixed.
--local usagehelp
2017-03-20 18:12:05 +01:00
use_doc = i == stereotype_frame
if use_doc then
2020-02-19 04:54:17 +01:00
tt = S ( " Points to the world origin " )
2019-03-07 23:40:43 +01:00
longdesc = S ( " Compasses are tools which point to the world origin (X=0, Z=0) or the spawn point in the Overworld. " )
2017-03-02 21:55:25 +01:00
end
2017-03-20 18:12:05 +01:00
local itemstring = " mcl_compass: " .. ( i - 1 )
minetest.register_craftitem ( itemstring , {
2019-03-07 23:40:43 +01:00
description = S ( " Compass " ) ,
2020-02-19 04:54:17 +01:00
_tt_help = tt ,
2017-03-20 18:12:05 +01:00
_doc_items_create_entry = use_doc ,
2017-03-02 21:55:25 +01:00
_doc_items_longdesc = longdesc ,
2021-05-23 00:17:12 +02:00
--_doc_items_usagehelp = usagehelp,
2015-06-29 19:55:56 +02:00
inventory_image = img ,
wield_image = img ,
2017-02-08 16:59:34 +01:00
stack_max = 64 ,
2020-12-19 15:32:32 +01:00
groups = { not_in_creative_inventory = inv , compass = i , tool = 1 , disable_repair = 1 }
2015-06-29 19:55:56 +02:00
} )
2022-03-28 18:06:30 +02:00
minetest.register_craftitem ( itemstring .. " _lodestone " , {
description = S ( " Lodestone Compass " ) ,
_tt_help = tt ,
_doc_items_create_entry = use_doc ,
_doc_items_longdesc = longdesc ,
--_doc_items_usagehelp = usagehelp,
inventory_image = img .. " ^[colorize:purple:50 " ,
wield_image = img .. " ^[colorize:purple:50 " ,
stack_max = 64 ,
groups = { not_in_creative_inventory = 1 , compass = i , tool = 1 , disable_repair = 1 }
} )
2017-03-20 18:12:05 +01:00
-- Help aliases. Makes sure the lookup tool works correctly
if not use_doc and doc_mod then
doc.add_entry_alias ( " craftitems " , " mcl_compass: " .. ( stereotype_frame - 1 ) , " craftitems " , itemstring )
end
2015-06-29 19:55:56 +02:00
end
minetest.register_craft ( {
2021-05-29 16:12:33 +02:00
output = " mcl_compass: " .. stereotype_frame ,
2015-06-29 19:55:56 +02:00
recipe = {
2021-05-29 16:12:33 +02:00
{ " " , " mcl_core:iron_ingot " , " " } ,
{ " mcl_core:iron_ingot " , " mesecons:redstone " , " mcl_core:iron_ingot " } ,
{ " " , " mcl_core:iron_ingot " , " " }
2015-06-29 19:55:56 +02:00
}
2017-01-04 05:04:13 +01:00
} )
2017-01-09 03:26:00 +01:00
2022-03-28 18:06:30 +02:00
minetest.register_craft ( {
output = " mcl_compass:lodestone " ,
recipe = {
{ " mcl_core:stonebrickcarved " , " mcl_core:stonebrickcarved " , " mcl_core:stonebrickcarved " } ,
{ " mcl_core:stonebrickcarved " , " mcl_nether:netherite_ingot " , " mcl_core:stonebrickcarved " } ,
{ " mcl_core:stonebrickcarved " , " mcl_core:stonebrickcarved " , " mcl_core:stonebrickcarved " }
}
} )
2017-01-09 03:26:00 +01:00
minetest.register_alias ( " mcl_compass:compass " , " mcl_compass: " .. stereotype_frame )
2017-02-20 21:14:10 +01:00
-- Export stereotype item for other mods to use
mcl_compass.stereotype = " mcl_compass: " .. tostring ( stereotype_frame )
2022-03-28 18:06:30 +02:00
minetest.register_node ( " mcl_compass:lodestone " , {
2022-04-09 08:12:07 +02:00
description = S ( " Lodestone " ) ,
2022-03-28 18:06:30 +02:00
on_rightclick = function ( pos , node , player , itemstack )
if itemstack.get_name ( itemstack ) . match ( itemstack.get_name ( itemstack ) , " mcl_compass: " ) then
if itemstack.get_name ( itemstack ) ~= " mcl_compass:lodestone " then
itemstack : get_meta ( ) : set_string ( " x " , pos.x )
itemstack : get_meta ( ) : set_string ( " y " , pos.y )
itemstack : get_meta ( ) : set_string ( " z " , pos.z )
end
end
end ,
tiles = {
" lodestone_top.png " ,
" lodestone_bottom.png " ,
" lodestone_side1.png " ,
" lodestone_side2.png " ,
" lodestone_side3.png " ,
" lodestone_side4.png "
} ,
groups = { pickaxey = 1 , material_stone = 1 } ,
_mcl_hardness = 1.5 ,
_mcl_blast_resistance = 6 ,
sounds = mcl_sounds.node_sound_stone_defaults ( )
} )