forked from MineClone5/MineClone5
Merge remote-tracking branch 'origin/testing' into production
This commit is contained in:
commit
55cc5144e1
15
README.md
15
README.md
|
@ -1,5 +1,4 @@
|
||||||
# MineClone 5
|
# MineClone 5
|
||||||
Version: 0.71.7 Release Candidate 0
|
|
||||||
|
|
||||||
MineClone 5 is a fork of MineClone 2 with different workflow:
|
MineClone 5 is a fork of MineClone 2 with different workflow:
|
||||||
* No Minecraft version limitation, target version is Latest Java Edition
|
* No Minecraft version limitation, target version is Latest Java Edition
|
||||||
|
@ -70,9 +69,8 @@ Use the `/giveme` chat command to obtain them. See the in-game help for
|
||||||
an explanation.
|
an explanation.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
This game requires [Minetest](http://minetest.net) to run (version 5.4.1 or
|
This game requires latest stable [Minetest](http://minetest.net) to run, please install
|
||||||
later). So you need to install Minetest first. Only stable versions of Minetest
|
it first. Only stable versions of Minetest are officially supported.
|
||||||
are officially supported.
|
|
||||||
There is no support for running MineClone 5 in development versions of Minetest.
|
There is no support for running MineClone 5 in development versions of Minetest.
|
||||||
|
|
||||||
To install MineClone 5 (if you haven't already), move this directory into the
|
To install MineClone 5 (if you haven't already), move this directory into the
|
||||||
|
@ -83,10 +81,8 @@ Minetest to learn more.
|
||||||
The MineClone 5 repository is hosted at Mesehub. To contribute or report issues, head there.
|
The MineClone 5 repository is hosted at Mesehub. To contribute or report issues, head there.
|
||||||
|
|
||||||
* Mesehub: <https://git.minetest.land/MineClone5/MineClone5>
|
* Mesehub: <https://git.minetest.land/MineClone5/MineClone5>
|
||||||
* IRC: <https://web.libera.chat/#mineclone2>
|
* Minetest forums: <https://forum.minetest.net/viewtopic.php?f=50&t=27107>
|
||||||
* Matrix: <https://app.element.io/#/room/#mc2:matrix.org>
|
* Semi-official Discord: <https://discord.gg/PUm5YRn7dX>
|
||||||
* Reddit: <https://www.reddit.com/r/MineClone2/>
|
|
||||||
* Minetest forums: <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
|
||||||
|
|
||||||
## Project description
|
## Project description
|
||||||
The main goal of **MineClone 5** is to be a clone of Minecraft and to be released as free software.
|
The main goal of **MineClone 5** is to be a clone of Minecraft and to be released as free software.
|
||||||
|
@ -155,7 +151,7 @@ The following features are incomplete:
|
||||||
* Special minecarts
|
* Special minecarts
|
||||||
* A couple of non-trivial blocks and items
|
* A couple of non-trivial blocks and items
|
||||||
|
|
||||||
Bonus features (not found in Minecraft 1.12):
|
Bonus features (not found in Minecraft):
|
||||||
|
|
||||||
* Built-in crafting guide which shows you crafting and smelting recipes
|
* Built-in crafting guide which shows you crafting and smelting recipes
|
||||||
* In-game help system containing extensive help about gameplay basics, blocks, items and more
|
* In-game help system containing extensive help about gameplay basics, blocks, items and more
|
||||||
|
@ -168,6 +164,7 @@ Bonus features (not found in Minecraft 1.12):
|
||||||
* Nether Brick Fence Gate
|
* Nether Brick Fence Gate
|
||||||
* Red Nether Brick Fence
|
* Red Nether Brick Fence
|
||||||
* Red Nether Brick Fence Gate
|
* Red Nether Brick Fence Gate
|
||||||
|
* Arbitrary-shaped Nether portals
|
||||||
|
|
||||||
Technical differences from Minecraft:
|
Technical differences from Minecraft:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# mcl_time
|
||||||
|
## by kay27 for MineClone 5
|
||||||
|
---------------------------
|
||||||
|
This mod counts time when all players sleep or some area is inactive.
|
||||||
|
|
||||||
|
It depends very much on `time_speed` configuration variable, which could be changed 'on the fly' by a chat command.
|
||||||
|
|
||||||
|
If `time_speed` set to 0, this mod logs warnings and returns zeroes.
|
||||||
|
|
||||||
|
### mcl_time.get_seconds_irl()
|
||||||
|
------------------------------
|
||||||
|
Returns: Integer value of realtime (not in-game) seconds since world creation.
|
||||||
|
|
||||||
|
Usually this value grow smoothly. But when you skip the night being in the bed, or leave some area for some time, you may experience value jumps. That's basically the idea of this mod.
|
||||||
|
|
||||||
|
### mcl_time.get_number_of_times(last_time, interval, chance)
|
||||||
|
-------------------------------------------------------------
|
||||||
|
Handy to process AMBs.
|
||||||
|
|
||||||
|
You pass `last_time` - last known value of `seconds_irl`, also ABM `interval` and ABM `chance`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
* Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night.
|
||||||
|
* Integer value of realtime (not in-game) seconds since world creation.
|
||||||
|
|
||||||
|
### mcl_time.touch(pos)
|
||||||
|
-----------------------
|
||||||
|
This function 'toches' node at position `pos` by writing `_t` meta variable of `seconds_irl`.
|
||||||
|
|
||||||
|
### mcl_time.get_number_of_times_at_pos(pos, interval, chance)
|
||||||
|
--------------------------------------------------------------
|
||||||
|
Much more handy to call from LBM on area load, than `mcl_time.get_number_of_times()`!
|
||||||
|
|
||||||
|
It reads meta variable `_t` from position `pos` and uses it as previous `seconds_irl`, which then pass as first argument into `mcl_time.get_number_of_times()`.
|
||||||
|
After calling this, it also 'touches' the node at `pos` by writing `seconds_irl` into meta variable `_t`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
* Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night.
|
||||||
|
* Integer value of realtime (not in-game) seconds since world creation.
|
||||||
|
|
||||||
|
*Warning!* This function can return 0. So it's better not to use it for regular ABMs - use `mcl_time.get_number_of_times_at_pos_or_1()` instead.
|
||||||
|
|
||||||
|
### mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance)
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Much more handy to process ABMs than `mcl_time.get_number_of_times()` and `mcl_time.get_number_of_times_at_pos()`!
|
||||||
|
|
||||||
|
It just calls `mcl_time.get_number_of_times_at_pos()` but doesn't return 0, the minimum number it can return is 1,
|
||||||
|
which is the most suitable for regular ABM processing function.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
* Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night.
|
||||||
|
* Integer value of realtime (not in-game) seconds since world creation.
|
|
@ -0,0 +1,140 @@
|
||||||
|
mcl_time = {}
|
||||||
|
|
||||||
|
local time_update_interval = 2
|
||||||
|
local retry_on_fail_interval = 500
|
||||||
|
local default_time_speed = 72
|
||||||
|
local save_to_storage_interval = 600
|
||||||
|
local meta_name = "_t"
|
||||||
|
|
||||||
|
local current_time_update_interval = time_update_interval
|
||||||
|
|
||||||
|
local storage = minetest.get_mod_storage()
|
||||||
|
local seconds_irl_public = tonumber(storage:get_string("seconds_irl")) or -2
|
||||||
|
local last_save_seconds_irl = seconds_irl_public
|
||||||
|
local next_save_seconds_irl = last_save_seconds_irl + save_to_storage_interval
|
||||||
|
|
||||||
|
local previous_seconds_irl = -2
|
||||||
|
local function get_seconds_irl()
|
||||||
|
local time_speed = tonumber(minetest.settings:get("time_speed") or default_time_speed)
|
||||||
|
if time_speed < 1 then
|
||||||
|
minetest.log("warning", "[mcl_time] time_speed < 1 - please increase to make mcl_time api work (default: " .. default_time_speed .. ")")
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
local irl_multiplier = 86400 / time_speed
|
||||||
|
local day_count = minetest.get_day_count()
|
||||||
|
local timeofday = minetest.get_timeofday()
|
||||||
|
local seconds_irl
|
||||||
|
if not day_count or not timeofday then
|
||||||
|
seconds_irl = seconds_irl_public
|
||||||
|
else
|
||||||
|
local days_ig = 0.0 + day_count + timeofday
|
||||||
|
seconds_irl = days_ig * irl_multiplier
|
||||||
|
end
|
||||||
|
|
||||||
|
if previous_seconds_irl == seconds_irl then
|
||||||
|
current_time_update_interval = math.min(current_time_update_interval * 2, retry_on_fail_interval)
|
||||||
|
minetest.log("warning", "[mcl_time] Time doesn't change! seconds_irl=" .. tostring(seconds_irl)
|
||||||
|
.. ", day_count = " .. tostring(day_count) .. ", timeofday=" .. tostring(timeofday)
|
||||||
|
.. " - increasing update interval to " .. tostring(current_time_update_interval))
|
||||||
|
else
|
||||||
|
previous_seconds_irl = seconds_irl
|
||||||
|
if current_time_update_interval ~= time_update_interval then
|
||||||
|
current_time_update_interval = time_update_interval
|
||||||
|
minetest.log("action", "[mcl_time] Time is changing again: seconds_irl=" .. tostring(seconds_irl)
|
||||||
|
.. ", day_count = " .. tostring(day_count) .. ", timeofday=" .. tostring(timeofday)
|
||||||
|
.. ", update_interval=" .. tostring(current_time_update_interval))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if last_save_seconds_irl >= next_save_seconds_irl then
|
||||||
|
storage:set_string("seconds_irl", tostring(seconds_irl))
|
||||||
|
next_save_seconds_irl = seconds_irl + save_to_storage_interval
|
||||||
|
end
|
||||||
|
|
||||||
|
return seconds_irl
|
||||||
|
end
|
||||||
|
|
||||||
|
local seconds_irl_public = get_seconds_irl()
|
||||||
|
|
||||||
|
function mcl_time.get_seconds_irl()
|
||||||
|
return seconds_irl_public
|
||||||
|
end
|
||||||
|
|
||||||
|
local function time_runner()
|
||||||
|
seconds_irl_public = get_seconds_irl()
|
||||||
|
minetest.after(current_time_update_interval, time_runner)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_time.get_number_of_times(last_time, interval, chance)
|
||||||
|
if not last_time then return 0 end
|
||||||
|
if seconds_irl_public < 2 then return 0 end
|
||||||
|
if not interval then return 0 end
|
||||||
|
if not chance then return 0 end
|
||||||
|
if interval < 1 then return 0 end
|
||||||
|
if chance < 1 then return 0 end
|
||||||
|
local number_of_intervals = (seconds_irl_public - last_time) / interval
|
||||||
|
if number_of_intervals < 1 then return 0 end
|
||||||
|
local average_chance = (1 + chance) / 2
|
||||||
|
local number_of_times = math.floor(number_of_intervals / average_chance)
|
||||||
|
return number_of_times, seconds_irl_public
|
||||||
|
end
|
||||||
|
|
||||||
|
local get_number_of_times = mcl_time.get_number_of_times
|
||||||
|
|
||||||
|
function mcl_time.touch(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_int(meta_name, seconds_irl_public)
|
||||||
|
end
|
||||||
|
|
||||||
|
local touch = mcl_time.touch
|
||||||
|
|
||||||
|
function mcl_time.get_number_of_times_at_pos(pos, interval, chance)
|
||||||
|
if not pos then return 0 end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local last_time = meta:get_int(meta_name)
|
||||||
|
local number_of_times = (last_time == 0) and 0 or get_number_of_times(last_time, interval, chance)
|
||||||
|
touch(pos)
|
||||||
|
return number_of_times, seconds_irl_public
|
||||||
|
end
|
||||||
|
|
||||||
|
local get_number_of_times_at_pos = mcl_time.get_number_of_times_at_pos
|
||||||
|
|
||||||
|
function mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance)
|
||||||
|
return math.max(get_number_of_times_at_pos(pos, interval, chance), 1), seconds_irl_public
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_time.get_irl_seconds_passed_at_pos(pos)
|
||||||
|
if not pos then return 0 end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local last_time = meta:get_int(meta_name)
|
||||||
|
local irl_seconds_passed = (last_time == 0) and 0 or (seconds_irl_public - last_time)
|
||||||
|
return irl_seconds_passed
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_time.get_irl_seconds_passed_at_pos_or_1(pos)
|
||||||
|
if not pos then return 1 end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local last_time = meta:get_int(meta_name)
|
||||||
|
local irl_seconds_passed = (last_time == 0) and 1 or (seconds_irl_public - last_time)
|
||||||
|
return irl_seconds_passed
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos)
|
||||||
|
if not pos then return end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local last_time = meta:get_int(meta_name)
|
||||||
|
if last_time == 0 then return end
|
||||||
|
local delta_time = seconds_irl_public - last_time
|
||||||
|
if delta_time <= 0 then return end
|
||||||
|
return delta_time
|
||||||
|
end
|
||||||
|
|
||||||
|
time_runner()
|
||||||
|
local day_count = minetest.get_day_count()
|
||||||
|
local timeofday = minetest.get_timeofday()
|
||||||
|
minetest.log("action", "[mcl_time] time runner started, current in-real-life seconds: " .. seconds_irl_public
|
||||||
|
.. ", time_speed: " .. tostring(minetest.settings:get("time_speed"))
|
||||||
|
.. ", day_count: " .. tostring(day_count)
|
||||||
|
.. ", timeofday: " .. tostring(timeofday)
|
||||||
|
.. ", update_interval=" .. tostring(current_time_update_interval)
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = mcl_time
|
||||||
|
author = kay27
|
||||||
|
description = This mod counts time when all players sleep or some area is inactive
|
|
@ -112,7 +112,9 @@ local function detach_object(obj, change_pos)
|
||||||
mcl_player.player_attached[obj:get_player_name()] = false
|
mcl_player.player_attached[obj:get_player_name()] = false
|
||||||
mcl_player.player_set_animation(obj, "stand" , 30)
|
mcl_player.player_set_animation(obj, "stand" , 30)
|
||||||
else
|
else
|
||||||
obj:get_luaentity()._old_visual_size = nil
|
local luaentity = obj:get_luaentity()
|
||||||
|
if not luaentity then return end
|
||||||
|
luaentity._old_visual_size = nil
|
||||||
end
|
end
|
||||||
if change_pos then
|
if change_pos then
|
||||||
obj:set_pos(vector.add(obj:get_pos(), vector.new(0, 0.2, 0)))
|
obj:set_pos(vector.add(obj:get_pos(), vector.new(0, 0.2, 0)))
|
||||||
|
|
|
@ -16,6 +16,10 @@ dofile(modpath .. "/api.lua")
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
for _, player in pairs(get_connected_players()) do
|
for _, player in pairs(get_connected_players()) do
|
||||||
local storage = mcl_burning.storage[player]
|
local storage = mcl_burning.storage[player]
|
||||||
|
if not storage then
|
||||||
|
mcl_burning.init_player(player)
|
||||||
|
storage = mcl_burning.storage[player]
|
||||||
|
end
|
||||||
if not mcl_burning.tick(player, dtime, storage) and not mcl_burning.is_affected_by_rain(player) then
|
if not mcl_burning.tick(player, dtime, storage) and not mcl_burning.is_affected_by_rain(player) then
|
||||||
local nodes = mcl_burning.get_touching_nodes(player, {"group:puts_out_fire", "group:set_on_fire"}, storage)
|
local nodes = mcl_burning.get_touching_nodes(player, {"group:puts_out_fire", "group:set_on_fire"}, storage)
|
||||||
local burn_time = 0
|
local burn_time = 0
|
||||||
|
|
|
@ -27,6 +27,11 @@ local mcl_item_entity = {}
|
||||||
local item_drop_settings = {} --settings table
|
local item_drop_settings = {} --settings table
|
||||||
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
|
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
|
||||||
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
|
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
|
||||||
|
item_drop_settings.fluid_flow_rate = 1.39 --the speed of a flowing fluid, used when computing push and drag forces of water on items; default is tuned to Minecraft
|
||||||
|
item_drop_settings.fluid_drag = 1.8 --how much drag water has on items (how quickly an item's motion will settle onto the water's flow speed)
|
||||||
|
item_drop_settings.ground_drag = 3.0 --how much friction with the ground slows items sliding on it
|
||||||
|
item_drop_settings.slippery_drag_factor = 0.25 --scales item friction with the ground on slippery floors (e.g. ice)
|
||||||
|
item_drop_settings.slippery_fluid_drag_factor = 0.4 --scales item drag with waterflow on slippery floors (e.g. ice)
|
||||||
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
|
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
|
||||||
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
|
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
|
||||||
item_drop_settings.radius_collect = 0.2 --radius of collection
|
item_drop_settings.radius_collect = 0.2 --radius of collection
|
||||||
|
@ -778,11 +783,35 @@ minetest.register_entity(":__builtin:item", {
|
||||||
-- Just to make sure we don't manipulate the speed for no reason
|
-- Just to make sure we don't manipulate the speed for no reason
|
||||||
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
||||||
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
||||||
local f = 1.39
|
local f = item_drop_settings.fluid_flow_rate --1.39
|
||||||
-- Set new item moving speed into the direciton of the liquid
|
|
||||||
|
-- Apply the force of the flowing liquid onto the item's velocity
|
||||||
local newv = vector.multiply(vec, f)
|
local newv = vector.multiply(vec, f)
|
||||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||||
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
|
|
||||||
|
local oldvel = self.object:get_velocity() -- v is vector, vel is velocity
|
||||||
|
|
||||||
|
-- drag
|
||||||
|
local fluid_drag = item_drop_settings.fluid_drag
|
||||||
|
|
||||||
|
local floornn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
|
||||||
|
local floornode = floornn and minetest.registered_nodes[floornn]
|
||||||
|
if floornode and minetest.get_item_group(floornode.name, "slippery") then
|
||||||
|
-- scale fluid drag on slippery floors
|
||||||
|
fluid_drag = fluid_drag * item_drop_settings.slippery_fluid_drag_factor
|
||||||
|
end
|
||||||
|
|
||||||
|
newv.x = newv.x - (oldvel.x - newv.x) * fluid_drag * dtime
|
||||||
|
newv.y = newv.y - (oldvel.y - newv.y) * fluid_drag * dtime
|
||||||
|
newv.z = newv.z - (oldvel.z - newv.z) * fluid_drag * dtime
|
||||||
|
|
||||||
|
newv.y = newv.y + -0.22 -- (keep slight downward thrust from previous version of code)
|
||||||
|
-- NOTE: is there any particular reason we have this, anyway?
|
||||||
|
-- since fluid drag is now on, we could as well just
|
||||||
|
-- apply gravity here; drag will slow down the fall
|
||||||
|
-- realistically
|
||||||
|
|
||||||
|
self.object:set_velocity({x = oldvel.x + newv.x * dtime, y = oldvel.y + newv.y * dtime, z = oldvel.z + newv.z * dtime})
|
||||||
|
|
||||||
self.physical_state = true
|
self.physical_state = true
|
||||||
self._flowing = true
|
self._flowing = true
|
||||||
|
@ -794,15 +823,17 @@ minetest.register_entity(":__builtin:item", {
|
||||||
elseif self._flowing == true then
|
elseif self._flowing == true then
|
||||||
-- Disable flowing physics if not on/in flowing liquid
|
-- Disable flowing physics if not on/in flowing liquid
|
||||||
self._flowing = false
|
self._flowing = false
|
||||||
enable_physics(self.object, self, true)
|
--enable_physics(self.object, self, true) -- do not reset velocity upon leaving water!
|
||||||
|
self.object:set_acceleration({x=0,y=-get_gravity(),z=0}) -- resume applying gravity
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If node is not registered or node is walkably solid and resting on nodebox
|
-- If node is not registered or node is walkably solid and resting on nodebox
|
||||||
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
|
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
|
||||||
local v = self.object:get_velocity()
|
local v = self.object:get_velocity()
|
||||||
|
local node = nn and minetest.registered_nodes[nn]
|
||||||
|
|
||||||
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and v.y == 0 then
|
if not node or node.walkable and v.y == 0 then
|
||||||
if self.physical_state then
|
if self.physical_state then
|
||||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||||
-- Merge with close entities of the same item
|
-- Merge with close entities of the same item
|
||||||
|
@ -815,7 +846,28 @@ minetest.register_entity(":__builtin:item", {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
--disable_physics(self.object, self)
|
||||||
|
-- apply ground drag
|
||||||
|
local oldvel = self.object:get_velocity()
|
||||||
|
|
||||||
|
-- ignore momentum if it's tiny
|
||||||
|
if math.abs(oldvel.x) < 0.05 and math.abs(oldvel.z) < 0.05 then
|
||||||
disable_physics(self.object, self)
|
disable_physics(self.object, self)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local ground_drag = item_drop_settings.ground_drag
|
||||||
|
|
||||||
|
if node and minetest.get_item_group(node.name, "slippery") ~= 0 then
|
||||||
|
ground_drag = ground_drag * item_drop_settings.slippery_drag_factor
|
||||||
|
end
|
||||||
|
|
||||||
|
local newvel = {
|
||||||
|
x = oldvel.x - oldvel.x * ground_drag * dtime,
|
||||||
|
y = 0,
|
||||||
|
z = oldvel.z - oldvel.z * ground_drag * dtime
|
||||||
|
}
|
||||||
|
self.object:set_velocity(newvel)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if self._magnet_active == false then
|
if self._magnet_active == false then
|
||||||
|
|
|
@ -893,6 +893,17 @@ function mobs.mob_step(self, dtime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--water damage
|
||||||
|
if self.water_damage and self.water_damage ~= 0 then
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
local node = minetest_get_node(pos).name
|
||||||
|
if minetest_get_item_group(node, "water") ~= 0 then
|
||||||
|
mobs.smoke_effect(self)
|
||||||
|
self.health = self.health - self.water_damage
|
||||||
|
self:teleport()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--set mobs on fire when burned by sunlight
|
--set mobs on fire when burned by sunlight
|
||||||
if self.ignited_by_sunlight then
|
if self.ignited_by_sunlight then
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
|
|
@ -148,3 +148,23 @@ mobs.breeding_effect = function(self)
|
||||||
texture = "heart.png",
|
texture = "heart.png",
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mobs.smoke_effect = function(self)
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 5,
|
||||||
|
time = 0.25,
|
||||||
|
minpos = pos,
|
||||||
|
maxpos = pos,
|
||||||
|
minvel = {x = -1, y = -1, z = -1},
|
||||||
|
maxvel = {x = 1, y = 1, z = 1},
|
||||||
|
minacc = {x = 0, y = 10, z = 0},
|
||||||
|
maxacc = {x = 0, y = 10, z = 0},
|
||||||
|
minexptime = 0.1,
|
||||||
|
maxexptime = 1,
|
||||||
|
minsize = 0.5,
|
||||||
|
maxsize = 1,
|
||||||
|
collisiondetection = false,
|
||||||
|
texture = "mcl_particles_smoke.png",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
mcl_mobs
|
|
||||||
mcl_potions
|
|
|
@ -260,9 +260,22 @@ local dispenserdef = {
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Drop item otherwise
|
-- Drop item otherwise
|
||||||
minetest.add_item(droppos, dropitem)
|
-- Drop item normally
|
||||||
|
local dropitemobj = minetest.add_item(droppos, dropitem)
|
||||||
stack:take_item()
|
stack:take_item()
|
||||||
inv:set_stack("main", stack_id, stack)
|
inv:set_stack("main", stack_id, stack)
|
||||||
|
|
||||||
|
-- Set item velocity (overrides the default random drop direction)
|
||||||
|
local shoot_force = 1.3
|
||||||
|
|
||||||
|
local newv = minetest.facedir_to_dir(node.param2)
|
||||||
|
newv = {
|
||||||
|
x = newv.x * shoot_force,
|
||||||
|
y = newv.y * shoot_force,
|
||||||
|
z = newv.z * shoot_force
|
||||||
|
}
|
||||||
|
|
||||||
|
dropitemobj:set_velocity(newv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -134,9 +134,21 @@ local dropperdef = {
|
||||||
-- No container?
|
-- No container?
|
||||||
if not dropped and not dropnodedef.groups.container then
|
if not dropped and not dropnodedef.groups.container then
|
||||||
-- Drop item normally
|
-- Drop item normally
|
||||||
minetest.add_item(droppos, dropitem)
|
local dropitemobj = minetest.add_item(droppos, dropitem)
|
||||||
stack:take_item()
|
stack:take_item()
|
||||||
inv:set_stack("main", stack_id, stack)
|
inv:set_stack("main", stack_id, stack)
|
||||||
|
|
||||||
|
-- Set item velocity (overrides the default random drop direction)
|
||||||
|
local shoot_force = 1.3
|
||||||
|
|
||||||
|
local newv = minetest.facedir_to_dir(node.param2)
|
||||||
|
newv = {
|
||||||
|
x = -newv.x * shoot_force,
|
||||||
|
y = -newv.y * shoot_force,
|
||||||
|
z = -newv.z * shoot_force
|
||||||
|
}
|
||||||
|
|
||||||
|
dropitemobj:set_velocity(newv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
local S = minetest.get_translator(minetest.get_current_modname())
|
local S = minetest.get_translator(minetest.get_current_modname())
|
||||||
|
local F = minetest.formspec_escape
|
||||||
|
local C = minetest.colorize
|
||||||
local mod_doc = minetest.get_modpath("doc")
|
local mod_doc = minetest.get_modpath("doc")
|
||||||
|
|
||||||
-- Chest Entity
|
-- Chest Entity
|
||||||
|
@ -174,7 +176,7 @@ end]]
|
||||||
local function player_chest_open(player, pos, node_name, textures, param2, double, sound, mesh, shulker)
|
local function player_chest_open(player, pos, node_name, textures, param2, double, sound, mesh, shulker)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
open_chests[name] = {pos = pos, node_name = node_name, textures = textures, param2 = param2, double = double, sound = sound, mesh = mesh, shulker = shulker}
|
open_chests[name] = {pos = pos, node_name = node_name, textures = textures, param2 = param2, double = double, sound = sound, mesh = mesh, shulker = shulker}
|
||||||
if animate_chests then
|
if animate_chests and not string.find(node_name, "barrel") then
|
||||||
local dir = minetest.facedir_to_dir(param2)
|
local dir = minetest.facedir_to_dir(param2)
|
||||||
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name)
|
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name)
|
||||||
end
|
end
|
||||||
|
@ -226,6 +228,8 @@ local function chest_update_after_close(pos)
|
||||||
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
|
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
|
||||||
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
|
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
|
||||||
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
|
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
|
||||||
|
elseif node.name == "mcl_chests:barrel_open" then
|
||||||
|
minetest.swap_node(pos, {name = "mcl_chests:barrel", param2 = node.param2})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -236,7 +240,7 @@ local function player_chest_close(player)
|
||||||
if open_chest == nil then
|
if open_chest == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if animate_chests then
|
if animate_chests and not string.find(open_chest.node_name, "barrel") then
|
||||||
find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2, open_chest.double, open_chest.sound, open_chest.mesh, open_chest.shulker and "shulker" or "chest"):close(name)
|
find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2, open_chest.double, open_chest.sound, open_chest.mesh, open_chest.shulker and "shulker" or "chest"):close(name)
|
||||||
end
|
end
|
||||||
chest_update_after_close(open_chest.pos)
|
chest_update_after_close(open_chest.pos)
|
||||||
|
@ -291,27 +295,40 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drop_items_chest(pos, oldnode, oldmetadata)
|
local function drop_item_stack(pos, stack)
|
||||||
local meta = minetest.get_meta(pos)
|
if not stack or stack:is_empty() then return end
|
||||||
local meta2 = meta:to_table()
|
local drop_offset = vector.new(math.random() - 0.5, 0, math.random() - 0.5)
|
||||||
if oldmetadata then
|
minetest.add_item(vector.add(pos, drop_offset), stack)
|
||||||
meta:from_table(oldmetadata)
|
|
||||||
end
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
for i=1,inv:get_size("main") do
|
|
||||||
local stack = inv:get_stack("main", i)
|
|
||||||
if not stack:is_empty() then
|
|
||||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
|
||||||
minetest.add_item(p, stack)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
meta:from_table(meta2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function on_chest_blast(pos)
|
local function drop_items_chest(pos, oldnode, oldmetadata, digger)
|
||||||
|
if oldmetadata and oldmetadata.inventory then
|
||||||
|
-- process after_dig_node callback
|
||||||
|
local main = oldmetadata.inventory.main
|
||||||
|
if not main then return end
|
||||||
|
for _, stack in pairs(main) do
|
||||||
|
drop_item_stack(pos, stack)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
for i = 1, inv:get_size("main") do
|
||||||
|
drop_item_stack(pos, inv:get_stack("main", i))
|
||||||
|
end
|
||||||
|
meta:from_table()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function on_chest_blast(pos, intensity)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
drop_items_chest(pos, node)
|
drop_items_chest(pos, node)
|
||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
|
-- drop node itself with some probability depended on explosion intensity (1 for TNT):
|
||||||
|
if math.random(1, math.floor((intensity or 1) * 2)) ~= 1 then return end
|
||||||
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
|
if not node_def then return end
|
||||||
|
local node_name = node_def.drop or node_def.name
|
||||||
|
drop_item_stack(pos, ItemStack(node_name))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function limit_put_list(stack, list)
|
local function limit_put_list(stack, list)
|
||||||
|
@ -478,10 +495,10 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
minetest.show_formspec(clicker:get_player_name(),
|
minetest.show_formspec(clicker:get_player_name(),
|
||||||
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||||
"size[9,8.75]"..
|
"size[9,8.75]"..
|
||||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]"..
|
"label[0,0;"..F(C("#313131", name)).."]"..
|
||||||
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
|
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
||||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]"..
|
||||||
"list[current_player;main;0,4.5;9,3;9]"..
|
"list[current_player;main;0,4.5;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||||
"list[current_player;main;0,7.74;9,1;]"..
|
"list[current_player;main;0,7.74;9,1;]"..
|
||||||
|
@ -629,12 +646,12 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
minetest.show_formspec(clicker:get_player_name(),
|
minetest.show_formspec(clicker:get_player_name(),
|
||||||
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||||
"size[9,11.5]"..
|
"size[9,11.5]"..
|
||||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]"..
|
"label[0,0;"..F(C("#313131", name)).."]"..
|
||||||
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
|
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
||||||
"list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,3.5;9,3;]"..
|
"list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,3.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,3.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,3.5,9,3)..
|
||||||
"label[0,7;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
"label[0,7;"..F(C("#313131", S("Inventory"))).."]"..
|
||||||
"list[current_player;main;0,7.5;9,3;9]"..
|
"list[current_player;main;0,7.5;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,7.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,7.5,9,3)..
|
||||||
"list[current_player;main;0,10.75;9,1;]"..
|
"list[current_player;main;0,10.75;9,1;]"..
|
||||||
|
@ -777,12 +794,12 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
"mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||||
|
|
||||||
"size[9,11.5]"..
|
"size[9,11.5]"..
|
||||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]"..
|
"label[0,0;"..F(C("#313131", name)).."]"..
|
||||||
"list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,0.5;9,3;]"..
|
"list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,0.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
||||||
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,3.5;9,3;]"..
|
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,3.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,3.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,3.5,9,3)..
|
||||||
"label[0,7;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
"label[0,7;"..F(C("#313131", S("Inventory"))).."]"..
|
||||||
"list[current_player;main;0,7.5;9,3;9]"..
|
"list[current_player;main;0,7.5;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,7.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,7.5,9,3)..
|
||||||
"list[current_player;main;0,10.75;9,1;]"..
|
"list[current_player;main;0,10.75;9,1;]"..
|
||||||
|
@ -902,38 +919,6 @@ register_chest("trapped_chest_on",
|
||||||
"trapped_chest"
|
"trapped_chest"
|
||||||
)
|
)
|
||||||
|
|
||||||
--[[local function close_if_trapped_chest(pos, player)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
|
|
||||||
if node.name == "mcl_chests:trapped_chest_on_small" then
|
|
||||||
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
|
|
||||||
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
|
|
||||||
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
|
|
||||||
|
|
||||||
player_chest_close(player)
|
|
||||||
elseif node.name == "mcl_chests:trapped_chest_on_left" then
|
|
||||||
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
|
|
||||||
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
|
|
||||||
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
|
|
||||||
|
|
||||||
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
|
|
||||||
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
|
|
||||||
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
|
|
||||||
|
|
||||||
player_chest_close(player)
|
|
||||||
elseif node.name == "mcl_chests:trapped_chest_on_right" then
|
|
||||||
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
|
|
||||||
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
|
|
||||||
|
|
||||||
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
|
|
||||||
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
|
|
||||||
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
|
|
||||||
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
|
|
||||||
|
|
||||||
player_chest_close(player)
|
|
||||||
end
|
|
||||||
end]]
|
|
||||||
|
|
||||||
-- Disable chest when it has been closed
|
-- Disable chest when it has been closed
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if formname:find("mcl_chests:") == 1 then
|
if formname:find("mcl_chests:") == 1 then
|
||||||
|
@ -990,10 +975,10 @@ minetest.register_node("mcl_chests:ender_chest", {
|
||||||
})
|
})
|
||||||
|
|
||||||
local formspec_ender_chest = "size[9,8.75]"..
|
local formspec_ender_chest = "size[9,8.75]"..
|
||||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Ender Chest"))).."]"..
|
"label[0,0;"..F(C("#313131", S("Ender Chest"))).."]"..
|
||||||
"list[current_player;enderchest;0,0.5;9,3;]"..
|
"list[current_player;enderchest;0,0.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
||||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]"..
|
||||||
"list[current_player;main;0,4.5;9,3;9]"..
|
"list[current_player;main;0,4.5;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||||
"list[current_player;main;0,7.74;9,1;]"..
|
"list[current_player;main;0,7.74;9,1;]"..
|
||||||
|
@ -1125,10 +1110,10 @@ local function formspec_shulker_box(name)
|
||||||
name = S("Shulker Box")
|
name = S("Shulker Box")
|
||||||
end
|
end
|
||||||
return "size[9,8.75]"..
|
return "size[9,8.75]"..
|
||||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]"..
|
"label[0,0;"..F(C("#313131", name)).."]"..
|
||||||
"list[context;main;0,0.5;9,3;]"..
|
"list[context;main;0,0.5;9,3;]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,0.5,9,3)..
|
||||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]"..
|
||||||
"list[current_player;main;0,4.5;9,3;9]"..
|
"list[current_player;main;0,4.5;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||||
"list[current_player;main;0,7.74;9,1;]"..
|
"list[current_player;main;0,7.74;9,1;]"..
|
||||||
|
@ -1436,3 +1421,95 @@ minetest.register_lbm({
|
||||||
minetest.get_meta(pos):set_string("formspec", "")
|
minetest.get_meta(pos):set_string("formspec", "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local function barrel_open(pos, node, clicker)
|
||||||
|
local name = minetest.get_meta(pos):get_string("name")
|
||||||
|
|
||||||
|
if name == "" then
|
||||||
|
name = S("Barrel")
|
||||||
|
end
|
||||||
|
|
||||||
|
local playername = clicker:get_player_name()
|
||||||
|
|
||||||
|
minetest.show_formspec(playername,
|
||||||
|
"mcl_chests:barrel_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||||
|
table.concat({
|
||||||
|
"size[9,8.75]",
|
||||||
|
"label[0,0;"..F(C("#313131", name)).."]",
|
||||||
|
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]",
|
||||||
|
mcl_formspec.get_itemslot_bg(0, 0.5, 9, 3),
|
||||||
|
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]",
|
||||||
|
"list[current_player;main;0,4.5;9,3;9]",
|
||||||
|
mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3),
|
||||||
|
"list[current_player;main;0,7.74;9,1;]",
|
||||||
|
mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1),
|
||||||
|
"listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]",
|
||||||
|
"listring[current_player;main]",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
minetest.swap_node(pos, { name = "mcl_chests:barrel_open", param2 = node.param2 })
|
||||||
|
player_chest_open(clicker, pos, "mcl_chests:barrel")
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("mcl_chests:barrel", {
|
||||||
|
description = S("Barrel"),
|
||||||
|
_tt_help = S("27 inventory slots"),
|
||||||
|
_doc_items_longdesc = S("Barrels are containers which provide 27 inventory slots."),
|
||||||
|
_doc_items_usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||||
|
tiles = {"mcl_barrels_barrel_top.png", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
minetest.rotate_and_place(itemstack, placer, pointed_thing, minetest.is_creative_enabled(placer:get_player_name()), {}, false)
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
stack_max = 64,
|
||||||
|
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||||
|
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1},
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
inv:set_size("main", 9*3)
|
||||||
|
end,
|
||||||
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||||
|
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||||
|
end,
|
||||||
|
after_dig_node = drop_items_chest,
|
||||||
|
on_blast = on_blast,
|
||||||
|
on_rightclick = barrel_open,
|
||||||
|
on_destruct = close_forms,
|
||||||
|
_mcl_blast_resistance = 2.5,
|
||||||
|
_mcl_hardness = 2.5,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("mcl_chests:barrel_open", {
|
||||||
|
description = S("Barrel Open"),
|
||||||
|
_tt_help = S("27 inventory slots"),
|
||||||
|
_doc_items_longdesc = S("Barrels are containers which provide 27 inventory slots."),
|
||||||
|
_doc_items_usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||||
|
_doc_items_create_entry = false,
|
||||||
|
tiles = {"mcl_barrels_barrel_top_open.png", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
drop = "mcl_chests:barrel",
|
||||||
|
stack_max = 64,
|
||||||
|
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||||
|
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1},
|
||||||
|
after_dig_node = drop_items_chest,
|
||||||
|
on_blast = on_blast,
|
||||||
|
on_rightclick = barrel_open,
|
||||||
|
on_destruct = close_forms,
|
||||||
|
_mcl_blast_resistance = 2.5,
|
||||||
|
_mcl_hardness = 2.5,
|
||||||
|
})
|
||||||
|
|
||||||
|
--Minecraft Java Edition craft
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "mcl_chests:barrel",
|
||||||
|
recipe = {
|
||||||
|
{"group:wood", "group:wood_slab", "group:wood"},
|
||||||
|
{"group:wood", "", "group:wood"},
|
||||||
|
{"group:wood", "group:wood_slab", "group:wood"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
|
@ -34,3 +34,5 @@ Can be combined to a large chest=Peut être combiné à un grand coffre
|
||||||
27 interdimensional inventory slots=27 emplacements d'inventaire interdimensionnels
|
27 interdimensional inventory slots=27 emplacements d'inventaire interdimensionnels
|
||||||
Put items inside, retrieve them from any ender chest=Mettez des objets à l'intérieur, récupérez-les dans n'importe quel coffre
|
Put items inside, retrieve them from any ender chest=Mettez des objets à l'intérieur, récupérez-les dans n'importe quel coffre
|
||||||
Emits a redstone signal when opened=Émet un signal redstone à l'ouverture
|
Emits a redstone signal when opened=Émet un signal redstone à l'ouverture
|
||||||
|
Barrel=Tonneau
|
||||||
|
Barrels are containers which provide 27 inventory slots.=Les tonneaux sont des conteneurs qui offrent 27 emplacements d'inventaire.
|
||||||
|
|
|
@ -34,3 +34,5 @@ Can be combined to a large chest=Можно объединить в большо
|
||||||
27 interdimensional inventory slots=27 межпространственных отсеков инвентаря
|
27 interdimensional inventory slots=27 межпространственных отсеков инвентаря
|
||||||
Put items inside, retrieve them from any ender chest=Положите внутрь предмет и получите его из любого сундука Предела
|
Put items inside, retrieve them from any ender chest=Положите внутрь предмет и получите его из любого сундука Предела
|
||||||
Emits a redstone signal when opened=Подаёт сигнал редстоуна, будучи открытым
|
Emits a redstone signal when opened=Подаёт сигнал редстоуна, будучи открытым
|
||||||
|
Barrel=Бочка
|
||||||
|
Barrels are containers which provide 27 inventory slots.=Бочки это хранилища, предоставляющие 27 отсеков инвентаря.
|
||||||
|
|
|
@ -34,3 +34,5 @@ Can be combined to a large chest=
|
||||||
27 interdimensional inventory slots=
|
27 interdimensional inventory slots=
|
||||||
Put items inside, retrieve them from any ender chest=
|
Put items inside, retrieve them from any ender chest=
|
||||||
Emits a redstone signal when opened=
|
Emits a redstone signal when opened=
|
||||||
|
Barrel=
|
||||||
|
Barrels are containers which provide 27 inventory slots.=
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
name = mcl_chests
|
name = mcl_chests
|
||||||
|
author = Wuzzy, Fleckenstein, AFCMS
|
||||||
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_end, mesecons
|
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_end, mesecons
|
||||||
optional_depends = doc, screwdriver
|
optional_depends = doc, screwdriver
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 542 B |
Binary file not shown.
After Width: | Height: | Size: 499 B |
Binary file not shown.
After Width: | Height: | Size: 566 B |
Binary file not shown.
After Width: | Height: | Size: 421 B |
|
@ -655,7 +655,7 @@ mcl_enchanting.enchantments.soul_speed = {
|
||||||
mcl_enchanting.enchantments.unbreaking = {
|
mcl_enchanting.enchantments.unbreaking = {
|
||||||
name = S("Unbreaking"),
|
name = S("Unbreaking"),
|
||||||
max_level = 3,
|
max_level = 3,
|
||||||
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, pickaxe = true, shovel = true, axe = true, hoe = true, sword = true, fishing_rod = true, bow = true},
|
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, crossbow = true, pickaxe = true, shovel = true, axe = true, hoe = true, sword = true, fishing_rod = true, bow = true},
|
||||||
secondary = {tool = true},
|
secondary = {tool = true},
|
||||||
disallow = {non_combat_armor = true},
|
disallow = {non_combat_armor = true},
|
||||||
incompatible = {},
|
incompatible = {},
|
||||||
|
|
|
@ -215,62 +215,11 @@ local function swap_node(pos, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function furnace_reset_delta_time(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local time_speed = tonumber(minetest.settings:get("time_speed") or 72)
|
|
||||||
if (time_speed < 0.1) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local time_multiplier = 86400 / time_speed
|
|
||||||
local current_game_time = .0 + ((minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier)
|
|
||||||
|
|
||||||
-- TODO: Change meta:get/set_string() to get/set_float() for "last_gametime".
|
|
||||||
-- In Windows *_float() works OK but under Linux it returns rounded unusable values like 449540.000000000
|
|
||||||
local last_game_time = meta:get_string("last_gametime")
|
|
||||||
if last_game_time then
|
|
||||||
last_game_time = tonumber(last_game_time)
|
|
||||||
end
|
|
||||||
if not last_game_time or last_game_time < 1 or math.abs(last_game_time - current_game_time) <= 1.5 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
meta:set_string("last_gametime", tostring(current_game_time))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function furnace_get_delta_time(pos, elapsed)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local time_speed = tonumber(minetest.settings:get("time_speed") or 72)
|
|
||||||
local current_game_time
|
|
||||||
if (time_speed < 0.1) then
|
|
||||||
return meta, elapsed
|
|
||||||
else
|
|
||||||
local time_multiplier = 86400 / time_speed
|
|
||||||
current_game_time = .0 + ((minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier)
|
|
||||||
end
|
|
||||||
|
|
||||||
local last_game_time = meta:get_string("last_gametime")
|
|
||||||
if last_game_time then
|
|
||||||
last_game_time = tonumber(last_game_time)
|
|
||||||
end
|
|
||||||
if not last_game_time or last_game_time < 1 then
|
|
||||||
last_game_time = current_game_time - 0.1
|
|
||||||
elseif last_game_time == current_game_time then
|
|
||||||
current_game_time = current_game_time + 1.0
|
|
||||||
end
|
|
||||||
|
|
||||||
local elapsed_game_time = .0 + current_game_time - last_game_time
|
|
||||||
|
|
||||||
meta:set_string("last_gametime", tostring(current_game_time))
|
|
||||||
|
|
||||||
return meta, elapsed_game_time
|
|
||||||
end
|
|
||||||
|
|
||||||
local function furnace_node_timer(pos, elapsed)
|
local function furnace_node_timer(pos, elapsed)
|
||||||
--
|
--
|
||||||
-- Inizialize metadata
|
-- Inizialize metadata
|
||||||
--
|
--
|
||||||
local meta, elapsed_game_time = furnace_get_delta_time(pos, elapsed)
|
local meta = minetest.get_meta(pos)
|
||||||
|
|
||||||
local fuel_time = meta:get_float("fuel_time") or 0
|
local fuel_time = meta:get_float("fuel_time") or 0
|
||||||
local src_time = meta:get_float("src_time") or 0
|
local src_time = meta:get_float("src_time") or 0
|
||||||
local src_item = meta:get_string("src_item") or ""
|
local src_item = meta:get_string("src_item") or ""
|
||||||
|
@ -294,6 +243,7 @@ local function furnace_node_timer(pos, elapsed)
|
||||||
end
|
end
|
||||||
|
|
||||||
local update = true
|
local update = true
|
||||||
|
local elapsed_game_time = mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos) or elapsed
|
||||||
while elapsed_game_time > 0.00001 and update do
|
while elapsed_game_time > 0.00001 and update do
|
||||||
--
|
--
|
||||||
-- Cooking
|
-- Cooking
|
||||||
|
@ -489,20 +439,20 @@ minetest.register_node("mcl_furnaces:furnace", {
|
||||||
|
|
||||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
-- Reset accumulated game time when player works with furnace:
|
-- Reset accumulated game time when player works with furnace:
|
||||||
furnace_reset_delta_time(pos)
|
mcl_time.touch(pos)
|
||||||
minetest.get_node_timer(pos):start(1.0)
|
minetest.get_node_timer(pos):start(1.0)
|
||||||
|
|
||||||
on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_put = function(pos)
|
on_metadata_inventory_put = function(pos)
|
||||||
-- Reset accumulated game time when player works with furnace:
|
-- Reset accumulated game time when player works with furnace:
|
||||||
furnace_reset_delta_time(pos)
|
mcl_time.touch(pos)
|
||||||
-- start timer function, it will sort out whether furnace can burn or not.
|
-- start timer function, it will sort out whether furnace can burn or not.
|
||||||
minetest.get_node_timer(pos):start(1.0)
|
minetest.get_node_timer(pos):start(1.0)
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
-- Reset accumulated game time when player works with furnace:
|
-- Reset accumulated game time when player works with furnace:
|
||||||
furnace_reset_delta_time(pos)
|
mcl_time.touch(pos)
|
||||||
-- start timer function, it will helpful if player clears dst slot
|
-- start timer function, it will helpful if player clears dst slot
|
||||||
minetest.get_node_timer(pos):start(1.0)
|
minetest.get_node_timer(pos):start(1.0)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
name = mcl_furnaces
|
name = mcl_furnaces
|
||||||
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_craftguide, mcl_achievements, mcl_particles
|
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_craftguide, mcl_achievements, mcl_particles, mcl_time
|
||||||
optional_depends = doc, screwdriver
|
optional_depends = doc, screwdriver
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
name = mcl_nether
|
name = mcl_nether
|
||||||
depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors
|
depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors, mcl_time
|
||||||
optional_depends = doc, screwdriver
|
optional_depends = doc, screwdriver
|
||||||
|
|
|
@ -6,21 +6,6 @@ local interval = 35
|
||||||
local chance = 11
|
local chance = 11
|
||||||
local max_interval = interval * chance
|
local max_interval = interval * chance
|
||||||
|
|
||||||
local time_speed
|
|
||||||
local time_multiplier
|
|
||||||
local current_game_time
|
|
||||||
|
|
||||||
function update_timespeed()
|
|
||||||
time_speed = tonumber(minetest.settings:get("time_speed") or 72)
|
|
||||||
time_multiplier = 86400 / time_speed
|
|
||||||
current_game_time = .0 + ((minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier)
|
|
||||||
minetest.after(5, update_timespeed)
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_on_mods_loaded(function()
|
|
||||||
minetest.after(5, update_timespeed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
minetest.register_node("mcl_nether:nether_wart_0", {
|
minetest.register_node("mcl_nether:nether_wart_0", {
|
||||||
description = S("Premature Nether Wart (Stage 1)"),
|
description = S("Premature Nether Wart (Stage 1)"),
|
||||||
_doc_items_longdesc = S("A premature nether wart has just recently been planted on soul sand. Nether wart slowly grows on soul sand in 4 stages (the second and third stages look identical). Although nether wart is home to the Nether, it grows in any dimension."),
|
_doc_items_longdesc = S("A premature nether wart has just recently been planted on soul sand. Nether wart slowly grows on soul sand in 4 stages (the second and third stages look identical). Although nether wart is home to the Nether, it grows in any dimension."),
|
||||||
|
@ -183,6 +168,9 @@ local function grow(pos, node)
|
||||||
new_node.param = node.param
|
new_node.param = node.param
|
||||||
new_node.param2 = node.param2
|
new_node.param2 = node.param2
|
||||||
minetest.set_node(pos, new_node)
|
minetest.set_node(pos, new_node)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("gametime", tostring(mcl_time:get_seconds_irl()))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
|
@ -197,9 +185,10 @@ minetest.register_abm({
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
pos.y = pos.y+1
|
pos.y = pos.y+1
|
||||||
|
|
||||||
|
for i = 1, mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance) do
|
||||||
grow(pos, node)
|
grow(pos, node)
|
||||||
local meta = minetest.get_meta(pos)
|
end
|
||||||
meta:set_string("gametime", tostring(current_game_time))
|
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -214,20 +203,8 @@ minetest.register_lbm({
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
pos.y = pos.y+1
|
pos.y = pos.y+1
|
||||||
local meta = minetest.get_meta(pos)
|
for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do
|
||||||
local last_game_time = tonumber(meta:get_string("gametime"))
|
|
||||||
if not last_game_time then return end
|
|
||||||
|
|
||||||
local real_seconds = last_game_time - current_game_time
|
|
||||||
if real_seconds < interval then return end
|
|
||||||
|
|
||||||
local threshold = math.random(interval, max_interval)
|
|
||||||
local i = 0
|
|
||||||
while real_seconds >= threshold and i < 4 do
|
|
||||||
grow(pos, node)
|
grow(pos, node)
|
||||||
real_seconds = real_seconds - threshold
|
|
||||||
threshold = math.random(interval, max_interval)
|
|
||||||
i = i + 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
|
@ -90,7 +90,7 @@ function mcl_player.player_set_model(player, model_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set_texture(player, index, texture)
|
local function set_texture(player, index, texture)
|
||||||
local textures = player_textures[player:get_player_name()]
|
local textures = player_textures[player:get_player_name()] or {}
|
||||||
textures[index] = texture
|
textures[index] = texture
|
||||||
player:set_properties({textures = textures})
|
player:set_properties({textures = textures})
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue