Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 294 B |
|
@ -1,24 +0,0 @@
|
|||
Minetest mod: boost_cart
|
||||
=======================
|
||||
Based on (and fully compatible with) the mod "carts" by PilzAdam
|
||||
Target: Run smoothly and do not use too much CPU.
|
||||
Edited by TenPlus1 to drop cart when no-one inside
|
||||
|
||||
License of source code:
|
||||
-----------------------
|
||||
WTFPL
|
||||
|
||||
License of media (textures, sounds and models):
|
||||
-----------------------------------------------
|
||||
CC-0
|
||||
|
||||
Authors of media files:
|
||||
-----------------------
|
||||
kddekadenz:
|
||||
cart_bottom.png
|
||||
cart_side.png
|
||||
cart_top.png
|
||||
|
||||
Zeg9:
|
||||
cart.x
|
||||
cart.png
|
|
@ -1,4 +0,0 @@
|
|||
default
|
||||
mesecons?
|
||||
moreores?
|
||||
mobs?
|
|
@ -1,150 +0,0 @@
|
|||
function boost_cart:get_sign(z)
|
||||
if z == 0 then
|
||||
return 0
|
||||
else
|
||||
return z / math.abs(z)
|
||||
end
|
||||
end
|
||||
|
||||
function boost_cart:velocity_to_dir(v)
|
||||
if math.abs(v.x) > math.abs(v.z) then
|
||||
return {x=boost_cart:get_sign(v.x), y=boost_cart:get_sign(v.y), z=0}
|
||||
else
|
||||
return {x=0, y=boost_cart:get_sign(v.y), z=boost_cart:get_sign(v.z)}
|
||||
end
|
||||
end
|
||||
|
||||
function boost_cart:is_rail(pos, railtype)
|
||||
local node = minetest.get_node(pos).name
|
||||
if node == "ignore" then
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(pos, pos)
|
||||
local area = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax,
|
||||
}
|
||||
local data = vm:get_data()
|
||||
local vi = area:indexp(pos)
|
||||
node = minetest.get_name_from_content_id(data[vi])
|
||||
end
|
||||
if minetest.get_item_group(node, "rail") == 0 then
|
||||
return false
|
||||
end
|
||||
if not railtype then
|
||||
return true
|
||||
end
|
||||
return minetest.get_item_group(node, "connect_to_raillike") == railtype
|
||||
end
|
||||
|
||||
function boost_cart:check_front_up_down(pos, dir_, check_down, railtype)
|
||||
local dir = vector.new(dir_)
|
||||
local cur = nil
|
||||
|
||||
-- Front
|
||||
dir.y = 0
|
||||
cur = vector.add(pos, dir)
|
||||
if boost_cart:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
-- Up
|
||||
if check_down then
|
||||
dir.y = 1
|
||||
cur = vector.add(pos, dir)
|
||||
if boost_cart:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
end
|
||||
-- Down
|
||||
dir.y = -1
|
||||
cur = vector.add(pos, dir)
|
||||
if boost_cart:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
||||
local pos = vector.round(pos_)
|
||||
local cur = nil
|
||||
local left_check, right_check = true, true
|
||||
|
||||
-- Check left and right
|
||||
local left = {x=0, y=0, z=0}
|
||||
local right = {x=0, y=0, z=0}
|
||||
if dir.z ~= 0 and dir.x == 0 then
|
||||
left.x = -dir.z
|
||||
right.x = dir.z
|
||||
elseif dir.x ~= 0 and dir.z == 0 then
|
||||
left.z = dir.x
|
||||
right.z = -dir.x
|
||||
end
|
||||
|
||||
if ctrl then
|
||||
if old_switch == 1 then
|
||||
left_check = false
|
||||
elseif old_switch == 2 then
|
||||
right_check = false
|
||||
end
|
||||
if ctrl.left and left_check then
|
||||
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
|
||||
if cur then
|
||||
return cur, 1
|
||||
end
|
||||
left_check = false
|
||||
end
|
||||
if ctrl.right and right_check then
|
||||
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur, 2
|
||||
end
|
||||
right_check = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Normal
|
||||
cur = boost_cart:check_front_up_down(pos, dir, true, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
|
||||
-- Left, if not already checked
|
||||
if left_check then
|
||||
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
|
||||
-- Right, if not already checked
|
||||
if right_check then
|
||||
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
|
||||
-- Backwards
|
||||
if not old_switch then
|
||||
cur = boost_cart:check_front_up_down(pos, {
|
||||
x = -dir.x,
|
||||
y = dir.y,
|
||||
z = -dir.z
|
||||
}, true, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
|
||||
return {x=0, y=0, z=0}
|
||||
end
|
||||
|
||||
function boost_cart:boost_rail(pos, amount)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount))
|
||||
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
||||
if not obj_:is_player()
|
||||
and obj_:get_luaentity()
|
||||
and obj_:get_luaentity().name == "carts:cart" then
|
||||
obj_:get_luaentity():on_punch()
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,380 +0,0 @@
|
|||
boost_cart = {}
|
||||
boost_cart.modpath = minetest.get_modpath("boost_cart")
|
||||
boost_cart.speed_max = 10
|
||||
|
||||
function vector.floor(v)
|
||||
return {
|
||||
x = math.floor(v.x),
|
||||
y = math.floor(v.y),
|
||||
z = math.floor(v.z)
|
||||
}
|
||||
end
|
||||
|
||||
dofile(boost_cart.modpath.."/functions.lua")
|
||||
dofile(boost_cart.modpath.."/rails.lua")
|
||||
|
||||
-- Support for non-default games
|
||||
if not default.player_attached then
|
||||
default.player_attached = {}
|
||||
end
|
||||
|
||||
boost_cart.cart = {
|
||||
physical = false,
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
visual = "mesh",
|
||||
mesh = "cart.x",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = {"cart.png"},
|
||||
driver = nil,
|
||||
punched = false, -- used to re-send velocity and position
|
||||
velocity = {x=0, y=0, z=0}, -- only used on punch
|
||||
old_dir = {x=0, y=0, z=0},
|
||||
old_pos = nil,
|
||||
old_switch = 0,
|
||||
railtype = nil,
|
||||
attached_items = {},
|
||||
}
|
||||
|
||||
local function get_v(v)
|
||||
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||
end
|
||||
|
||||
function boost_cart.cart:on_rightclick(clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
local player_name = clicker:get_player_name()
|
||||
if self.driver and player_name == self.driver then
|
||||
self.driver = nil
|
||||
clicker:set_detach()
|
||||
elseif not self.driver then
|
||||
self.driver = player_name
|
||||
default.player_attached[player_name] = true
|
||||
clicker:set_attach(self.object, "", {x=0, y=3, z=0}, {x=0, y=0, z=0})
|
||||
end
|
||||
end
|
||||
|
||||
function boost_cart.cart:on_activate(staticdata, dtime_s)
|
||||
|
||||
if mobs and mobs.entity and mobs.entity == false then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
self.driver = nil
|
||||
self.count = 0
|
||||
self.snd = 0
|
||||
self.handle = nil
|
||||
end
|
||||
|
||||
function boost_cart.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||
local pos = self.object:getpos()
|
||||
if not self.railtype then
|
||||
local node = minetest.get_node(vector.floor(pos)).name
|
||||
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
||||
end
|
||||
|
||||
if not puncher or not puncher:is_player() then
|
||||
local cart_dir = boost_cart:get_rail_direction(pos, {x=1, y=0, z=0}, nil, nil, self.railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
self.velocity = vector.multiply(cart_dir, 3)
|
||||
self.old_pos = nil
|
||||
self.punched = true
|
||||
return
|
||||
end
|
||||
|
||||
if puncher:get_player_control().sneak then
|
||||
if self.driver then
|
||||
if self.old_pos then
|
||||
self.object:setpos(self.old_pos)
|
||||
end
|
||||
|
||||
if self.handle then
|
||||
minetest.sound_stop(self.handle)
|
||||
self.handle = nil
|
||||
self.snd = 0
|
||||
end
|
||||
|
||||
default.player_attached[self.driver] = nil
|
||||
local player = minetest.get_player_by_name(self.driver)
|
||||
if player then
|
||||
player:set_detach()
|
||||
end
|
||||
end
|
||||
for _,obj_ in ipairs(self.attached_items) do
|
||||
if obj_ then
|
||||
obj_:set_detach()
|
||||
end
|
||||
end
|
||||
|
||||
local inv = puncher:get_inventory()
|
||||
if inv:room_for_item("main", "carts:cart") then
|
||||
inv:add_item("main", "carts:cart")
|
||||
else
|
||||
minetest.add_item(self.object:getpos(), "carts:cart")
|
||||
end
|
||||
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local vel = self.object:getvelocity()
|
||||
if puncher:get_player_name() == self.driver then
|
||||
if math.abs(vel.x + vel.z) > 7 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local punch_dir = boost_cart:velocity_to_dir(puncher:get_look_dir())
|
||||
punch_dir.y = 0
|
||||
local cart_dir = boost_cart:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
time_from_last_punch = math.min(time_from_last_punch, tool_capabilities.full_punch_interval)
|
||||
local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval)
|
||||
|
||||
self.velocity = vector.multiply(cart_dir, f)
|
||||
self.old_pos = nil
|
||||
self.punched = true
|
||||
end
|
||||
|
||||
function boost_cart.cart:on_step(dtime)
|
||||
|
||||
self.count = self.count + dtime
|
||||
|
||||
-- no driver inside
|
||||
if self.count > 10 and not self.driver then
|
||||
minetest.add_item(self.object:getpos(), "carts:cart")
|
||||
self.object:remove()
|
||||
return
|
||||
|
||||
-- driver inside
|
||||
elseif self.driver then
|
||||
self.count = 0
|
||||
|
||||
-- items inside
|
||||
elseif #self.attached_items > 0 then
|
||||
self.count = 0
|
||||
end
|
||||
|
||||
local vel = self.object:getvelocity()
|
||||
|
||||
local vv = get_v(vel) ; --print ("vel", vv, self.driver)
|
||||
if vv > 1 and self.driver and self.snd == 0 then
|
||||
|
||||
self.handle = minetest.sound_play("cart_ride", {
|
||||
-- to_player = self.player,
|
||||
object = self.object,
|
||||
gain = 1.0,
|
||||
loop = true,
|
||||
})
|
||||
if self.handle then
|
||||
self.snd = 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (vv < 1 or not self.driver) and self.snd == 1 then
|
||||
|
||||
if self.handle then
|
||||
minetest.sound_stop(self.handle)
|
||||
self.handle = nil
|
||||
self.snd = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if self.punched then
|
||||
vel = vector.add(vel, self.velocity)
|
||||
self.object:setvelocity(vel)
|
||||
elseif vector.equals(vel, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
local dir, last_switch = nil, nil
|
||||
local pos = self.object:getpos()
|
||||
if self.old_pos and not self.punched then
|
||||
local flo_pos = vector.floor(pos)
|
||||
local flo_old = vector.floor(self.old_pos)
|
||||
if vector.equals(flo_pos, flo_old) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local update = {}
|
||||
local ctrl, player = nil, nil
|
||||
if self.driver then
|
||||
player = minetest.get_player_by_name(self.driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
end
|
||||
end
|
||||
if self.old_pos then
|
||||
local diff = vector.subtract(self.old_pos, pos)
|
||||
for _,v in ipairs({"x","y","z"}) do
|
||||
if math.abs(diff[v]) > 1.1 then
|
||||
local expected_pos = vector.add(self.old_pos, self.old_dir)
|
||||
dir, last_switch = boost_cart:get_rail_direction(pos, self.old_dir, ctrl, self.old_switch, self.railtype)
|
||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
dir = false
|
||||
pos = vector.new(expected_pos)
|
||||
update.pos = true
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if vel.y == 0 then
|
||||
for _,v in ipairs({"x", "z"}) do
|
||||
if vel[v] ~= 0 and math.abs(vel[v]) < 0.9 then
|
||||
vel[v] = 0
|
||||
update.vel = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cart_dir = boost_cart:velocity_to_dir(vel)
|
||||
local max_vel = boost_cart.speed_max
|
||||
if not dir then
|
||||
dir, last_switch = boost_cart:get_rail_direction(pos, cart_dir, ctrl, self.old_switch, self.railtype)
|
||||
end
|
||||
|
||||
local new_acc = {x=0, y=0, z=0}
|
||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
vel = {x=0, y=0, z=0}
|
||||
update.vel = true
|
||||
else
|
||||
-- If the direction changed
|
||||
if dir.x ~= 0 and self.old_dir.z ~= 0 then
|
||||
vel.x = dir.x * math.abs(vel.z)
|
||||
vel.z = 0
|
||||
pos.z = math.floor(pos.z + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
if dir.z ~= 0 and self.old_dir.x ~= 0 then
|
||||
vel.z = dir.z * math.abs(vel.x)
|
||||
vel.x = 0
|
||||
pos.x = math.floor(pos.x + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
-- Up, down?
|
||||
if dir.y ~= self.old_dir.y then
|
||||
vel.y = dir.y * math.abs(vel.x + vel.z)
|
||||
pos = vector.round(pos)
|
||||
update.pos = true
|
||||
end
|
||||
|
||||
-- Slow down or speed up..
|
||||
local acc = dir.y * -1.8
|
||||
|
||||
local speed_mod = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
|
||||
if speed_mod and speed_mod ~= 0 then
|
||||
if speed_mod > 0 then
|
||||
for _,v in ipairs({"x","y","z"}) do
|
||||
if math.abs(vel[v]) >= max_vel then
|
||||
speed_mod = 0
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
acc = acc + (speed_mod * 8)
|
||||
else
|
||||
acc = acc - 0.4
|
||||
-- Handbrake
|
||||
if ctrl and ctrl.down and math.abs(vel.x + vel.z) > 1.2 then
|
||||
acc = acc - 1.2
|
||||
end
|
||||
end
|
||||
|
||||
new_acc = vector.multiply(dir, acc)
|
||||
end
|
||||
|
||||
self.object:setacceleration(new_acc)
|
||||
self.old_pos = vector.new(pos)
|
||||
self.old_dir = vector.new(dir)
|
||||
self.old_switch = last_switch
|
||||
|
||||
-- Limits
|
||||
for _,v in ipairs({"x","y","z"}) do
|
||||
if math.abs(vel[v]) > max_vel then
|
||||
vel[v] = boost_cart:get_sign(vel[v]) * max_vel
|
||||
update.vel = true
|
||||
end
|
||||
end
|
||||
|
||||
if self.punched then
|
||||
-- Collect dropped items
|
||||
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
if not obj_:is_player() and
|
||||
obj_:get_luaentity() and
|
||||
not obj_:get_luaentity().physical_state and
|
||||
obj_:get_luaentity().name == "__builtin:item" then
|
||||
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
|
||||
self.attached_items[#self.attached_items + 1] = obj_
|
||||
end
|
||||
end
|
||||
self.punched = false
|
||||
end
|
||||
|
||||
if not (update.vel or update.pos) then
|
||||
return
|
||||
end
|
||||
|
||||
local yaw = 0
|
||||
if dir.x < 0 then
|
||||
yaw = 0.5
|
||||
elseif dir.x > 0 then
|
||||
yaw = 1.5
|
||||
elseif dir.z < 0 then
|
||||
yaw = 1
|
||||
end
|
||||
self.object:setyaw(yaw * math.pi)
|
||||
|
||||
local anim = {x=0, y=0}
|
||||
if dir.y == -1 then
|
||||
anim = {x=1, y=1}
|
||||
elseif dir.y == 1 then
|
||||
anim = {x=2, y=2}
|
||||
end
|
||||
self.object:set_animation(anim, 1, 0)
|
||||
|
||||
self.object:setvelocity(vel)
|
||||
if update.pos then
|
||||
self.object:setpos(pos)
|
||||
end
|
||||
update = nil
|
||||
end
|
||||
|
||||
minetest.register_entity(":carts:cart", boost_cart.cart)
|
||||
minetest.register_craftitem(":carts:cart", {
|
||||
description = "Cart",
|
||||
inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"),
|
||||
wield_image = "cart_side.png",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if not pointed_thing.type == "node" then
|
||||
return
|
||||
end
|
||||
if boost_cart:is_rail(pointed_thing.under) then
|
||||
minetest.add_entity(pointed_thing.under, "carts:cart")
|
||||
elseif boost_cart:is_rail(pointed_thing.above) then
|
||||
minetest.add_entity(pointed_thing.above, "carts:cart")
|
||||
else return end
|
||||
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "carts:cart",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
},
|
||||
})
|
Before Width: | Height: | Size: 216 B |
|
@ -1,339 +0,0 @@
|
|||
xof 0303txt 0032
|
||||
|
||||
Frame Root {
|
||||
FrameTransformMatrix {
|
||||
1.000000, 0.000000, 0.000000, 0.000000,
|
||||
0.000000, 0.000000, 1.000000, 0.000000,
|
||||
0.000000, 1.000000,-0.000000, 0.000000,
|
||||
0.000000, 0.000000, 0.000000, 1.000000;;
|
||||
}
|
||||
Frame Cube {
|
||||
FrameTransformMatrix {
|
||||
5.000000, 0.000000,-0.000000, 0.000000,
|
||||
-0.000000, 3.535534, 3.535534, 0.000000,
|
||||
0.000000,-3.535534, 3.535534, 0.000000,
|
||||
0.000000,-3.000000, 3.000000, 1.000000;;
|
||||
}
|
||||
Mesh { //Cube_001 Mesh
|
||||
72;
|
||||
-1.000000; 1.000000;-1.000000;,
|
||||
-1.000000;-1.000000;-1.000000;,
|
||||
1.000000;-1.000000;-1.000000;,
|
||||
1.000000; 1.000000;-1.000000;,
|
||||
-0.833334;-1.000000; 1.000000;,
|
||||
-1.000000;-1.000000; 1.000000;,
|
||||
-1.000000;-0.833333; 1.000000;,
|
||||
-0.833334;-0.833333; 1.000000;,
|
||||
-1.000000;-1.000000;-1.000000;,
|
||||
-1.000000;-1.000000; 1.000000;,
|
||||
0.999999;-1.000001; 1.000000;,
|
||||
1.000000;-1.000000;-1.000000;,
|
||||
0.999999;-1.000001; 1.000000;,
|
||||
0.833332;-1.000000; 1.000000;,
|
||||
0.833333;-0.833334; 1.000000;,
|
||||
1.000000;-0.833334; 1.000000;,
|
||||
0.833332;-1.000000; 1.000000;,
|
||||
-0.833334;-1.000000; 1.000000;,
|
||||
-0.833334;-0.833333; 1.000000;,
|
||||
0.833333;-0.833334; 1.000000;,
|
||||
1.000000; 0.833333; 1.000000;,
|
||||
0.833334; 0.833333; 1.000000;,
|
||||
0.833334; 1.000000; 1.000000;,
|
||||
1.000000; 0.999999; 1.000000;,
|
||||
1.000000;-0.833334; 1.000000;,
|
||||
0.833333;-0.833334; 1.000000;,
|
||||
0.833334; 0.833333; 1.000000;,
|
||||
1.000000; 0.833333; 1.000000;,
|
||||
0.833334; 0.833333; 1.000000;,
|
||||
-0.833333; 0.833333; 1.000000;,
|
||||
-0.833333; 1.000000; 1.000000;,
|
||||
0.833334; 1.000000; 1.000000;,
|
||||
0.833334; 0.833333;-0.800000;,
|
||||
-0.833333; 0.833333;-0.800000;,
|
||||
-0.833333; 0.833333; 1.000000;,
|
||||
0.833334; 0.833333; 1.000000;,
|
||||
-0.833333; 0.833333; 1.000000;,
|
||||
-1.000000; 0.833333; 1.000000;,
|
||||
-1.000000; 1.000000; 1.000000;,
|
||||
-0.833333; 1.000000; 1.000000;,
|
||||
-0.833334;-0.833333; 1.000000;,
|
||||
-1.000000;-0.833333; 1.000000;,
|
||||
-1.000000; 0.833333; 1.000000;,
|
||||
-0.833333; 0.833333; 1.000000;,
|
||||
0.833333;-0.833334;-0.800000;,
|
||||
-0.833334;-0.833333;-0.800000;,
|
||||
-0.833333; 0.833333;-0.800000;,
|
||||
0.833334; 0.833333;-0.800000;,
|
||||
-0.833333; 0.833333;-0.800000;,
|
||||
-0.833334;-0.833333;-0.800000;,
|
||||
-0.833334;-0.833333; 1.000000;,
|
||||
-0.833333; 0.833333; 1.000000;,
|
||||
-0.833334;-0.833333;-0.800000;,
|
||||
0.833333;-0.833334;-0.800000;,
|
||||
0.833333;-0.833334; 1.000000;,
|
||||
-0.833334;-0.833333; 1.000000;,
|
||||
0.833333;-0.833334;-0.800000;,
|
||||
0.833334; 0.833333;-0.800000;,
|
||||
0.833334; 0.833333; 1.000000;,
|
||||
0.833333;-0.833334; 1.000000;,
|
||||
-1.000000; 1.000000;-1.000000;,
|
||||
-1.000000; 1.000000; 1.000000;,
|
||||
-1.000000;-1.000000; 1.000000;,
|
||||
-1.000000;-1.000000;-1.000000;,
|
||||
-1.000000; 1.000000; 1.000000;,
|
||||
-1.000000; 1.000000;-1.000000;,
|
||||
1.000000; 1.000000;-1.000000;,
|
||||
1.000000; 0.999999; 1.000000;,
|
||||
1.000000;-1.000000;-1.000000;,
|
||||
0.999999;-1.000001; 1.000000;,
|
||||
1.000000; 0.999999; 1.000000;,
|
||||
1.000000; 1.000000;-1.000000;;
|
||||
18;
|
||||
4;0;1;2;3;,
|
||||
4;4;5;6;7;,
|
||||
4;8;9;10;11;,
|
||||
4;12;13;14;15;,
|
||||
4;16;17;18;19;,
|
||||
4;20;21;22;23;,
|
||||
4;24;25;26;27;,
|
||||
4;28;29;30;31;,
|
||||
4;32;33;34;35;,
|
||||
4;36;37;38;39;,
|
||||
4;40;41;42;43;,
|
||||
4;44;45;46;47;,
|
||||
4;48;49;50;51;,
|
||||
4;52;53;54;55;,
|
||||
4;56;57;58;59;,
|
||||
4;60;61;62;63;,
|
||||
4;64;65;66;67;,
|
||||
4;68;69;70;71;;
|
||||
MeshNormals { //Cube_001 Normals
|
||||
72;
|
||||
0.000000; 0.000000;-1.000000;,
|
||||
0.000000; 0.000000;-1.000000;,
|
||||
0.000000; 0.000000;-1.000000;,
|
||||
0.000000; 0.000000;-1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
-0.000000;-1.000000;-0.000000;,
|
||||
-0.000000;-1.000000;-0.000000;,
|
||||
-0.000000;-1.000000;-0.000000;,
|
||||
-0.000000;-1.000000;-0.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
-0.000000;-1.000000; 0.000000;,
|
||||
-0.000000;-1.000000; 0.000000;,
|
||||
-0.000000;-1.000000; 0.000000;,
|
||||
-0.000000;-1.000000; 0.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
0.000000;-0.000000; 1.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
-1.000000; 0.000000; 0.000000;,
|
||||
-1.000000; 0.000000; 0.000000;,
|
||||
-1.000000; 0.000000; 0.000000;,
|
||||
-1.000000; 0.000000; 0.000000;,
|
||||
-1.000000; 0.000000;-0.000000;,
|
||||
-1.000000; 0.000000;-0.000000;,
|
||||
-1.000000; 0.000000;-0.000000;,
|
||||
-1.000000; 0.000000;-0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
0.000000; 1.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;,
|
||||
1.000000;-0.000000; 0.000000;;
|
||||
18;
|
||||
4;0;1;2;3;,
|
||||
4;4;5;6;7;,
|
||||
4;8;9;10;11;,
|
||||
4;12;13;14;15;,
|
||||
4;16;17;18;19;,
|
||||
4;20;21;22;23;,
|
||||
4;24;25;26;27;,
|
||||
4;28;29;30;31;,
|
||||
4;32;33;34;35;,
|
||||
4;36;37;38;39;,
|
||||
4;40;41;42;43;,
|
||||
4;44;45;46;47;,
|
||||
4;48;49;50;51;,
|
||||
4;52;53;54;55;,
|
||||
4;56;57;58;59;,
|
||||
4;60;61;62;63;,
|
||||
4;64;65;66;67;,
|
||||
4;68;69;70;71;;
|
||||
} //End of Cube_001 Normals
|
||||
MeshMaterialList { //Cube_001 Material List
|
||||
1;
|
||||
18;
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0;;
|
||||
Material Material {
|
||||
0.640000; 0.640000; 0.640000; 1.000000;;
|
||||
96.078431;
|
||||
0.500000; 0.500000; 0.500000;;
|
||||
0.000000; 0.000000; 0.000000;;
|
||||
TextureFilename {"cart.png";}
|
||||
}
|
||||
} //End of Cube_001 Material List
|
||||
MeshTextureCoords { //Cube_001 UV Coordinates
|
||||
72;
|
||||
0.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 1.000000;,
|
||||
0.000000; 1.000000;,
|
||||
0.031250; 0.500000;,
|
||||
-0.000000; 0.500000;,
|
||||
-0.000000; 0.468750;,
|
||||
0.031250; 0.468750;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.468750; 0.468750;,
|
||||
0.500000; 0.468750;,
|
||||
0.500000; 0.500000;,
|
||||
0.468750; 0.500000;,
|
||||
0.031250; 0.468750;,
|
||||
0.468750; 0.468750;,
|
||||
0.468750; 0.500000;,
|
||||
0.031250; 0.500000;,
|
||||
0.468750; 0.000000;,
|
||||
0.500000; 0.000000;,
|
||||
0.500000; 0.031250;,
|
||||
0.468750; 0.031250;,
|
||||
0.468750; 0.031250;,
|
||||
0.500000; 0.031250;,
|
||||
0.500000; 0.468750;,
|
||||
0.468750; 0.468750;,
|
||||
0.468750; 0.031250;,
|
||||
0.031250; 0.031250;,
|
||||
0.031250; 0.000000;,
|
||||
0.468750; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
0.031250; 0.031250;,
|
||||
0.000000; 0.031250;,
|
||||
0.000000; 0.000000;,
|
||||
0.031250; 0.000000;,
|
||||
0.031250; 0.468750;,
|
||||
-0.000000; 0.468750;,
|
||||
0.000000; 0.031250;,
|
||||
0.031250; 0.031250;,
|
||||
0.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 1.000000;,
|
||||
0.000000; 1.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
0.500000; 0.500000;,
|
||||
0.500000; 0.000000;,
|
||||
1.000000; 0.000000;,
|
||||
1.000000; 0.500000;;
|
||||
} //End of Cube_001 UV Coordinates
|
||||
} //End of Cube_001 Mesh
|
||||
} //End of Cube
|
||||
} //End of Root Frame
|
||||
AnimationSet {
|
||||
Animation {
|
||||
{Cube}
|
||||
AnimationKey { //Position
|
||||
2;
|
||||
4;
|
||||
0;3; 0.000000, 0.000000, 0.000000;;,
|
||||
1;3; 0.000000, 3.000000, 3.000000;;,
|
||||
2;3; 0.000000,-3.000000, 3.000000;;,
|
||||
3;3; 0.000000,-3.000000, 3.000000;;;
|
||||
}
|
||||
AnimationKey { //Rotation
|
||||
0;
|
||||
4;
|
||||
0;4; -1.000000, 0.000000, 0.000000, 0.000000;;,
|
||||
1;4; -0.923880,-0.382683,-0.000000, 0.000000;;,
|
||||
2;4; -0.923880, 0.382683, 0.000000, 0.000000;;,
|
||||
3;4; -0.923880, 0.382683, 0.000000, 0.000000;;;
|
||||
}
|
||||
AnimationKey { //Scale
|
||||
1;
|
||||
4;
|
||||
0;3; 5.000000, 5.000000, 5.000000;;,
|
||||
1;3; 5.000000, 5.000000, 5.000000;;,
|
||||
2;3; 5.000000, 5.000000, 5.000000;;,
|
||||
3;3; 5.000000, 5.000000, 5.000000;;;
|
||||
}
|
||||
}
|
||||
} //End of AnimationSet
|
|
@ -1,115 +0,0 @@
|
|||
minetest.register_node("boost_cart:rail", {
|
||||
description = "Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
inventory_image = "default_rail.png",
|
||||
wield_image = "default_rail.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'boost_cart:rail 15',
|
||||
recipe = {
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
||||
{'default:steel_ingot', 'default:stick', 'default:steel_ingot'},
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
-- Speed up
|
||||
|
||||
minetest.register_node(":carts:powerrail", {
|
||||
description = "Powered rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png", "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
|
||||
inventory_image = "carts_rail_pwr.png",
|
||||
wield_image = "carts_rail_pwr.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
boost_cart:boost_rail(pos, 0.5)
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "carts:powerrail 6",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node(":carts:brakerail", {
|
||||
description = "Brake rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png", "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
|
||||
inventory_image = "carts_rail_brk.png",
|
||||
wield_image = "carts_rail_brk.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
boost_cart:boost_rail(pos, -0.2)
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "carts:brakerail 6",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
|
||||
}
|
||||
})
|
Before Width: | Height: | Size: 147 B |
Before Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 399 B |
|
@ -1,73 +0,0 @@
|
|||
local default_spawn_settings = minetest.setting_get("static_spawnpoint")
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
local players = minetest.get_connected_players()
|
||||
for i,player in ipairs(players) do
|
||||
local function has_compass(player)
|
||||
for _,stack in ipairs(player:get_inventory():get_list("main")) do
|
||||
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
if has_compass(player) then
|
||||
local spawn = beds_player_spawns[player:get_player_name()] or
|
||||
minetest.setting_get("static_spawnpoint") or
|
||||
{x=0,y=0,z=0}
|
||||
pos = player:getpos()
|
||||
dir = player:get_look_yaw()
|
||||
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
|
||||
angle_dir = 90 - math.deg(dir)
|
||||
local angle_relative = (angle_north - angle_dir) % 360
|
||||
local compass_image = math.floor((angle_relative/30) + 0.5)%12
|
||||
|
||||
for j,stack in ipairs(player:get_inventory():get_list("main")) do
|
||||
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 and
|
||||
minetest.get_item_group(stack:get_name(), "compass")-1 ~= compass_image then
|
||||
player:get_inventory():set_stack("main", j, "compass:"..compass_image)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local images = {
|
||||
"compass_0.png",
|
||||
"compass_1.png",
|
||||
"compass_2.png",
|
||||
"compass_3.png",
|
||||
"compass_4.png",
|
||||
"compass_5.png",
|
||||
"compass_6.png",
|
||||
"compass_7.png",
|
||||
"compass_8.png",
|
||||
"compass_9.png",
|
||||
"compass_10.png",
|
||||
"compass_11.png",
|
||||
}
|
||||
|
||||
local i
|
||||
for i,img in ipairs(images) do
|
||||
local inv = 1
|
||||
if i == 1 then
|
||||
inv = 0
|
||||
end
|
||||
minetest.register_tool("compass:"..(i-1), {
|
||||
description = "Compass",
|
||||
inventory_image = img,
|
||||
wield_image = img,
|
||||
stack_max = 1,
|
||||
groups = {not_in_creative_inventory=inv,compass=i, tools = inv}
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'compass:1',
|
||||
recipe = {
|
||||
{'', 'default:iron_ingot', ''},
|
||||
{'default:iron_ingot', 'default_bluestone_dust', 'default:iron_ingot'},
|
||||
{'', 'default:iron_ingot', ''}
|
||||
}
|
||||
})
|
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 360 B |
|
@ -1921,26 +1921,4 @@ minetest.register_node("default:snowblock", {
|
|||
footstep = {name="default_grass_footstep", gain=0.4},
|
||||
}),
|
||||
drop = "default:snow 4",
|
||||
})
|
||||
|
||||
minetest.register_node("default:cobweb", {
|
||||
description = "Cobweb",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.1,
|
||||
stack_max = 64,
|
||||
tiles = {"web.png"},
|
||||
inventory_image = "web.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
liquid_viscosity = 14,
|
||||
liquidtype = "source",
|
||||
liquid_alternative_flowing = "default:cobweb",
|
||||
liquid_alternative_source = "default:cobweb",
|
||||
liquid_renewable = false,
|
||||
liquid_range = 0,
|
||||
walkable = false,
|
||||
groups = {snappy=1,liquid=3,flammable=2, decorative = 1},
|
||||
drop = "farming:string",
|
||||
})
|
||||
|
||||
minetest.register_alias('mobs:cobweb','default:cobweb')
|
||||
})
|
After Width: | Height: | Size: 241 B |
Before Width: | Height: | Size: 271 B |
|
@ -1,5 +1,9 @@
|
|||
Minetest 0.4 mod: fire
|
||||
======================
|
||||
Fire Redo 0.2
|
||||
|
||||
by TenPlus1
|
||||
|
||||
Based on Minetest 0.4 mod: fire with changes by HybridDog
|
||||
=========================================================
|
||||
|
||||
License of source code:
|
||||
-----------------------
|
||||
|
@ -7,14 +11,14 @@ Copyright (C) 2012 Perttu Ahola (celeron55) <celeron55@gmail.com>
|
|||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 3.0 of the License, or
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
|
||||
License of media (textures and sounds)
|
||||
--------------------------------------
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
Authors of media files
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default
|
|
@ -1,37 +1,17 @@
|
|||
-- minetest/fire/init.lua (HybridDog pull request changes)
|
||||
|
||||
-- Tweaked by TenPlus1 to add chest drops, also removed sounds which are now
|
||||
-- handled by Ambience mod.
|
||||
|
||||
|
||||
-- Global namespace for functions
|
||||
|
||||
fire = {}
|
||||
fire.mod = "redo"
|
||||
|
||||
-- initial check to see if fire is disabled
|
||||
local disable_fire = minetest.setting_getbool("disable_fire")
|
||||
-- Register flame nodes
|
||||
|
||||
minetest.register_node("fire:basic_flame", {
|
||||
description = "Basic Flame",
|
||||
drawtype = "plantlike",
|
||||
tiles = {
|
||||
{
|
||||
name = "fire_basic_flame_animated.png",
|
||||
animation = {
|
||||
type="vertical_frames",
|
||||
aspect_w = 16,
|
||||
aspect_h = 16,
|
||||
length = 1
|
||||
},
|
||||
},
|
||||
},
|
||||
inventory_image = "fire_basic_flame.png",
|
||||
paramtype = "light",
|
||||
light_source = 14,
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
sunlight_propagates = true,
|
||||
damage_per_second = 4,
|
||||
groups = {igniter = 2, dig_immediate = 3},
|
||||
drop = '',
|
||||
on_blast = function()
|
||||
end, -- unaffected by explosions
|
||||
})
|
||||
|
||||
minetest.register_node("fire:permanent_flame", {
|
||||
local flamedef = {
|
||||
description = "Permanent Flame",
|
||||
drawtype = "firelike",
|
||||
tiles = {
|
||||
|
@ -56,83 +36,162 @@ minetest.register_node("fire:permanent_flame", {
|
|||
drop = "",
|
||||
|
||||
on_blast = function()
|
||||
end,
|
||||
})
|
||||
end, -- unaffected by explosions
|
||||
}
|
||||
minetest.register_node("fire:permanent_flame", table.copy(flamedef))
|
||||
|
||||
-- compatibility
|
||||
minetest.register_alias("fire:eternal_flame", "fire:permanent_flame")
|
||||
flamedef.description = "Basic Flame"
|
||||
flamedef.drawtype = "plantlike" -- quick draw for basic flame, fancy for permanent
|
||||
|
||||
-- extinguish flames quickly with dedicated ABM
|
||||
minetest.register_abm({
|
||||
nodenames = {"fire:basic_flame"},
|
||||
interval = 7,
|
||||
chance = 2,
|
||||
catch_up = false,
|
||||
action = function(p0, node, _, _)
|
||||
if not disable_fire then return end
|
||||
minetest.set_node(p0, {name = "air"})
|
||||
end,
|
||||
})
|
||||
minetest.register_node("fire:basic_flame", flamedef)
|
||||
|
||||
|
||||
-- Return positions for flames around a burning node
|
||||
|
||||
function fire.find_pos_for_flame_around(pos)
|
||||
return minetest.find_node_near(pos, 1, {"air"})
|
||||
end
|
||||
|
||||
|
||||
-- Detect nearby extinguishing nodes
|
||||
|
||||
function fire.flame_should_extinguish(pos)
|
||||
return minetest.find_node_near(pos, 1, {"group:puts_out_fire"})
|
||||
end
|
||||
|
||||
|
||||
-- Extinguish all flames quickly with water, snow, ice
|
||||
|
||||
-- extinguish flames quickly with water, snow, ice
|
||||
minetest.register_abm({
|
||||
nodenames = {"fire:basic_flame", "fire:permanent_flame"},
|
||||
neighbors = {"group:puts_out_fire"},
|
||||
interval = 3,
|
||||
chance = 2,
|
||||
chance = 1,
|
||||
catch_up = false,
|
||||
action = function(p0, node, _, _)
|
||||
minetest.set_node(p0, {name = "air"})
|
||||
action = function(p0)
|
||||
-- fire node holds no metadata so quickly swap out for air
|
||||
minetest.swap_node(p0, {name = "air"})
|
||||
minetest.sound_play("fire_extinguish_flame",
|
||||
{pos = p0, max_hear_distance = 16, gain = 0.15})
|
||||
{pos = p0, max_hear_distance = 16, gain = 0.25})
|
||||
end,
|
||||
})
|
||||
|
||||
-- ignite neighboring nodes
|
||||
minetest.register_abm({
|
||||
nodenames = {"group:flammable"},
|
||||
neighbors = {"group:igniter"},
|
||||
interval = 7,
|
||||
chance = 16,
|
||||
catch_up = false,
|
||||
action = function(p0, node, _, _)
|
||||
-- check to see if fire is still disabled
|
||||
disable_fire = minetest.setting_getbool("disable_fire")
|
||||
--print ("disable fire set to ", disable_fire)
|
||||
|
||||
-- if there is water or stuff like that around flame, don't ignite
|
||||
if disable_fire
|
||||
or minetest.find_node_near(p0, 1, {"group:puts_out_fire"}) then
|
||||
return
|
||||
-- Enable the following ABMs according to 'disable fire' setting
|
||||
|
||||
if minetest.setting_getbool("disable_fire") then
|
||||
|
||||
-- Remove basic flames only
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"fire:basic_flame"},
|
||||
interval = 7,
|
||||
chance = 1,
|
||||
catch_up = false,
|
||||
action = function(p0)
|
||||
-- fire node holds no metadata so quickly swap out for air
|
||||
minetest.swap_node(p0, {name = "air"})
|
||||
end
|
||||
local p = minetest.find_node_near(p0, 1, {"air"})
|
||||
if p then
|
||||
minetest.set_node(p, {name = "fire:basic_flame"})
|
||||
end
|
||||
end,
|
||||
})
|
||||
})
|
||||
|
||||
-- remove flammable nodes and flame
|
||||
minetest.register_abm({
|
||||
nodenames = {"fire:basic_flame"},
|
||||
interval = 5,
|
||||
chance = 16,
|
||||
catch_up = false,
|
||||
action = function(p0, node, _, _)
|
||||
else
|
||||
|
||||
-- If there are no flammable nodes around flame, remove flame
|
||||
if not minetest.find_node_near(p0, 1, {"group:flammable"}) then
|
||||
minetest.set_node(p0, {name = "air"})
|
||||
return
|
||||
end
|
||||
-- Ignite neighboring nodes, add basic flames
|
||||
|
||||
if math.random(1, 4) == 1 then
|
||||
-- remove a flammable node around flame
|
||||
local p = minetest.find_node_near(p0, 1, {"group:flammable"})
|
||||
if p then
|
||||
minetest.set_node(p, {name = "air"})
|
||||
-- nodeupdate(p)
|
||||
minetest.register_abm({
|
||||
nodenames = {"group:flammable"},
|
||||
neighbors = {"group:igniter"},
|
||||
interval = 7,
|
||||
chance = 16,
|
||||
catch_up = false,
|
||||
action = function(p0)
|
||||
-- If there is water or stuff like that around node, don't ignite
|
||||
if fire.flame_should_extinguish(p0) then
|
||||
return
|
||||
end
|
||||
local p = fire.find_pos_for_flame_around(p0)
|
||||
if p then
|
||||
-- air node holds no metadata so quickly swap out for fire
|
||||
minetest.swap_node(p, {name = "fire:basic_flame"})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Remove basic flames and flammable nodes
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"fire:basic_flame"},
|
||||
interval = 5,
|
||||
chance = 16,
|
||||
catch_up = false,
|
||||
action = function(p0)
|
||||
-- If there are no flammable nodes around flame, remove flame
|
||||
if not minetest.find_node_near(p0, 1, {"group:flammable"}) then
|
||||
-- fire node holds no metadata so quickly swap out for air
|
||||
minetest.swap_node(p0, {name = "air"})
|
||||
return
|
||||
end
|
||||
if math.random(1, 4) ~= 1 then
|
||||
return
|
||||
end
|
||||
-- remove flammable nodes around flame
|
||||
local p = minetest.find_node_near(p0, 1, {"group:flammable"})
|
||||
if not p then
|
||||
return
|
||||
end
|
||||
local node = minetest.get_node(p)
|
||||
local on_burn = minetest.registered_nodes[node.name].on_burn
|
||||
if on_burn then
|
||||
if type(on_burn) == "string" then
|
||||
node.name = on_burn
|
||||
minetest.set_node(p, node)
|
||||
nodeupdate(p)
|
||||
return
|
||||
end
|
||||
if on_burn(p, node) ~= false then
|
||||
return
|
||||
end
|
||||
end
|
||||
minetest.remove_node(p)
|
||||
nodeupdate(p)
|
||||
end,
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- used to drop items inside a chest or container
|
||||
function fire.drop_items(pos, invstring)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
for i = 1, inv:get_size(invstring) do
|
||||
|
||||
local m_stack = inv:get_stack(invstring, i)
|
||||
local obj = minetest.add_item(pos, m_stack)
|
||||
|
||||
if obj then
|
||||
|
||||
obj:setvelocity({
|
||||
x = math.random(-1, 1),
|
||||
y = 3,
|
||||
z = math.random(-1, 1)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- override chest node so that it's flammable
|
||||
minetest.override_item("default:chest", {
|
||||
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3},
|
||||
|
||||
on_burn = function(p)
|
||||
fire.drop_items(p, "main")
|
||||
minetest.remove_node(p)
|
||||
end,
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -15,16 +15,15 @@ if minetest.get_modpath("mobs") ~= nil then
|
|||
if mobs.mod ~= nil and mobs.mod == "redo" then
|
||||
register_food("mobs:cheese", 4)
|
||||
register_food("mobs:meat", 8)
|
||||
register_food("mobs:meat_raw", 4, "", 2)
|
||||
register_food("mobs:meat_raw", 4, "", 3)
|
||||
register_food("mobs:rat_cooked", 4)
|
||||
register_food("mobs:rat_meat", 2)
|
||||
register_food("mobs:honey", 2)
|
||||
register_food("mobs:pork_raw", 4, "", 2)
|
||||
register_food("mobs:pork_raw", 3, "", 3)
|
||||
register_food("mobs:pork_cooked", 8)
|
||||
register_food("mobs:chicken_cooked", 6)
|
||||
register_food("mobs:chicken_raw", 2, "", 2)
|
||||
register_food("mobs:chicken_raw", 2, "", 3)
|
||||
register_food("mobs:chicken_egg_fried", 2)
|
||||
register_food("mobs:rotten_flesh", 1, "", 5)
|
||||
if minetest.get_modpath("bucket") then
|
||||
register_food("mobs:bucket_milk", 3, "bucket:bucket_empty")
|
||||
end
|
||||
|
|
|
@ -22,11 +22,11 @@ dofile(path.."/spider.lua") -- AspireMint
|
|||
dofile(path.."/zombie.lua") -- Blockmen
|
||||
dofile(path.."/skeleton.lua") -- Blockmen
|
||||
|
||||
-- NPC
|
||||
dofile(path.."/npc.lua") -- TenPlus1
|
||||
|
||||
-- Mob Items
|
||||
dofile(path.."/crafts.lua")
|
||||
|
||||
-- Spawner
|
||||
dofile(path.."/spawner.lua")
|
||||
dofile(path.."/spawner.lua")
|
||||
|
||||
-- Remove
|
||||
dofile(path.."/npc.lua")
|
|
@ -75,7 +75,7 @@ minetest.register_node("mobs:cobweb", {
|
|||
liquid_range = 0,
|
||||
walkable = false,
|
||||
groups = {snappy = 1, liquid = 3},
|
||||
drop = "farming:cotton",
|
||||
--drop = "farming:cotton",
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
|
|
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 127 B After Width: | Height: | Size: 127 B |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 573 B After Width: | Height: | Size: 573 B |
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 129 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
|
@ -0,0 +1,21 @@
|
|||
Minetest Mod - Railcart [railcart]
|
||||
==================================
|
||||
|
||||
License Source Code: LGPL v2.1
|
||||
|
||||
License of media (textures, sounds and models not otherwise specified): CC-0
|
||||
|
||||
Authors of media files:
|
||||
-----------------------
|
||||
|
||||
HybridDog: WTFPL
|
||||
|
||||
cart.png
|
||||
cart_bottom.png
|
||||
cart_side.png
|
||||
cart_top.png
|
||||
|
||||
Zeg9:
|
||||
|
||||
cart.x
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
Minetest Mod - Railcart [railcart]
|
||||
==================================
|
||||
|
||||
Minetest version: 0.4.13
|
||||
|
||||
Depends: railtrack
|
||||
|
||||
Proof of concept ground up re-write of the carts mod. Currently uses media files
|
||||
borrowed from the original carts mod by PilzAdam.
|
||||
|
||||
Please note, this mod makes heavy use of metadata so that carts are able to
|
||||
travel through unloaded map chunks, therefor a 'carts' privilege is required
|
||||
to place or pick up carts in multiplayer mode.
|
||||
|
||||
Crafting
|
||||
--------
|
||||
|
||||
S = Steel Ingot [default:steel_ingot]
|
||||
W = Wood [group:wood]
|
||||
|
||||
Railcart: [railcart:cart]
|
||||
|
||||
+---+---+---+
|
||||
| S | | S |
|
||||
+---+---+---+
|
||||
| S | | S |
|
||||
+---+---+---+
|
||||
| W | S | W |
|
||||
+---+---+---+
|
||||
|
|
@ -0,0 +1 @@
|
|||
railtrack
|
|
@ -0,0 +1,191 @@
|
|||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
dofile(modpath.."/railcart.lua")
|
||||
|
||||
local worldpath = minetest.get_worldpath()
|
||||
|
||||
local function create_detached_inventory(id)
|
||||
local inv = minetest.create_detached_inventory("railcart_"..tostring(id), {
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
railcart:save()
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
railcart:save()
|
||||
end,
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
return 1
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
return count
|
||||
end,
|
||||
})
|
||||
inv:set_size("main", 32)
|
||||
return inv
|
||||
end
|
||||
|
||||
local input = io.open(worldpath.."/railcart.txt", "r")
|
||||
if input then
|
||||
local data = input:read('*all')
|
||||
if data then
|
||||
local carts = minetest.deserialize(data) or {}
|
||||
for id, ref in pairs(carts) do
|
||||
local cart = railcart.cart:new(ref)
|
||||
if ref.inv then
|
||||
local inv = create_detached_inventory(cart.id)
|
||||
for i, stack in pairs(ref.inv) do
|
||||
inv:set_stack("main", i, stack)
|
||||
end
|
||||
cart.inv = inv
|
||||
end
|
||||
railcart.allcarts[id] = cart
|
||||
end
|
||||
end
|
||||
input = nil
|
||||
end
|
||||
|
||||
local function is_valid_player(object)
|
||||
if object then
|
||||
return object:is_player()
|
||||
end
|
||||
end
|
||||
|
||||
railcart:register_entity("railcart:cart_entity", {
|
||||
on_punch = function(self, puncher, _, _, direction)
|
||||
if not is_valid_player(puncher) then
|
||||
return
|
||||
end
|
||||
if puncher:get_player_control().sneak then
|
||||
if self.cart then
|
||||
if self.cart.id then
|
||||
if self.cart.inv then
|
||||
if not self.cart.inv:is_empty("main") then
|
||||
return
|
||||
end
|
||||
end
|
||||
railcart:remove_cart(self.cart.id)
|
||||
end
|
||||
end
|
||||
self.object:remove()
|
||||
local inv = puncher:get_inventory()
|
||||
if minetest.setting_getbool("creative_mode") then
|
||||
if not inv:contains_item("main", "railcart:cart") then
|
||||
inv:add_item("main", "railcart:cart")
|
||||
end
|
||||
else
|
||||
inv:add_item("main", "railcart:cart")
|
||||
end
|
||||
return
|
||||
end
|
||||
if self.cart and direction then
|
||||
if self.driver then
|
||||
direction = {x=0, y=0, z=0}
|
||||
local ld = self.driver:get_look_dir()
|
||||
if ld.y > -0.99 then
|
||||
direction = {
|
||||
x = railtrack:get_sign(ld.x),
|
||||
z = railtrack:get_sign(ld.z),
|
||||
y = self.cart.dir.y
|
||||
}
|
||||
end
|
||||
end
|
||||
local pos = vector.round(self.object:getpos())
|
||||
local dir = vector.round(vector.normalize(direction))
|
||||
local speed = railcart:velocity_to_speed(self.cart.vel)
|
||||
self.timer = 0
|
||||
self.cart.target = nil
|
||||
self.cart.prev = pos
|
||||
self.cart.vel = vector.multiply(dir, 5)
|
||||
self.cart.accel = railtrack:get_acceleration(pos)
|
||||
self.object:setvelocity(self.cart.vel)
|
||||
end
|
||||
end,
|
||||
on_rightclick = function(self, clicker)
|
||||
if not is_valid_player(clicker) then
|
||||
return
|
||||
end
|
||||
if clicker:get_player_control().sneak then
|
||||
local name = clicker:get_player_name()
|
||||
local cart = self.cart or {}
|
||||
if cart.id and name then
|
||||
local formspec = "size[8,9]"..
|
||||
default.gui_bg..default.gui_bg_img..default.gui_slots..
|
||||
"list[detached:railcart_"..cart.id..";main;0,0.3;8,4;]"..
|
||||
"list[current_player;main;0,4.85;8,1;]"..
|
||||
"list[current_player;main;0,6.08;8,3;8]"..
|
||||
"listring[detached:railcart_"..cart.id..";main]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0,4.85)
|
||||
minetest.show_formspec(name, "inventory", formspec)
|
||||
end
|
||||
return
|
||||
end
|
||||
if self.driver and clicker == self.driver then
|
||||
self.driver = nil
|
||||
clicker:set_detach()
|
||||
elseif not self.driver then
|
||||
self.driver = clicker
|
||||
clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("railcart:cart", {
|
||||
description = "Railcart",
|
||||
inventory_image = minetest.inventorycube("railcart_top.png", "railcart_side.png", "railcart_side.png"),
|
||||
wield_image = "railcart_side.png",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local name = placer:get_player_name()
|
||||
if not name or pointed_thing.type ~= "node" then
|
||||
return
|
||||
end
|
||||
if not minetest.is_singleplayer() then
|
||||
if not minetest.check_player_privs(name, {carts=true}) then
|
||||
minetest.chat_send_player(name, "Requires carts privilege")
|
||||
return
|
||||
end
|
||||
end
|
||||
local pos = pointed_thing.under
|
||||
if not railtrack:is_railnode(pos) then
|
||||
return
|
||||
end
|
||||
local carts = railcart:get_carts_in_radius(pos, 0.9)
|
||||
if #carts > 0 then
|
||||
return
|
||||
end
|
||||
local id = railcart:get_new_id()
|
||||
local ref = {
|
||||
id = id,
|
||||
inv = create_detached_inventory(id),
|
||||
pos = vector.new(pos),
|
||||
prev = vector.new(pos),
|
||||
accel = railtrack:get_acceleration(pos),
|
||||
dir = railcart:get_rail_direction(pos),
|
||||
}
|
||||
local cart = railcart.cart:new(ref)
|
||||
table.insert(railcart.allcarts, cart)
|
||||
railcart:save()
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_privilege("carts", "Player can pick-up and place carts.")
|
||||
|
||||
minetest.register_craft({
|
||||
output = "railcart:cart",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||
{"group:wood", "default:steel_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
railcart:save()
|
||||
end)
|
||||
|
|
@ -0,0 +1,444 @@
|
|||
local ENTITY_UPDATE_TIME = 1
|
||||
local OBJECT_UPDATE_TIME = 5
|
||||
local OBJECT_SAVE_TIME = 10
|
||||
local RELOAD_DISTANCE = 32
|
||||
local SNAP_DISTANCE = 0.5
|
||||
local SPEED_MIN = 0.1
|
||||
local SPEED_MAX = 15
|
||||
|
||||
railcart = {
|
||||
timer = 0,
|
||||
allcarts = {},
|
||||
default_entity = {
|
||||
physical = false,
|
||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||
visual = "mesh",
|
||||
mesh = "railcart.b3d",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = {"railcart.png"},
|
||||
cart = nil,
|
||||
driver = nil,
|
||||
timer = 0,
|
||||
},
|
||||
}
|
||||
|
||||
railcart.cart = {
|
||||
id = nil,
|
||||
pos = nil,
|
||||
target = nil,
|
||||
prev = nil,
|
||||
accel = nil,
|
||||
inv = nil,
|
||||
dir = {x=0, y=0, z=0},
|
||||
vel = {x=0, y=0, z=0},
|
||||
acc = {x=0, y=0, z=0},
|
||||
timer = 0,
|
||||
name = "railcart:cart_entity",
|
||||
}
|
||||
|
||||
function railcart.cart:new(obj)
|
||||
obj = obj or {}
|
||||
setmetatable(obj, self)
|
||||
self.__index = self
|
||||
return obj
|
||||
end
|
||||
|
||||
function railcart.cart:is_loaded()
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local pos = player:getpos()
|
||||
if pos then
|
||||
local dist = railtrack:get_distance(pos, self.pos)
|
||||
if dist <= RELOAD_DISTANCE then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function railcart.cart:on_step(dtime)
|
||||
self.timer = self.timer - dtime
|
||||
if self.timer > 0 then
|
||||
return
|
||||
end
|
||||
self.timer = OBJECT_UPDATE_TIME
|
||||
local entity = railcart:get_cart_entity(self.id)
|
||||
if entity.object then
|
||||
return
|
||||
end
|
||||
if self:is_loaded() then
|
||||
local object = minetest.add_entity(self.pos, self.name)
|
||||
if object then
|
||||
entity = object:get_luaentity() or {}
|
||||
entity.cart = self
|
||||
object:setvelocity(self.vel)
|
||||
object:setacceleration(self.acc)
|
||||
end
|
||||
else
|
||||
self.timer = railcart:update(self, self.timer)
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:register_entity(name, def)
|
||||
local ref = {}
|
||||
for k, v in pairs(railcart.default_entity) do
|
||||
ref[k] = def[k] or railtrack:copy(v)
|
||||
end
|
||||
ref.on_activate = function(self, staticdata, dtime_s)
|
||||
if type(def.on_activate) == "function" then
|
||||
def.on_activate(self, staticdata, dtime_s)
|
||||
end
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
if staticdata == "expired" then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
ref.on_step = function(self, dtime)
|
||||
if type(def.on_step) == "function" then
|
||||
def.on_step(self, dtime)
|
||||
end
|
||||
local cart = self.cart
|
||||
local object = self.object
|
||||
if not cart or not object then
|
||||
return
|
||||
end
|
||||
self.timer = self.timer - dtime
|
||||
if self.timer > 0 then
|
||||
return
|
||||
end
|
||||
self.timer = railcart:update(cart, ENTITY_UPDATE_TIME, object)
|
||||
if type(def.on_update) == "function" then
|
||||
def.on_update(self)
|
||||
end
|
||||
end
|
||||
ref.get_staticdata = function(self)
|
||||
if type(def.get_staticdata) == "function" then
|
||||
def.get_staticdata(self)
|
||||
end
|
||||
if self.cart then
|
||||
if self.cart:is_loaded() == false then
|
||||
self.cart.timer = 0
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
return "expired"
|
||||
end
|
||||
for k, v in pairs(def) do
|
||||
ref[k] = ref[k] or v
|
||||
end
|
||||
minetest.register_entity(name, ref)
|
||||
end
|
||||
|
||||
function railcart:save()
|
||||
local carts = {}
|
||||
for id, cart in pairs(railcart.allcarts) do
|
||||
local ref = {}
|
||||
for k, v in pairs(cart) do
|
||||
ref[k] = v
|
||||
end
|
||||
local inv = {}
|
||||
if ref.inv then
|
||||
local list = ref.inv:get_list("main")
|
||||
for i, stack in ipairs(list) do
|
||||
inv[i] = stack:to_string()
|
||||
end
|
||||
end
|
||||
ref.inv = inv
|
||||
table.insert(carts, ref)
|
||||
end
|
||||
local output = io.open(minetest.get_worldpath().."/railcart.txt",'w')
|
||||
if output then
|
||||
output:write(minetest.serialize(carts))
|
||||
io.close(output)
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:remove_cart(id)
|
||||
for i, cart in pairs(railcart.allcarts) do
|
||||
if cart.id == id then
|
||||
railcart.allcarts[i] = nil
|
||||
railcart:save()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:get_rail_direction(pos)
|
||||
local target = nil
|
||||
local cons = railtrack:get_connections(pos)
|
||||
local ymax = pos.y
|
||||
for _, con in pairs(cons) do
|
||||
if con.y >= ymax then
|
||||
ymax = con.y
|
||||
target = con
|
||||
end
|
||||
end
|
||||
if target then
|
||||
if #cons == 1 then
|
||||
target.y = pos.y
|
||||
end
|
||||
return railtrack:get_direction(target, pos)
|
||||
end
|
||||
return {x=0, y=0, z=0}
|
||||
end
|
||||
|
||||
function railcart:get_new_id()
|
||||
local id = 0
|
||||
for _, cart in pairs(railcart.allcarts) do
|
||||
if cart.id > id then
|
||||
id = cart.id
|
||||
end
|
||||
end
|
||||
return id + 1
|
||||
end
|
||||
|
||||
function railcart:get_cart_ref(id)
|
||||
for _, cart in pairs(railcart.allcarts) do
|
||||
if cart.id == id then
|
||||
return cart
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:get_cart_entity(id)
|
||||
local cart_ref = {}
|
||||
for _, ref in pairs(minetest.luaentities) do
|
||||
if ref.cart then
|
||||
if ref.cart.id == id then
|
||||
cart_ref = ref
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return cart_ref
|
||||
end
|
||||
|
||||
function railcart:get_carts_in_radius(pos, rad)
|
||||
local carts = {}
|
||||
for _, cart in pairs(railcart.allcarts) do
|
||||
local px = pos.x - cart.pos.x
|
||||
local py = pos.y - cart.pos.y
|
||||
local pz = pos.z - cart.pos.z
|
||||
if (px * px) + (py * py) + (pz * pz) <= rad * rad then
|
||||
table.insert(carts, cart)
|
||||
end
|
||||
end
|
||||
return carts
|
||||
end
|
||||
|
||||
function railcart:get_cart_in_sight(p1, p2)
|
||||
local ref = nil
|
||||
local dist = railtrack:get_distance(p1, p2) + 1
|
||||
local dir = railtrack:get_direction(p2, p1)
|
||||
local carts = railcart:get_carts_in_radius(p1, dist)
|
||||
for _, cart in pairs(carts) do
|
||||
if not vector.equals(p1, cart.pos) then
|
||||
local dc = railtrack:get_direction(cart.pos, p1)
|
||||
if vector.equals(dc, dir) then
|
||||
local d = railtrack:get_distance(p1, cart.pos)
|
||||
if d < dist then
|
||||
dist = d
|
||||
ref = cart
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return ref
|
||||
end
|
||||
|
||||
function railcart:get_delta_time(vel, acc, dist)
|
||||
if vel > 0 then
|
||||
if acc == 0 then
|
||||
return dist / vel
|
||||
end
|
||||
local r = math.sqrt(vel * vel + 2 * acc * dist)
|
||||
if r > 0 then
|
||||
return (-vel + r) / acc
|
||||
end
|
||||
end
|
||||
return 9999 --INF
|
||||
end
|
||||
|
||||
function railcart:velocity_to_dir(v)
|
||||
if math.abs(v.x) > math.abs(v.z) then
|
||||
return {x=railtrack:get_sign(v.x), y=railtrack:get_sign(v.y), z=0}
|
||||
else
|
||||
return {x=0, y=railtrack:get_sign(v.y), z=railtrack:get_sign(v.z)}
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:velocity_to_speed(vel)
|
||||
local speed = math.max(math.abs(vel.x), math.abs(vel.z))
|
||||
if speed < SPEED_MIN then
|
||||
speed = 0
|
||||
elseif speed > SPEED_MAX then
|
||||
speed = SPEED_MAX
|
||||
end
|
||||
return speed
|
||||
end
|
||||
|
||||
function railcart:get_target(pos, vel)
|
||||
local meta = minetest.get_meta(vector.round(pos))
|
||||
local dir = self:velocity_to_dir(vel)
|
||||
local targets = {}
|
||||
local rots = railtrack.rotations
|
||||
local contype = meta:get_string("contype") or ""
|
||||
local s_junc = meta:get_string("junctions") or ""
|
||||
local s_cons = meta:get_string("connections") or ""
|
||||
local s_rots = meta:get_string("rotations") or ""
|
||||
if contype == "section" then
|
||||
local junctions = minetest.deserialize(s_junc) or {}
|
||||
for _, p in pairs(junctions) do
|
||||
table.insert(targets, p)
|
||||
end
|
||||
else
|
||||
local cons = minetest.deserialize(s_cons) or {}
|
||||
for _, p in pairs(cons) do
|
||||
table.insert(targets, p)
|
||||
end
|
||||
if s_rots ~= "" then
|
||||
local fwd = false
|
||||
for _, p in pairs(cons) do
|
||||
if vector.equals(vector.add(pos, dir), p) then
|
||||
fwd = true
|
||||
end
|
||||
end
|
||||
if fwd == true or #cons == 1 then
|
||||
rots = s_rots
|
||||
end
|
||||
end
|
||||
end
|
||||
local rotations = railtrack:get_rotations(rots, dir)
|
||||
for _, r in ipairs(rotations) do
|
||||
for _, t in pairs(targets) do
|
||||
local d = railtrack:get_direction(t, pos)
|
||||
if r.x == d.x and r.z == d.z then
|
||||
return t
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function railcart:update(cart, time, object)
|
||||
if object then
|
||||
cart.pos = object:getpos()
|
||||
cart.vel = object:getvelocity()
|
||||
end
|
||||
if not cart.target then
|
||||
cart.pos = vector.new(cart.prev)
|
||||
cart.target = railcart:get_target(cart.pos, cart.vel)
|
||||
if object then
|
||||
object:moveto(cart.pos)
|
||||
end
|
||||
end
|
||||
local speed = railcart:velocity_to_speed(cart.vel)
|
||||
if cart.target then
|
||||
cart.dir = railtrack:get_direction(cart.target, cart.pos)
|
||||
else
|
||||
speed = 0
|
||||
end
|
||||
if speed > SPEED_MIN then
|
||||
local blocked = false
|
||||
local cis = railcart:get_cart_in_sight(cart.pos, cart.target)
|
||||
if cis then
|
||||
if railcart:velocity_to_speed(cis.vel) == 0 then
|
||||
cart.target = vector.subtract(cis.pos, cart.dir)
|
||||
blocked = true
|
||||
end
|
||||
end
|
||||
--[[
|
||||
if object then
|
||||
local p1 = vector.add(cart.pos, {x=0, y=1, z=0})
|
||||
local p2 = vector.add(cart.target, {x=0, y=1, z=0})
|
||||
if minetest.get_node_or_nil(p2) then
|
||||
local los, bp = minetest.line_of_sight(p1, p2)
|
||||
if los == false then
|
||||
bp.y = bp.y - 1
|
||||
cart.target = vector.subtract(bp, cart.dir)
|
||||
blocked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
]]--
|
||||
local d1 = railtrack:get_distance(cart.prev, cart.target)
|
||||
local d2 = railtrack:get_distance(cart.prev, cart.pos)
|
||||
local dist = d1 - d2
|
||||
if dist > SNAP_DISTANCE then
|
||||
local accel = railtrack.accel_flat
|
||||
if cart.dir.y == -1 then
|
||||
accel = railtrack.accel_down
|
||||
elseif cart.dir.y == 1 then
|
||||
accel = railtrack.accel_up
|
||||
end
|
||||
accel = cart.accel or accel
|
||||
if object then
|
||||
dist = math.max(dist - SNAP_DISTANCE, 0)
|
||||
end
|
||||
local dt = railcart:get_delta_time(speed, accel, dist)
|
||||
if dt < time then
|
||||
time = dt
|
||||
end
|
||||
local dp = speed * time + 0.5 * accel * time * time
|
||||
local vf = speed + accel * time
|
||||
if object then
|
||||
if vf <= 0 then
|
||||
speed = 0
|
||||
accel = 0
|
||||
end
|
||||
cart.vel = vector.multiply(cart.dir, speed)
|
||||
cart.acc = vector.multiply(cart.dir, accel)
|
||||
elseif dp > 0 then
|
||||
cart.vel = vector.multiply(cart.dir, vf)
|
||||
cart.pos = vector.add(cart.pos, vector.multiply(cart.dir, dp))
|
||||
end
|
||||
else
|
||||
if blocked and vector.equals(cart.target, cart.prev) then
|
||||
cart.vel = {x=0, y=0, z=0}
|
||||
cart.acc = {x=0, y=0, z=0}
|
||||
else
|
||||
cart.pos = vector.new(cart.target)
|
||||
cart.prev = vector.new(cart.target)
|
||||
cart.accel = railtrack:get_acceleration(cart.target)
|
||||
cart.target = nil
|
||||
return 0
|
||||
end
|
||||
end
|
||||
else
|
||||
cart.dir = railcart:get_rail_direction(cart.pos)
|
||||
cart.vel = {x=0, y=0, z=0}
|
||||
cart.acc = {x=0, y=0, z=0}
|
||||
end
|
||||
if object then
|
||||
if cart.dir.y == -1 then
|
||||
object:set_animation({x=1, y=1}, 1, 0)
|
||||
elseif cart.dir.y == 1 then
|
||||
object:set_animation({x=2, y=2}, 1, 0)
|
||||
else
|
||||
object:set_animation({x=0, y=0}, 1, 0)
|
||||
end
|
||||
if cart.dir.x < 0 then
|
||||
object:setyaw(math.pi / 2)
|
||||
elseif cart.dir.x > 0 then
|
||||
object:setyaw(3 * math.pi / 2)
|
||||
elseif cart.dir.z < 0 then
|
||||
object:setyaw(math.pi)
|
||||
elseif cart.dir.z > 0 then
|
||||
object:setyaw(0)
|
||||
end
|
||||
object:setvelocity(cart.vel)
|
||||
object:setacceleration(cart.acc)
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, cart in pairs(railcart.allcarts) do
|
||||
cart:on_step(dtime)
|
||||
end
|
||||
railcart.timer = railcart.timer + dtime
|
||||
if railcart.timer > OBJECT_SAVE_TIME then
|
||||
railcart:save()
|
||||
railcart.timer = 0
|
||||
end
|
||||
end)
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 413 B |
|
@ -0,0 +1,14 @@
|
|||
Minetest Mod - Railtrack [railtrack]
|
||||
====================================
|
||||
|
||||
License Source Code: LGPL v2.1
|
||||
|
||||
License of media (textures, sounds and models not otherwise specified): CC-0
|
||||
|
||||
Authors of media files:
|
||||
-----------------------
|
||||
|
||||
rarkenin:
|
||||
|
||||
cart_rail_*.png
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
Minetest Mod - Railtrack [railtrack]
|
||||
====================================
|
||||
|
||||
Minetest version: 0.4.13
|
||||
|
||||
Depends: default
|
||||
|
||||
Proof of concept rail networking system which enables rail-carts to travel
|
||||
through unloaded map chunks.
|
||||
|
||||
Please note, this mod makes heavy use of metadata so that much of the processing
|
||||
gets done as tracks are laid, for this reason a 'rails' privilege is required in
|
||||
order to place rails when using multiplayer mode.
|
||||
|
||||
Crafting
|
||||
--------
|
||||
|
||||
R = Rail [default:rail]
|
||||
F = Mese Crystal Fragment [default:mese_crystal_fragment]
|
||||
C = Coal Lump [default:coal_lump]
|
||||
D = Diamond [default:diamond]
|
||||
M = Mese Block [default:mese]
|
||||
|
||||
Powered Rail: [railtrack:powerrail]
|
||||
|
||||
By default these rails apply a positive acceleration during the time a cart
|
||||
remains on a given section of track. When used with the mesecons mod the rails
|
||||
will require power from a mesecon source to become active.
|
||||
|
||||
+---+---+---+
|
||||
| R | F | R |
|
||||
+---+---+---+
|
||||
|
||||
Braking Rail: [railtrack:brakerail]
|
||||
|
||||
By default these rails apply a negative acceleration during the time a cart
|
||||
remains on a given section of track. When used with the mesecons mod the rails
|
||||
will require power from a mesecon source to become active.
|
||||
|
||||
+---+---+---+
|
||||
| R | C | R |
|
||||
+---+---+---+
|
||||
|
||||
Superconducting Rail: [railtrack:superrail]
|
||||
|
||||
Zero friction rails that are easier to manage and are also a little less
|
||||
cpu-intensive by avoiding the use of square root calculations.
|
||||
|
||||
+---+---+---+
|
||||
| R | D | R |
|
||||
+---+---+---+
|
||||
|
||||
Switching Rail: [railtrack:switchrail]
|
||||
|
||||
Currently depends on mesecons to do much other than provide a convenient, zero
|
||||
friction union to join long sections of superconducting rails.
|
||||
|
||||
+---+---+---+
|
||||
| R | M | R |
|
||||
+---+---+---+
|
||||
|
||||
Misc Items
|
||||
----------
|
||||
|
||||
Rail Fixer: [railtrack:fixer]
|
||||
|
||||
Only available in creative menu or with give(me) privileges.
|
||||
|
||||
Rail Inspector [railtrack:inspector]
|
||||
|
||||
Only available in creative menu or with give(me) privileges.
|
||||
|
|
@ -0,0 +1 @@
|
|||
default
|
|
@ -0,0 +1,200 @@
|
|||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
dofile(modpath.."/railtrack.lua")
|
||||
|
||||
railtrack:register_rail(":default:rail", {
|
||||
description = "Rail",
|
||||
tiles = {"default_rail.png", "default_rail_curved.png",
|
||||
"default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
railtype = "rail",
|
||||
})
|
||||
|
||||
railtrack:register_rail("railtrack:superrail", {
|
||||
description = "Superconducting Rail",
|
||||
tiles = {"carts_rail_sup.png", "carts_rail_curved_sup.png",
|
||||
"carts_rail_t_junction_sup.png", "carts_rail_crossing_sup.png"},
|
||||
railtype = "superrail",
|
||||
acceleration = 0,
|
||||
})
|
||||
|
||||
railtrack:register_rail("railtrack:powerrail", {
|
||||
description = "Powered Rail",
|
||||
tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png",
|
||||
"carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
|
||||
railtype = "powerrail",
|
||||
acceleration = 4,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
railtrack:set_acceleration(pos, 4)
|
||||
end,
|
||||
action_off = function(pos, node)
|
||||
railtrack:set_acceleration(pos, nil)
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
railtrack:register_rail("railtrack:brakerail", {
|
||||
description = "Braking Rail",
|
||||
tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png",
|
||||
"carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
|
||||
railtype = "brakerail",
|
||||
acceleration = -4,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
railtrack:set_acceleration(pos, -4)
|
||||
end,
|
||||
action_off = function(pos, node)
|
||||
railtrack:set_acceleration(pos, nil)
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
railtrack:register_rail("railtrack:switchrail", {
|
||||
description = "Switching Rail",
|
||||
tiles = {"carts_rail_swt.png", "carts_rail_curved_swt.png",
|
||||
"carts_rail_t_junction_swt.png", "carts_rail_crossing_swt.png"},
|
||||
railtype = "switchrail",
|
||||
acceleration = 0,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("rotations", "RFLB")
|
||||
end,
|
||||
action_off = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("rotations", nil)
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_privilege("rails", "Player can dig and place rails.")
|
||||
|
||||
minetest.register_tool("railtrack:fixer", {
|
||||
description = "Rail Fixer",
|
||||
inventory_image = "railtrack_fixer.png",
|
||||
wield_image = "railtrack_fixer.png",
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
|
||||
local name = user:get_player_name()
|
||||
if not pos or not name or pointed_thing.type ~= "node" then
|
||||
return
|
||||
end
|
||||
if not railtrack:is_railnode(pos) then
|
||||
minetest.chat_send_player(name, "Not a rail node!")
|
||||
return
|
||||
end
|
||||
if not minetest.is_singleplayer() then
|
||||
if not minetest.check_player_privs(name, {rails=true}) then
|
||||
minetest.chat_send_player(name, "Requires rails privilege")
|
||||
return
|
||||
end
|
||||
end
|
||||
local node = minetest.get_node(pos)
|
||||
if node then
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(pos, node)
|
||||
local def = minetest.registered_items[node.name] or {}
|
||||
local itemstack = ItemStack(node.name)
|
||||
if type(def.after_place_node) == "function" then
|
||||
def.after_place_node(pos, user, itemstack)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_tool("railtrack:inspector", {
|
||||
description = "Rail Inspector",
|
||||
inventory_image = "railtrack_inspector.png",
|
||||
wield_image = "railtrack_inspector.png",
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
local name = user:get_player_name()
|
||||
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
|
||||
if not name or not pos then
|
||||
return
|
||||
end
|
||||
local node = minetest.get_node(pos) or {}
|
||||
if not railtrack:is_railnode(pos) or not node.name then
|
||||
minetest.chat_send_player(name, "Not a rail node!")
|
||||
return
|
||||
end
|
||||
local ref = minetest.registered_items[node.name] or {}
|
||||
local meta = minetest.get_meta(pos)
|
||||
local form = ""
|
||||
local size = 2.5
|
||||
form = form.."label[0.5,0.5;POS: "..minetest.pos_to_string(pos).."]"
|
||||
local railtype = ref.railtype or "NIL"
|
||||
form = form.."label[0.5,1.0;RAILTYPE: "..railtype.."]"
|
||||
local contype = meta:get_string("contype") or "NIL"
|
||||
form = form.."label[0.5,1.5;CONTYPE: "..contype.."]"
|
||||
local accel = meta:get_string("acceleration") or "NIL"
|
||||
form = form.."label[0.5,2.0;ACCEL: "..accel.."]"
|
||||
local s_junc = meta:get_string("junctions")
|
||||
if s_junc then
|
||||
local junctions = minetest.deserialize(s_junc)
|
||||
if junctions then
|
||||
form = form.."label[0.5,2.5;JUNCTIONS:]"
|
||||
for i, p in ipairs(junctions) do
|
||||
size = size + 0.5
|
||||
form = form.."label[0.5,"..size..";#"..i.." "
|
||||
..minetest.pos_to_string(p).."]"
|
||||
end
|
||||
end
|
||||
end
|
||||
local s_cons = meta:get_string("connections")
|
||||
if s_cons then
|
||||
local cons = minetest.deserialize(s_cons)
|
||||
if cons then
|
||||
size = size + 0.5
|
||||
form = form.."label[0.5,"..size..";CONNECTIONS:]"
|
||||
for i, p in pairs(cons) do
|
||||
size = size + 0.5
|
||||
form = form.."label[0.5,"..size..";#"..i.." "
|
||||
..minetest.pos_to_string(p).."]"
|
||||
end
|
||||
end
|
||||
end
|
||||
local s_rots = meta:get_string("rotations")
|
||||
if s_rots then
|
||||
size = size + 0.5
|
||||
form = form.."label[0.5,"..size..";ROTATIONS: "..s_rots.."]"
|
||||
end
|
||||
form = form.."button_exit[3.0,"..(size + 1)..";2,0.5;;Ok]"
|
||||
form = "size[8,"..(size + 2).."]"..form
|
||||
minetest.show_formspec(name, "info", form)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "railtrack:powerrail 2",
|
||||
recipe = {
|
||||
{"default:rail", "default:mese_crystal_fragment", "default:rail"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "railtrack:brakerail 2",
|
||||
recipe = {
|
||||
{"default:rail", "default:coal_lump", "default:rail"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "railtrack:switchrail 2",
|
||||
recipe = {
|
||||
{"default:rail", "default:mese", "default:rail"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "railtrack:superrail 2",
|
||||
recipe = {
|
||||
{"default:rail", "default:diamond", "default:rail"},
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
local MAX_SECTION_LEN = 20
|
||||
|
||||
railtrack = {
|
||||
rotations = "FLR",
|
||||
accel_flat = -0.5,
|
||||
accel_up = -2,
|
||||
accel_down = 2,
|
||||
}
|
||||
|
||||
railtrack.default_rail = {
|
||||
description = "Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"default_rail.png", "default_rail_curved.png",
|
||||
"default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
is_ground_content = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy = 2, dig_immediate = 2, attached_node = 1,
|
||||
connect_to_raillike = minetest.raillike_group("rail")},
|
||||
railtype = "rail",
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local def = itemstack:get_definition() or {}
|
||||
if def.acceleration then
|
||||
meta:set_string("acceleration", def.acceleration)
|
||||
end
|
||||
local junc = {}
|
||||
local contype = meta:get_string("contype") or ""
|
||||
local s_cons = meta:get_string("connections") or ""
|
||||
if contype == "section" then
|
||||
railtrack:limit_section_len(placer, pos, meta)
|
||||
elseif s_cons ~= "" then
|
||||
local cons = minetest.deserialize(s_cons)
|
||||
for _, con in pairs(cons) do
|
||||
if railtrack:limit_section_len(placer, con) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
railtrack:update_rails(pos)
|
||||
end,
|
||||
after_destruct = function(pos, oldnode)
|
||||
local cons = railtrack:get_connections(pos)
|
||||
for _, p in pairs(cons) do
|
||||
railtrack:update_rails(p)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
function railtrack:copy(t)
|
||||
if type(t) ~= "table" then
|
||||
return t
|
||||
end
|
||||
local copy = {}
|
||||
for k, v in pairs(t) do
|
||||
copy[k] = v
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
function railtrack:register_rail(name, def)
|
||||
local udef = {}
|
||||
for k, v in pairs(railtrack.default_rail) do
|
||||
if not def[k] then
|
||||
def[k] = railtrack:copy(v)
|
||||
end
|
||||
udef[k] = railtrack:copy(def[k])
|
||||
end
|
||||
def.inventory_image = def.inventory_image or def.tiles[1]
|
||||
def.wield_image = def.wield_image or def.tiles[1]
|
||||
minetest.register_node(name, def)
|
||||
udef.drop = name
|
||||
udef.railtype = udef.railtype.."_union"
|
||||
udef.groups.not_in_creative_inventory=1
|
||||
minetest.register_node(name.."_union", udef)
|
||||
end
|
||||
|
||||
function railtrack:limit_section_len(player, pos, meta)
|
||||
meta = meta or minetest.get_meta(pos)
|
||||
local contype = meta:get_string("contype") or ""
|
||||
if contype == "section" then
|
||||
local s_junc = meta:get_string("junctions") or ""
|
||||
if s_junc ~= "" then
|
||||
local junc = minetest.deserialize(s_junc)
|
||||
if #junc == 2 then
|
||||
local dist = railtrack:get_distance(junc[1], junc[2])
|
||||
if dist > MAX_SECTION_LEN then
|
||||
local node = minetest.get_node(pos) or {}
|
||||
if node.name then
|
||||
minetest.swap_node(pos, {name=node.name.."_union"})
|
||||
railtrack:update_rails(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:is_railnode(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node then
|
||||
return minetest.get_item_group(node.name, "connect_to_raillike") > 0
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:get_sign(z)
|
||||
if z == 0 then
|
||||
return 0
|
||||
else
|
||||
return z / math.abs(z)
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:get_rotations(s_rots, dir)
|
||||
local rots = {}
|
||||
for i = 1, string.len(s_rots) do
|
||||
local r = string.sub(s_rots, i, i)
|
||||
local rot = nil
|
||||
if r == "F" then
|
||||
rot = {x=dir.x, z=dir.z}
|
||||
elseif r == "L" then
|
||||
rot = {x=-dir.z, z=dir.x}
|
||||
elseif r == "R" then
|
||||
rot = {x=dir.z, z=-dir.x}
|
||||
elseif r == "B" then
|
||||
rot = {x=-dir.x, z=-dir.z}
|
||||
end
|
||||
if rot then
|
||||
table.insert(rots, rot)
|
||||
end
|
||||
end
|
||||
return rots
|
||||
end
|
||||
|
||||
function railtrack:get_acceleration(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local accel = meta:get_string("acceleration") or ""
|
||||
if accel ~= "" then
|
||||
return tonumber(accel)
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:get_direction(p1, p2)
|
||||
local v = vector.subtract(p1, p2)
|
||||
return {
|
||||
x = railtrack:get_sign(v.x),
|
||||
y = railtrack:get_sign(v.y),
|
||||
z = railtrack:get_sign(v.z),
|
||||
}
|
||||
end
|
||||
|
||||
function railtrack:get_distance(p1, p2)
|
||||
local dx = p1.x - p2.x
|
||||
local dz = p1.z - p2.z
|
||||
return math.abs(dx) + math.abs(dz)
|
||||
end
|
||||
|
||||
|
||||
function railtrack:get_railtype(pos)
|
||||
local node = minetest.get_node(pos) or {}
|
||||
if node.name then
|
||||
local ref = minetest.registered_items[node.name] or {}
|
||||
return ref.railtype
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:get_connection_type(pos, cons)
|
||||
local railtype = railtrack:get_railtype(pos)
|
||||
if #cons == 0 then
|
||||
return "single"
|
||||
elseif #cons == 1 then
|
||||
return "junction"
|
||||
elseif #cons == 2 then
|
||||
if cons[1].x == cons[2].x or cons[1].z == cons[2].z then
|
||||
if (cons[1].y == cons[2].y and cons[1].y == pos.y) or
|
||||
(math.abs(cons[1].y - cons[2].y) == 2) then
|
||||
if railtype == railtrack:get_railtype(cons[1]) and
|
||||
railtype == railtrack:get_railtype(cons[2]) then
|
||||
return "section"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "junction"
|
||||
end
|
||||
|
||||
function railtrack:get_connections(pos)
|
||||
local connections = {}
|
||||
for y = 1, -1, -1 do
|
||||
for x = -1, 1 do
|
||||
for z = -1, 1 do
|
||||
if math.abs(x) ~= math.abs(z) then
|
||||
local p = vector.add(pos, {x=x, y=y, z=z})
|
||||
if railtrack:is_railnode(p) then
|
||||
table.insert(connections, p)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return connections
|
||||
end
|
||||
|
||||
function railtrack:get_junctions(pos, last_pos, junctions)
|
||||
junctions = junctions or {}
|
||||
local cons = railtrack:get_connections(pos)
|
||||
local contype = railtrack:get_connection_type(pos, cons)
|
||||
if contype == "junction" then
|
||||
table.insert(junctions, pos)
|
||||
elseif contype == "section" then
|
||||
if last_pos then
|
||||
for i, p in pairs(cons) do
|
||||
if vector.equals(p, last_pos) then
|
||||
cons[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, p in pairs(cons) do
|
||||
railtrack:get_junctions(p, pos, junctions)
|
||||
end
|
||||
end
|
||||
return junctions
|
||||
end
|
||||
|
||||
function railtrack:set_acceleration(pos, accel)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local contype = meta:get_string("contype")
|
||||
if contype == "section" then
|
||||
local s_junc = meta:get_string("junctions") or ""
|
||||
local junc = minetest.deserialize(s_junc) or {}
|
||||
if #junc == 2 then
|
||||
local p = vector.new(junc[2])
|
||||
local dir = railtrack:get_direction(junc[1], junc[2])
|
||||
local dist = railtrack:get_distance(junc[1], junc[2])
|
||||
for i = 0, dist do
|
||||
local m = minetest.get_meta(p)
|
||||
if m then
|
||||
m:set_string("acceleration", tostring(accel))
|
||||
end
|
||||
p = vector.add(dir, p)
|
||||
end
|
||||
end
|
||||
else
|
||||
meta:set_string("acceleration", tostring(accel))
|
||||
end
|
||||
end
|
||||
|
||||
function railtrack:update_rails(pos, last_pos, level)
|
||||
local connections = {}
|
||||
local junctions = {}
|
||||
local meta = minetest.get_meta(pos)
|
||||
local cons = railtrack:get_connections(pos)
|
||||
local contype = railtrack:get_connection_type(pos, cons)
|
||||
level = level or 0
|
||||
for i, p in pairs(cons) do
|
||||
connections[i] = p
|
||||
end
|
||||
if contype == "junction" then
|
||||
level = level + 1
|
||||
end
|
||||
if contype == "section" or level < 2 then
|
||||
if last_pos then
|
||||
for i, p in pairs(cons) do
|
||||
if vector.equals(p, last_pos) then
|
||||
cons[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, p in pairs(cons) do
|
||||
railtrack:update_rails(p, pos, level)
|
||||
end
|
||||
end
|
||||
if contype == "section" then
|
||||
junctions = railtrack:get_junctions(pos)
|
||||
connections = {}
|
||||
end
|
||||
meta:set_string("connections", minetest.serialize(connections))
|
||||
meta:set_string("junctions", minetest.serialize(junctions))
|
||||
meta:set_string("contype", contype)
|
||||
end
|
||||
|
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 378 B |
After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
After Width: | Height: | Size: 381 B |
After Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 383 B |