Compare commits
56 Commits
0.4.dev-20
...
0.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3ddbe8c6b | ||
|
|
d085139057 | ||
|
|
28e7443f9b | ||
|
|
e79ad21aeb | ||
|
|
0b61253931 | ||
|
|
a2738dec59 | ||
|
|
1788709e2d | ||
|
|
47d30d12cb | ||
|
|
43df78102c | ||
|
|
cc10eec6c6 | ||
|
|
15bf9a7026 | ||
|
|
2795f44f03 | ||
|
|
b0ba05c9ac | ||
|
|
71c6845a94 | ||
|
|
4b97023251 | ||
|
|
369046bbb4 | ||
|
|
38580fbee7 | ||
|
|
08e1d40d6e | ||
|
|
80f35467d8 | ||
|
|
1b19020bf4 | ||
|
|
61e58ee9b7 | ||
|
|
f21af8da9c | ||
|
|
dece3a3600 | ||
|
|
16ad10e62f | ||
|
|
02fb912a95 | ||
|
|
48790c0751 | ||
|
|
c57e5083e8 | ||
|
|
c9a2058361 | ||
|
|
7039dfafd6 | ||
|
|
22ae83a589 | ||
|
|
1575448b1a | ||
|
|
9f031a6759 | ||
|
|
d0ea6f9920 | ||
|
|
1bc37d576c | ||
|
|
d159591b9a | ||
|
|
57550b2b3d | ||
|
|
d15d6c4e6b | ||
|
|
6b598f61a6 | ||
|
|
9e21204f8b | ||
|
|
e6b86fa304 | ||
|
|
268e50dfbd | ||
|
|
07ccc15fc2 | ||
|
|
2b500d72e5 | ||
|
|
cd0014b24f | ||
|
|
b3786d84c5 | ||
|
|
fd1135c7af | ||
|
|
f0678979b1 | ||
|
|
f4a7e11bce | ||
|
|
6a0388bb4b | ||
|
|
7ba72f2763 | ||
|
|
f7147d9c0a | ||
|
|
523a5fd2e5 | ||
|
|
ff85e2343c | ||
|
|
e74668ef7f | ||
|
|
22502f80db | ||
|
|
4b2cc38aba |
@@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH dev-20120606)
|
||||
set(VERSION_PATCH 1)
|
||||
if(VERSION_EXTRA)
|
||||
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
|
||||
endif()
|
||||
|
||||
@@ -41,7 +41,7 @@ end)
|
||||
--
|
||||
|
||||
-- Register C++ commands without functions
|
||||
minetest.register_chatcommand("me", {params = nil, description = "chat action (eg. /me orders a pizza)"})
|
||||
minetest.register_chatcommand("me", {params = nil, description = "chat action (eg. /me orders a pizza)", privs = {shout=true}})
|
||||
minetest.register_chatcommand("status", {description = "print server status line"})
|
||||
minetest.register_chatcommand("shutdown", {params = "", description = "shutdown server", privs = {server=true}})
|
||||
minetest.register_chatcommand("clearobjects", {params = "", description = "clear all objects in world", privs = {server=true}})
|
||||
@@ -193,12 +193,27 @@ minetest.register_chatcommand("setpassword", {
|
||||
description = "set given password",
|
||||
privs = {password=true},
|
||||
func = function(name, param)
|
||||
if param == "" then
|
||||
minetest.chat_send_player(name, "Password field required")
|
||||
local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$")
|
||||
if not toname then
|
||||
toname = string.match(param, "^([^ ]+) *$")
|
||||
raw_password = nil
|
||||
end
|
||||
if not toname then
|
||||
minetest.chat_send_player(name, "Name field required")
|
||||
return
|
||||
end
|
||||
minetest.set_player_password(name, param)
|
||||
minetest.chat_send_player(name, "Password set")
|
||||
local actstr = "?"
|
||||
if not raw_password then
|
||||
minetest.set_player_password(toname, "")
|
||||
actstr = "cleared"
|
||||
else
|
||||
minetest.set_player_password(toname, minetest.get_password_hash(toname, raw_password))
|
||||
actstr = "set"
|
||||
end
|
||||
minetest.chat_send_player(name, "Password of player \""..toname.."\" "..actstr)
|
||||
if toname ~= name then
|
||||
minetest.chat_send_player(toname, "Your password was "..actstr.." by "..name)
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("clearpassword", {
|
||||
@@ -206,8 +221,13 @@ minetest.register_chatcommand("clearpassword", {
|
||||
description = "set empty password",
|
||||
privs = {password=true},
|
||||
func = function(name, param)
|
||||
minetest.set_player_password(name, '')
|
||||
minetest.chat_send_player(name, "Password cleared")
|
||||
toname = param
|
||||
if not toname then
|
||||
minetest.chat_send_player(toname, "Name field required")
|
||||
return
|
||||
end
|
||||
minetest.set_player_password(toname, '')
|
||||
minetest.chat_send_player(name, "Password of player \""..toname.."\" cleared")
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
@@ -149,10 +149,12 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif def.paramtype2 == 'facedir' then
|
||||
local playerpos = placer:getpos()
|
||||
local dir = {x = pos.x - playerpos.x, y = pos.y - playerpos.y, z = pos.z - playerpos.z}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
local placer_pos = placer:getpos()
|
||||
if placer_pos then
|
||||
local dir = {x = pos.x - placer_pos.x, y = pos.y - placer_pos.y, z = pos.z - placer_pos.z}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add node and update
|
||||
@@ -342,6 +344,7 @@ minetest.nodedef_default = {
|
||||
usable = false,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
node_placement_prediction = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||
@@ -361,11 +364,13 @@ minetest.nodedef_default = {
|
||||
-- Node properties
|
||||
drawtype = "normal",
|
||||
visual_scale = 1.0,
|
||||
tile_images = {""},
|
||||
special_materials = {
|
||||
{image="", backface_culling=true},
|
||||
{image="", backface_culling=true},
|
||||
},
|
||||
-- Don't define these because otherwise the old tile_images and
|
||||
-- special_materials wouldn't be read
|
||||
--tiles ={""},
|
||||
--special_tiles = {
|
||||
-- {name="", backface_culling=true},
|
||||
-- {name="", backface_culling=true},
|
||||
--},
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
paramtype = "none",
|
||||
|
||||
@@ -72,7 +72,8 @@ minetest.register_entity("__builtin:item", {
|
||||
local p = self.object:getpos()
|
||||
p.y = p.y - 0.3
|
||||
local nn = minetest.env:get_node(p).name
|
||||
if minetest.registered_nodes[nn].walkable then
|
||||
-- If node is not registered or node is walkably solid
|
||||
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable then
|
||||
if self.physical_state then
|
||||
self.object:setvelocity({x=0,y=0,z=0})
|
||||
self.object:setacceleration({x=0, y=0, z=0})
|
||||
|
||||
@@ -302,6 +302,8 @@ end
|
||||
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
||||
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
||||
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
||||
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
||||
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
||||
minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
|
||||
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
|
||||
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
||||
@@ -309,16 +311,3 @@ minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make
|
||||
minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_registration()
|
||||
minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration()
|
||||
|
||||
minetest.registered_on_placenodes = {}
|
||||
minetest.register_on_placenode = function(callback)
|
||||
minetest.log("info", debug.traceback())
|
||||
minetest.log("info", "WARNING: minetest.register_on_placenode is deprecated. Use on_construct or after_place_node in node definition instead.")
|
||||
table.insert(minetest.registered_on_placenodes, callback)
|
||||
end
|
||||
minetest.registered_on_dignodes = {}
|
||||
minetest.register_on_dignode = function(callback)
|
||||
minetest.log("info", debug.traceback())
|
||||
minetest.log("info", "WARNING: minetest.register_on_dignode is deprecated. Use on_destruct or after_dig_node in node definition instead.")
|
||||
table.insert(minetest.registered_on_dignodes, callback)
|
||||
end
|
||||
|
||||
|
||||
120
doc/lua_api.txt
120
doc/lua_api.txt
@@ -1,4 +1,4 @@
|
||||
Minetest Lua Modding API Reference 0.4.dev
|
||||
Minetest Lua Modding API Reference 0.4.0
|
||||
==========================================
|
||||
More information at http://c55.me/minetest/
|
||||
|
||||
@@ -280,6 +280,61 @@ param2 is reserved for the engine when any of these are used:
|
||||
|
||||
Nodes can also contain extra data. See "Node Metadata".
|
||||
|
||||
Node drawtypes
|
||||
---------------
|
||||
There are a bunch of different looking node types. These are mostly just
|
||||
copied from Minetest 0.3; more may be made in the future.
|
||||
|
||||
Look for examples in games/minimal or games/minetest_game.
|
||||
|
||||
- normal
|
||||
- airlike
|
||||
- liquid
|
||||
- flowingliquid
|
||||
- glasslike
|
||||
- allfaces
|
||||
- allfaces_optional
|
||||
- torchlike
|
||||
- signlike
|
||||
- plantlike
|
||||
- fencelike
|
||||
- raillike
|
||||
- nodebox -- See below. EXPERIMENTAL
|
||||
|
||||
Node boxes
|
||||
-----------
|
||||
Node selection boxes are defined using "node boxes"
|
||||
|
||||
The "nodebox" node drawtype allows defining visual of nodes consisting of
|
||||
arbitrary number of boxes. It allows defining stuff like stairs. Only the
|
||||
"fixed" box type is supported for these.
|
||||
^ Please note that this is still experimental, and may be incompatibly
|
||||
changed in the future.
|
||||
|
||||
A nodebox is defined as any of:
|
||||
{
|
||||
-- A normal cube; the default in most things
|
||||
type = "regular"
|
||||
}
|
||||
{
|
||||
-- A fixed box (facedir param2 is used, if applicable)
|
||||
type = "fixed",
|
||||
fixed = box OR {box1, box2, ...}
|
||||
}
|
||||
{
|
||||
-- A box like the selection box for torches
|
||||
-- (wallmounted param2 is used, if applicable)
|
||||
type = "wallmounted",
|
||||
wall_top = box,
|
||||
wall_bottom = box,
|
||||
wall_side = box
|
||||
}
|
||||
|
||||
A box is defined as:
|
||||
{x1, y1, z1, x2, y2, z2}
|
||||
A box of a regular node would look like:
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
|
||||
Representations of simple things
|
||||
--------------------------------
|
||||
Position/vector:
|
||||
@@ -287,6 +342,11 @@ Position/vector:
|
||||
Currently the API does not provide any helper functions for addition,
|
||||
subtraction and whatever; you can define those that you need yourself.
|
||||
|
||||
pointed_thing:
|
||||
{type="nothing"}
|
||||
{type="node", under=pos, above=pos}
|
||||
{type="object", ref=ObjectRef}
|
||||
|
||||
Items
|
||||
------
|
||||
Node (register_node):
|
||||
@@ -699,6 +759,10 @@ minetest.register_on_respawnplayer(func(ObjectRef))
|
||||
^ Called when player is to be respawned
|
||||
^ Called _before_ repositioning of player occurs
|
||||
^ return true in func to disable regular player placement
|
||||
minetest.register_on_joinplayer(func(ObjectRef))
|
||||
^ Called when a player joins the game
|
||||
minetest.register_on_leaveplayer(func(ObjectRef))
|
||||
^ Called when a player leaves the game
|
||||
minetest.register_on_chat_message(func(name, message))
|
||||
|
||||
Other registration functions:
|
||||
@@ -765,6 +829,13 @@ minetest.get_craft_result(input) -> output, decremented_input
|
||||
^ output.item = ItemStack, if unsuccessful: empty ItemStack
|
||||
^ output.time = number, if unsuccessful: 0
|
||||
^ decremented_input = like input
|
||||
minetest.get_craft_recipe(output) -> input
|
||||
^ output is a node or item type such as 'default:torch'
|
||||
^ input.method = 'normal' or 'cooking' or 'fuel'
|
||||
^ input.width = for example 3
|
||||
^ input.items = for example { stack 1, stack 2, stack 3, stack 4,
|
||||
stack 5, stack 6, stack 7, stack 8, stack 9 }
|
||||
^ input.items = nil if no recipe found
|
||||
|
||||
Defaults for the on_* item definition functions:
|
||||
(These return the leftover itemstack)
|
||||
@@ -933,8 +1004,8 @@ LuaEntitySAO-only: (no-op for other objects)
|
||||
- settexturemod(mod)
|
||||
- setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
|
||||
- select_horiz_by_yawpitch=false)
|
||||
- ^ Select sprite from spritesheet with optional animation and DM-style
|
||||
- texture selection based on yaw relative to camera
|
||||
^ Select sprite from spritesheet with optional animation and DM-style
|
||||
texture selection based on yaw relative to camera
|
||||
- get_entity_name() (DEPRECATED: Will be removed in a future version)
|
||||
- get_luaentity()
|
||||
Player-only: (no-op for other objects)
|
||||
@@ -943,6 +1014,10 @@ Player-only: (no-op for other objects)
|
||||
- get_look_dir(): get camera direction as a unit vector
|
||||
- get_look_pitch(): pitch in radians
|
||||
- get_look_yaw(): yaw in radians (wraps around pretty randomly as of now)
|
||||
- set_inventory_formspec(formspec)
|
||||
^ Redefine player's inventory form
|
||||
^ Should usually be called in on_joinplayer
|
||||
- get_inventory_formspec() -> formspec string
|
||||
|
||||
InvRef: Reference to an inventory
|
||||
methods:
|
||||
@@ -1036,7 +1111,9 @@ Definition tables
|
||||
|
||||
Object Properties
|
||||
{
|
||||
hp_max = 1,
|
||||
physical = true,
|
||||
weight = 5,
|
||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||
visual = "cube"/"sprite"/"upright_sprite",
|
||||
visual_size = {x=1, y=1},
|
||||
@@ -1045,6 +1122,7 @@ Object Properties
|
||||
initial_sprite_basepos = {x=0, y=0},
|
||||
is_visible = true,
|
||||
makes_footstep_sound = false,
|
||||
automatic_rotate = false,
|
||||
}
|
||||
|
||||
Entity definition (register_entity)
|
||||
@@ -1100,10 +1178,19 @@ Item definition (register_node, register_craftitem, register_tool)
|
||||
choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
|
||||
}
|
||||
}
|
||||
node_placement_prediction = nil,
|
||||
^ If nil and item is node, prediction is made automatically
|
||||
^ If nil and item is not a node, no prediction is made
|
||||
^ If "" and item is anything, no prediction is made
|
||||
^ Otherwise should be name of node which the client immediately places
|
||||
on ground when the player places the item. Server will always update
|
||||
actual result to client in a short moment.
|
||||
|
||||
on_place = func(itemstack, placer, pointed_thing),
|
||||
^ Shall place item and return the leftover itemstack
|
||||
^ default: minetest.item_place
|
||||
on_drop = func(itemstack, dropper, pos),
|
||||
^ Shall drop item and return the leftover itemstack
|
||||
^ default: minetest.item_drop
|
||||
on_use = func(itemstack, user, pointed_thing),
|
||||
^ default: nil
|
||||
@@ -1114,17 +1201,29 @@ Item definition (register_node, register_craftitem, register_tool)
|
||||
^ The default functions handle regular use cases.
|
||||
}
|
||||
|
||||
Tile definition:
|
||||
- "image.png"
|
||||
- {name="image.png", animation={Tile Animation definition}}
|
||||
- {name="image.png", backface_culling=bool}
|
||||
^ backface culling only supported in special tiles
|
||||
- deprecated still supported field names:
|
||||
- image -> name
|
||||
|
||||
Tile animation definition:
|
||||
- {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}
|
||||
|
||||
Node definition (register_node)
|
||||
{
|
||||
<all fields allowed in item definitions>,
|
||||
|
||||
drawtype = "normal",
|
||||
drawtype = "normal", -- See "Node drawtypes"
|
||||
visual_scale = 1.0,
|
||||
tile_images = {"default_unknown_block.png"},
|
||||
special_materials = {
|
||||
{image="", backface_culling=true},
|
||||
{image="", backface_culling=true},
|
||||
},
|
||||
tiles = {tile definition 1, def2, def3, def4, def5, def6},
|
||||
^ List can be shortened to needed length
|
||||
^ Old field name: tile_images
|
||||
special_tiles = {tile definition 1, Tile definition 2},
|
||||
^ List can be shortened to needed length
|
||||
^ Old field name: special_materials
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
paramtype = "none",
|
||||
@@ -1144,7 +1243,8 @@ Node definition (register_node)
|
||||
liquid_viscosity = 0,
|
||||
light_source = 0,
|
||||
damage_per_second = 0,
|
||||
selection_box = {type="regular"},
|
||||
node_box = {type="regular"}, -- See "Node boxes"
|
||||
selection_box = {type="regular"}, -- See "Node boxes"
|
||||
legacy_facedir_simple = false, -- Support maps made in and before January 2012
|
||||
legacy_wallmounted = false, -- Support maps made in and before January 2012
|
||||
sounds = {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
=================================================
|
||||
Minetest World Format used as of 0.4.dev-20120322
|
||||
=================================================
|
||||
=============================
|
||||
Minetest World Format 22...23
|
||||
=============================
|
||||
|
||||
This applies to a world format carrying the block serialization version 22
|
||||
which is used at least in version 0.4.dev-20120322.
|
||||
This applies to a world format carrying the block serialization version
|
||||
22...23, used at least in
|
||||
- 0.4.dev-20120322 ... 0.4.dev-20120606
|
||||
- 0.4.0.
|
||||
|
||||
The block serialization version used is 22. It does not fully specify every
|
||||
aspect of this format; if compliance with this format is to be checked, it
|
||||
needs to be done by detecting if the files and data indeed follows it.
|
||||
The block serialization version does not fully specify every aspect of this
|
||||
format; if compliance with this format is to be checked, it needs to be
|
||||
done by detecting if the files and data indeed follows it.
|
||||
|
||||
Legacy stuff
|
||||
=============
|
||||
@@ -20,8 +22,8 @@ Files
|
||||
Everything is contained in a directory, the name of which is freeform, but
|
||||
often serves as the name of the world.
|
||||
|
||||
Currently the authentication and ban data is stored on a per-world basis. It
|
||||
can be copied over from an old world to a newly created world.
|
||||
Currently the authentication and ban data is stored on a per-world basis.
|
||||
It can be copied over from an old world to a newly created world.
|
||||
|
||||
World
|
||||
|-- auth.txt ----- Authentication data
|
||||
@@ -283,9 +285,9 @@ zlib-compressed node metadata list
|
||||
u16 content_size
|
||||
u8[content_size] (content of metadata)
|
||||
|
||||
u16 mapblockobject_count
|
||||
- Always 0
|
||||
- Should be removed in version 23 (TODO)
|
||||
- unused node timers (version will be 24 when they are actually used):
|
||||
if version == 23:
|
||||
u8 unused version (always 0)
|
||||
|
||||
u8 static object version:
|
||||
- Always 0
|
||||
|
||||
@@ -90,6 +90,6 @@ bucket.register_liquid(
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "default:bucket_lava",
|
||||
recipe = "bucket:bucket_lava",
|
||||
burntime = 60,
|
||||
})
|
||||
|
||||
@@ -701,7 +701,7 @@ end
|
||||
|
||||
minetest.register_node("default:stone", {
|
||||
description = "Stone",
|
||||
tile_images = {"default_stone.png"},
|
||||
tiles ={"default_stone.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
drop = 'default:cobble',
|
||||
@@ -711,7 +711,7 @@ minetest.register_node("default:stone", {
|
||||
|
||||
minetest.register_node("default:stone_with_coal", {
|
||||
description = "Stone with coal",
|
||||
tile_images = {"default_stone.png^default_mineral_coal.png"},
|
||||
tiles ={"default_stone.png^default_mineral_coal.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
drop = 'default:coal_lump',
|
||||
@@ -720,7 +720,7 @@ minetest.register_node("default:stone_with_coal", {
|
||||
|
||||
minetest.register_node("default:stone_with_iron", {
|
||||
description = "Stone with iron",
|
||||
tile_images = {"default_stone.png^default_mineral_iron.png"},
|
||||
tiles ={"default_stone.png^default_mineral_iron.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
drop = 'default:iron_lump',
|
||||
@@ -729,7 +729,7 @@ minetest.register_node("default:stone_with_iron", {
|
||||
|
||||
minetest.register_node("default:dirt_with_grass", {
|
||||
description = "Dirt with grass",
|
||||
tile_images = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
tiles ={"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
drop = 'default:dirt',
|
||||
@@ -740,7 +740,7 @@ minetest.register_node("default:dirt_with_grass", {
|
||||
|
||||
minetest.register_node("default:dirt_with_grass_footsteps", {
|
||||
description = "Dirt with grass and footsteps",
|
||||
tile_images = {"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
tiles ={"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
drop = 'default:dirt',
|
||||
@@ -751,7 +751,7 @@ minetest.register_node("default:dirt_with_grass_footsteps", {
|
||||
|
||||
minetest.register_node("default:dirt", {
|
||||
description = "Dirt",
|
||||
tile_images = {"default_dirt.png"},
|
||||
tiles ={"default_dirt.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
sounds = default.node_sound_dirt_defaults(),
|
||||
@@ -759,7 +759,7 @@ minetest.register_node("default:dirt", {
|
||||
|
||||
minetest.register_node("default:sand", {
|
||||
description = "Sand",
|
||||
tile_images = {"default_sand.png"},
|
||||
tiles ={"default_sand.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
sounds = default.node_sound_sand_defaults(),
|
||||
@@ -767,7 +767,7 @@ minetest.register_node("default:sand", {
|
||||
|
||||
minetest.register_node("default:gravel", {
|
||||
description = "Gravel",
|
||||
tile_images = {"default_gravel.png"},
|
||||
tiles ={"default_gravel.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=2},
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
@@ -777,7 +777,7 @@ minetest.register_node("default:gravel", {
|
||||
|
||||
minetest.register_node("default:sandstone", {
|
||||
description = "Sandstone",
|
||||
tile_images = {"default_sandstone.png"},
|
||||
tiles ={"default_sandstone.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=2,cracky=2},
|
||||
drop = 'default:sand',
|
||||
@@ -786,7 +786,7 @@ minetest.register_node("default:sandstone", {
|
||||
|
||||
minetest.register_node("default:clay", {
|
||||
description = "Clay",
|
||||
tile_images = {"default_clay.png"},
|
||||
tiles ={"default_clay.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
drop = 'default:clay_lump 4',
|
||||
@@ -797,7 +797,7 @@ minetest.register_node("default:clay", {
|
||||
|
||||
minetest.register_node("default:brick", {
|
||||
description = "Brick",
|
||||
tile_images = {"default_brick.png"},
|
||||
tiles ={"default_brick.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
drop = 'default:clay_brick 4',
|
||||
@@ -806,7 +806,7 @@ minetest.register_node("default:brick", {
|
||||
|
||||
minetest.register_node("default:tree", {
|
||||
description = "Tree",
|
||||
tile_images = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
|
||||
tiles ={"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
@@ -814,7 +814,7 @@ minetest.register_node("default:tree", {
|
||||
|
||||
minetest.register_node("default:jungletree", {
|
||||
description = "Jungle Tree",
|
||||
tile_images = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
|
||||
tiles ={"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
@@ -824,7 +824,7 @@ minetest.register_node("default:junglegrass", {
|
||||
description = "Jungle Grass",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.3,
|
||||
tile_images = {"default_junglegrass.png"},
|
||||
tiles ={"default_junglegrass.png"},
|
||||
inventory_image = "default_junglegrass.png",
|
||||
wield_image = "default_junglegrass.png",
|
||||
paramtype = "light",
|
||||
@@ -837,7 +837,7 @@ minetest.register_node("default:leaves", {
|
||||
description = "Leaves",
|
||||
drawtype = "allfaces_optional",
|
||||
visual_scale = 1.3,
|
||||
tile_images = {"default_leaves.png"},
|
||||
tiles ={"default_leaves.png"},
|
||||
paramtype = "light",
|
||||
groups = {snappy=3},
|
||||
drop = {
|
||||
@@ -860,7 +860,7 @@ minetest.register_node("default:leaves", {
|
||||
|
||||
minetest.register_node("default:cactus", {
|
||||
description = "Cactus",
|
||||
tile_images = {"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"},
|
||||
tiles ={"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,choppy=3},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
@@ -869,7 +869,7 @@ minetest.register_node("default:cactus", {
|
||||
minetest.register_node("default:papyrus", {
|
||||
description = "Papyrus",
|
||||
drawtype = "plantlike",
|
||||
tile_images = {"default_papyrus.png"},
|
||||
tiles ={"default_papyrus.png"},
|
||||
inventory_image = "default_papyrus.png",
|
||||
wield_image = "default_papyrus.png",
|
||||
paramtype = "light",
|
||||
@@ -881,7 +881,7 @@ minetest.register_node("default:papyrus", {
|
||||
|
||||
minetest.register_node("default:bookshelf", {
|
||||
description = "Bookshelf",
|
||||
tile_images = {"default_wood.png", "default_wood.png", "default_bookshelf.png"},
|
||||
tiles ={"default_wood.png", "default_wood.png", "default_bookshelf.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,choppy=3,oddly_breakable_by_hand=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
@@ -890,7 +890,7 @@ minetest.register_node("default:bookshelf", {
|
||||
minetest.register_node("default:glass", {
|
||||
description = "Glass",
|
||||
drawtype = "glasslike",
|
||||
tile_images = {"default_glass.png"},
|
||||
tiles ={"default_glass.png"},
|
||||
inventory_image = minetest.inventorycube("default_glass.png"),
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
@@ -902,7 +902,7 @@ minetest.register_node("default:glass", {
|
||||
minetest.register_node("default:fence_wood", {
|
||||
description = "Wooden Fence",
|
||||
drawtype = "fencelike",
|
||||
tile_images = {"default_wood.png"},
|
||||
tiles ={"default_wood.png"},
|
||||
inventory_image = "default_fence.png",
|
||||
wield_image = "default_fence.png",
|
||||
paramtype = "light",
|
||||
@@ -918,7 +918,7 @@ minetest.register_node("default:fence_wood", {
|
||||
minetest.register_node("default:rail", {
|
||||
description = "Rail",
|
||||
drawtype = "raillike",
|
||||
tile_images = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
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",
|
||||
@@ -926,7 +926,7 @@ minetest.register_node("default:rail", {
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
--fixed = <default>
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy=2,snappy=1,dig_immediate=2},
|
||||
})
|
||||
@@ -934,7 +934,7 @@ minetest.register_node("default:rail", {
|
||||
minetest.register_node("default:ladder", {
|
||||
description = "Ladder",
|
||||
drawtype = "signlike",
|
||||
tile_images = {"default_ladder.png"},
|
||||
tiles ={"default_ladder.png"},
|
||||
inventory_image = "default_ladder.png",
|
||||
wield_image = "default_ladder.png",
|
||||
paramtype = "light",
|
||||
@@ -955,7 +955,7 @@ minetest.register_node("default:ladder", {
|
||||
|
||||
minetest.register_node("default:wood", {
|
||||
description = "Wood",
|
||||
tile_images = {"default_wood.png"},
|
||||
tiles ={"default_wood.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
@@ -963,7 +963,7 @@ minetest.register_node("default:wood", {
|
||||
|
||||
minetest.register_node("default:mese", {
|
||||
description = "Mese",
|
||||
tile_images = {"default_mese.png"},
|
||||
tiles ={"default_mese.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=1,level=2},
|
||||
sounds = default.node_sound_defaults(),
|
||||
@@ -971,7 +971,7 @@ minetest.register_node("default:mese", {
|
||||
|
||||
minetest.register_node("default:cloud", {
|
||||
description = "Cloud",
|
||||
tile_images = {"default_cloud.png"},
|
||||
tiles ={"default_cloud.png"},
|
||||
is_ground_content = true,
|
||||
sounds = default.node_sound_defaults(),
|
||||
})
|
||||
@@ -980,7 +980,11 @@ minetest.register_node("default:water_flowing", {
|
||||
description = "Water (flowing)",
|
||||
inventory_image = minetest.inventorycube("default_water.png"),
|
||||
drawtype = "flowingliquid",
|
||||
tile_images = {"default_water.png"},
|
||||
tiles ={"default_water.png"},
|
||||
special_tiles = {
|
||||
{name="default_water.png", backface_culling=false},
|
||||
{name="default_water.png", backface_culling=true},
|
||||
},
|
||||
alpha = WATER_ALPHA,
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
@@ -992,10 +996,6 @@ minetest.register_node("default:water_flowing", {
|
||||
liquid_alternative_source = "default:water_source",
|
||||
liquid_viscosity = WATER_VISC,
|
||||
post_effect_color = {a=64, r=100, g=100, b=200},
|
||||
special_materials = {
|
||||
{image="default_water.png", backface_culling=false},
|
||||
{image="default_water.png", backface_culling=true},
|
||||
},
|
||||
groups = {water=3, liquid=3},
|
||||
})
|
||||
|
||||
@@ -1003,7 +1003,11 @@ minetest.register_node("default:water_source", {
|
||||
description = "Water",
|
||||
inventory_image = minetest.inventorycube("default_water.png"),
|
||||
drawtype = "liquid",
|
||||
tile_images = {"default_water.png"},
|
||||
tiles ={"default_water.png"},
|
||||
special_tiles = {
|
||||
-- New-style water source material (mostly unused)
|
||||
{name="default_water.png", backface_culling=false},
|
||||
},
|
||||
alpha = WATER_ALPHA,
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
@@ -1015,10 +1019,6 @@ minetest.register_node("default:water_source", {
|
||||
liquid_alternative_source = "default:water_source",
|
||||
liquid_viscosity = WATER_VISC,
|
||||
post_effect_color = {a=64, r=100, g=100, b=200},
|
||||
special_materials = {
|
||||
-- New-style water source material (mostly unused)
|
||||
{image="default_water.png", backface_culling=false},
|
||||
},
|
||||
groups = {water=3, liquid=3},
|
||||
})
|
||||
|
||||
@@ -1026,7 +1026,19 @@ minetest.register_node("default:lava_flowing", {
|
||||
description = "Lava (flowing)",
|
||||
inventory_image = minetest.inventorycube("default_lava.png"),
|
||||
drawtype = "flowingliquid",
|
||||
tile_images = {"default_lava.png"},
|
||||
tiles ={"default_lava.png"},
|
||||
special_tiles = {
|
||||
{
|
||||
image="default_lava_flowing_animated.png",
|
||||
backface_culling=false,
|
||||
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3}
|
||||
},
|
||||
{
|
||||
image="default_lava_flowing_animated.png",
|
||||
backface_culling=true,
|
||||
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3}
|
||||
},
|
||||
},
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_MAX - 1,
|
||||
walkable = false,
|
||||
@@ -1039,10 +1051,6 @@ minetest.register_node("default:lava_flowing", {
|
||||
liquid_viscosity = LAVA_VISC,
|
||||
damage_per_second = 4*2,
|
||||
post_effect_color = {a=192, r=255, g=64, b=0},
|
||||
special_materials = {
|
||||
{image="default_lava.png", backface_culling=false},
|
||||
{image="default_lava.png", backface_culling=true},
|
||||
},
|
||||
groups = {lava=3, liquid=2, hot=3},
|
||||
})
|
||||
|
||||
@@ -1050,7 +1058,14 @@ minetest.register_node("default:lava_source", {
|
||||
description = "Lava",
|
||||
inventory_image = minetest.inventorycube("default_lava.png"),
|
||||
drawtype = "liquid",
|
||||
tile_images = {"default_lava.png"},
|
||||
--tiles ={"default_lava.png"},
|
||||
tiles ={
|
||||
{name="default_lava_source_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
|
||||
},
|
||||
special_tiles = {
|
||||
-- New-style lava source material (mostly unused)
|
||||
{name="default_lava.png", backface_culling=false},
|
||||
},
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_MAX - 1,
|
||||
walkable = false,
|
||||
@@ -1063,17 +1078,13 @@ minetest.register_node("default:lava_source", {
|
||||
liquid_viscosity = LAVA_VISC,
|
||||
damage_per_second = 4*2,
|
||||
post_effect_color = {a=192, r=255, g=64, b=0},
|
||||
special_materials = {
|
||||
-- New-style lava source material (mostly unused)
|
||||
{image="default_lava.png", backface_culling=false},
|
||||
},
|
||||
groups = {lava=3, liquid=2, hot=3},
|
||||
})
|
||||
|
||||
minetest.register_node("default:torch", {
|
||||
description = "Torch",
|
||||
drawtype = "torchlike",
|
||||
tile_images = {"default_torch_on_floor.png", "default_torch_on_ceiling.png", "default_torch.png"},
|
||||
tiles ={"default_torch_on_floor.png", "default_torch_on_ceiling.png", "default_torch.png"},
|
||||
inventory_image = "default_torch_on_floor.png",
|
||||
wield_image = "default_torch_on_floor.png",
|
||||
paramtype = "light",
|
||||
@@ -1095,14 +1106,13 @@ minetest.register_node("default:torch", {
|
||||
minetest.register_node("default:sign_wall", {
|
||||
description = "Sign",
|
||||
drawtype = "signlike",
|
||||
tile_images = {"default_sign_wall.png"},
|
||||
tiles ={"default_sign_wall.png"},
|
||||
inventory_image = "default_sign_wall.png",
|
||||
wield_image = "default_sign_wall.png",
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
metadata_name = "sign",
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
--wall_top = <default>
|
||||
@@ -1131,7 +1141,7 @@ minetest.register_node("default:sign_wall", {
|
||||
|
||||
minetest.register_node("default:chest", {
|
||||
description = "Chest",
|
||||
tile_images = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
tiles ={"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||
@@ -1182,7 +1192,7 @@ end
|
||||
|
||||
minetest.register_node("default:chest_locked", {
|
||||
description = "Locked Chest",
|
||||
tile_images = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
tiles ={"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||
@@ -1265,7 +1275,7 @@ default.furnace_inactive_formspec =
|
||||
|
||||
minetest.register_node("default:furnace", {
|
||||
description = "Furnace",
|
||||
tile_images = {"default_furnace_side.png", "default_furnace_side.png", "default_furnace_side.png",
|
||||
tiles ={"default_furnace_side.png", "default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2},
|
||||
@@ -1296,7 +1306,7 @@ minetest.register_node("default:furnace", {
|
||||
|
||||
minetest.register_node("default:furnace_active", {
|
||||
description = "Furnace",
|
||||
tile_images = {"default_furnace_side.png", "default_furnace_side.png", "default_furnace_side.png",
|
||||
tiles ={"default_furnace_side.png", "default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front_active.png"},
|
||||
paramtype2 = "facedir",
|
||||
light_source = 8,
|
||||
@@ -1444,7 +1454,7 @@ minetest.register_abm({
|
||||
|
||||
minetest.register_node("default:cobble", {
|
||||
description = "Cobble",
|
||||
tile_images = {"default_cobble.png"},
|
||||
tiles ={"default_cobble.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
@@ -1452,7 +1462,7 @@ minetest.register_node("default:cobble", {
|
||||
|
||||
minetest.register_node("default:mossycobble", {
|
||||
description = "Mossy Cobble",
|
||||
tile_images = {"default_mossycobble.png"},
|
||||
tiles ={"default_mossycobble.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
@@ -1460,7 +1470,7 @@ minetest.register_node("default:mossycobble", {
|
||||
|
||||
minetest.register_node("default:steelblock", {
|
||||
description = "Steel Block",
|
||||
tile_images = {"default_steel_block.png"},
|
||||
tiles ={"default_steel_block.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=1,bendy=2},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
@@ -1468,7 +1478,7 @@ minetest.register_node("default:steelblock", {
|
||||
|
||||
minetest.register_node("default:nyancat", {
|
||||
description = "Nyancat",
|
||||
tile_images = {"default_nc_side.png", "default_nc_side.png", "default_nc_side.png",
|
||||
tiles ={"default_nc_side.png", "default_nc_side.png", "default_nc_side.png",
|
||||
"default_nc_side.png", "default_nc_back.png", "default_nc_front.png"},
|
||||
inventory_image = "default_nc_front.png",
|
||||
paramtype2 = "facedir",
|
||||
@@ -1479,7 +1489,7 @@ minetest.register_node("default:nyancat", {
|
||||
|
||||
minetest.register_node("default:nyancat_rainbow", {
|
||||
description = "Nyancat Rainbow",
|
||||
tile_images = {"default_nc_rb.png"},
|
||||
tiles ={"default_nc_rb.png"},
|
||||
inventory_image = "default_nc_rb.png",
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_defaults(),
|
||||
@@ -1489,7 +1499,7 @@ minetest.register_node("default:sapling", {
|
||||
description = "Sapling",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.0,
|
||||
tile_images = {"default_sapling.png"},
|
||||
tiles ={"default_sapling.png"},
|
||||
inventory_image = "default_sapling.png",
|
||||
wield_image = "default_sapling.png",
|
||||
paramtype = "light",
|
||||
@@ -1502,7 +1512,7 @@ minetest.register_node("default:apple", {
|
||||
description = "Apple",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.0,
|
||||
tile_images = {"default_apple.png"},
|
||||
tiles ={"default_apple.png"},
|
||||
inventory_image = "default_apple.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
games/minimal/mods/default/textures/crack_anylength.png
Normal file
BIN
games/minimal/mods/default/textures/crack_anylength.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 367 B |
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
@@ -447,6 +447,9 @@ minetest.register_node("experimental:tester_node_1", {
|
||||
tile_images = {"wieldhand.png"},
|
||||
groups = {oddly_breakable_by_hand=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
-- This was known to cause a bug in minetest.item_place_node() when used
|
||||
-- via minetest.env:place_node(), causing a placer with no position
|
||||
paramtype2 = "facedir",
|
||||
|
||||
on_construct = function(pos)
|
||||
experimental.print_to_everything("experimental:tester_node_1:on_construct("..minetest.pos_to_string(pos)..")")
|
||||
@@ -504,6 +507,16 @@ minetest.register_craft({
|
||||
}
|
||||
})
|
||||
|
||||
--[[minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(3, function()
|
||||
player:set_inventory_formspec("invsize[8,7.5;]"..
|
||||
"image[1,0.6;1,2;player.png]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"list[current_player;craft;3,0;3,3;]"..
|
||||
"list[current_player;craftpreview;7,1;1,1;]")
|
||||
end)
|
||||
end)]]
|
||||
|
||||
minetest.log("experimental modname="..dump(minetest.get_current_modname()))
|
||||
minetest.log("experimental modpath="..dump(minetest.get_modpath("experimental")))
|
||||
minetest.log("experimental worldpath="..dump(minetest.get_worldpath()))
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 209 B |
1
games/minimal/mods/stairs/depends.txt
Normal file
1
games/minimal/mods/stairs/depends.txt
Normal file
@@ -0,0 +1 @@
|
||||
default
|
||||
93
games/minimal/mods/stairs/init.lua
Normal file
93
games/minimal/mods/stairs/init.lua
Normal file
@@ -0,0 +1,93 @@
|
||||
stairs = {}
|
||||
|
||||
-- Node will be called stairs:stair_<subname>
|
||||
function stairs.register_stair(subname, recipeitem, groups, images, description)
|
||||
minetest.register_node("stairs:stair_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = true,
|
||||
groups = groups,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
{-0.5, 0, 0, 0.5, 0.5, 0.5},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:stair_' .. subname .. ' 4',
|
||||
recipe = {
|
||||
{recipeitem, "", ""},
|
||||
{recipeitem, recipeitem, ""},
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Node will be called stairs:slab_<subname>
|
||||
function stairs.register_slab(subname, recipeitem, groups, images, description)
|
||||
minetest.register_node("stairs:slab_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
is_ground_content = true,
|
||||
groups = groups,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:slab_' .. subname .. ' 3',
|
||||
recipe = {
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Nodes will be called stairs:{stair,slab}_<subname>
|
||||
function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab)
|
||||
stairs.register_stair(subname, recipeitem, groups, images, desc_stair)
|
||||
stairs.register_slab(subname, recipeitem, groups, images, desc_slab)
|
||||
end
|
||||
|
||||
stairs.register_stair_and_slab("wood", "default:wood",
|
||||
{snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||
{"default_wood.png"},
|
||||
"Wooden stair",
|
||||
"Wooden slab")
|
||||
|
||||
stairs.register_stair_and_slab("stone", "default:stone",
|
||||
{cracky=3},
|
||||
{"default_stone.png"},
|
||||
"Stone stair",
|
||||
"Stone slab")
|
||||
|
||||
stairs.register_stair_and_slab("cobble", "default:cobble",
|
||||
{cracky=3},
|
||||
{"default_cobble.png"},
|
||||
"Cobble stair",
|
||||
"Cobble slab")
|
||||
|
||||
stairs.register_stair_and_slab("brick", "default:brick",
|
||||
{cracky=3},
|
||||
{"default_brick.png"},
|
||||
"Brick stair",
|
||||
"Brick slab")
|
||||
|
||||
stairs.register_stair_and_slab("sandstone", "default:sandstone",
|
||||
{crumbly=2,cracky=2},
|
||||
{"default_sandstone.png"},
|
||||
"Sandstone stair",
|
||||
"Sandstone slab")
|
||||
@@ -52,7 +52,8 @@
|
||||
# Some (temporary) keys for debugging
|
||||
#keymap_print_debug_stacks = KEY_KEY_P
|
||||
|
||||
# The desired FPS
|
||||
# Minimum FPS
|
||||
# The amount of rendered stuff is dynamically set according to this
|
||||
#wanted_fps = 30
|
||||
# If FPS would go higher than this, limit it by sleeping
|
||||
# (to not waste CPU power for no benefit)
|
||||
@@ -117,6 +118,8 @@
|
||||
# Sound settings
|
||||
#enable_sound = true
|
||||
#sound_volume = 0.7
|
||||
# Whether node texture animations should be desynchronized per MapBlock
|
||||
#desynchronize_mapblock_texture_animation = true
|
||||
|
||||
#
|
||||
# Server stuff
|
||||
@@ -144,14 +147,19 @@
|
||||
#give_initial_stuff = false
|
||||
# New users need to input this password
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
# Available privileges: interact, shout, teleport, settime, privs, ...
|
||||
# See /privs in game for a full list on your server and mod configuration.
|
||||
#default_privs = interact, shout
|
||||
# Whether players are shown to clients without any range limit
|
||||
#unlimited_player_transfer_distance = true
|
||||
# Whether to enable players killing each other
|
||||
#enable_pvp = true
|
||||
# If this is set, players will always (re)spawn at the given position
|
||||
#static_spawnpoint = 0, 10, 0
|
||||
# If true, new players cannot join with an empty password
|
||||
#disallow_empty_password = false
|
||||
# If true, disable cheat prevention in multiplayer
|
||||
#disable_anticheat = false
|
||||
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
|
||||
@@ -199,11 +199,16 @@ set(common_SRCS
|
||||
mapsector.cpp
|
||||
map.cpp
|
||||
player.cpp
|
||||
utility.cpp
|
||||
test.cpp
|
||||
sha1.cpp
|
||||
base64.cpp
|
||||
ban.cpp
|
||||
util/serialize.cpp
|
||||
util/directiontables.cpp
|
||||
util/numeric.cpp
|
||||
util/pointedthing.cpp
|
||||
util/string.cpp
|
||||
util/timetaker.cpp
|
||||
)
|
||||
|
||||
# This gives us the icon
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef ACTIVEOBJECT_HEADER
|
||||
#define ACTIVEOBJECT_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
|
||||
#define ACTIVEOBJECT_TYPE_INVALID 0
|
||||
|
||||
@@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <string>
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include "common_irrlicht.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
class BanManager
|
||||
|
||||
@@ -40,7 +40,7 @@ static inline bool is_base64(unsigned char c) {
|
||||
|
||||
bool base64_is_valid(std::string const& s)
|
||||
{
|
||||
for(int i=0; i<s.size(); i++)
|
||||
for(size_t i=0; i<s.size(); i++)
|
||||
if(!is_base64(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gamedef.h"
|
||||
#include "sound.h"
|
||||
#include "event.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/mathconstants.h"
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
|
||||
IGameDef *gamedef):
|
||||
@@ -212,8 +214,22 @@ void Camera::step(f32 dtime)
|
||||
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
f32 tool_reload_ratio)
|
||||
{
|
||||
// Get player position
|
||||
// Smooth the movement when walking up stairs
|
||||
v3f old_player_position = m_playernode->getPosition();
|
||||
v3f player_position = player->getPosition();
|
||||
//if(player->touching_ground && player_position.Y > old_player_position.Y)
|
||||
if(player->touching_ground &&
|
||||
player_position.Y > old_player_position.Y)
|
||||
{
|
||||
f32 oldy = old_player_position.Y;
|
||||
f32 newy = player_position.Y;
|
||||
f32 t = exp(-23*frametime);
|
||||
player_position.Y = oldy * t + newy * (1-t);
|
||||
}
|
||||
|
||||
// Set player node transformation
|
||||
m_playernode->setPosition(player->getPosition());
|
||||
m_playernode->setPosition(player_position);
|
||||
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
|
||||
m_playernode->updateAbsolutePosition();
|
||||
|
||||
@@ -234,17 +250,17 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
|
||||
#if 1
|
||||
f32 bobknob = 1.2;
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI);
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * M_PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * M_PI);
|
||||
|
||||
v3f bobvec = v3f(
|
||||
0.3 * bobdir * sin(bobfrac * PI),
|
||||
0.3 * bobdir * sin(bobfrac * M_PI),
|
||||
-0.28 * bobtmp * bobtmp,
|
||||
0.);
|
||||
|
||||
//rel_cam_pos += 0.2 * bobvec;
|
||||
//rel_cam_target += 0.03 * bobvec;
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI);
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * M_PI);
|
||||
float f = 1.0;
|
||||
f *= g_settings->getFloat("view_bobbing_amount");
|
||||
rel_cam_pos += bobvec * f;
|
||||
@@ -253,10 +269,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
rel_cam_target.Z -= 0.005 * bobvec.Z * f;
|
||||
//rel_cam_target.X -= 0.005 * bobvec.X * f;
|
||||
//rel_cam_target.Y -= 0.005 * bobvec.Y * f;
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f);
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * M_PI * f);
|
||||
#else
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * PI);
|
||||
f32 angle_rad = angle_deg * PI / 180;
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * M_PI);
|
||||
f32 angle_rad = angle_deg * M_PI / 180;
|
||||
f32 r = 0.05;
|
||||
v3f off = v3f(
|
||||
r * sin(angle_rad),
|
||||
@@ -289,7 +305,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
|
||||
// FOV and aspect ratio
|
||||
m_aspect = (f32)screensize.X / (f32) screensize.Y;
|
||||
m_fov_y = fov_degrees * PI / 180.0;
|
||||
m_fov_y = fov_degrees * M_PI / 180.0;
|
||||
// Increase vertical FOV on lower aspect ratios (<16:10)
|
||||
m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect)));
|
||||
// WTF is this? It can't be right
|
||||
@@ -320,22 +336,22 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 digfrac = m_digging_anim;
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * PI);
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * M_PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * M_PI);
|
||||
wield_position.Z += 5 * digfrac;
|
||||
|
||||
// Euler angles are PURE EVIL, so why not use quaternions?
|
||||
core::quaternion quat_begin(wield_rotation * core::DEGTORAD);
|
||||
core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD);
|
||||
core::quaternion quat_slerp;
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI));
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI));
|
||||
quat_slerp.toEuler(wield_rotation);
|
||||
wield_rotation *= core::RADTODEG;
|
||||
}
|
||||
else {
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim);
|
||||
wield_position.X -= sin(bobfrac*PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0;
|
||||
wield_position.X -= sin(bobfrac*M_PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*M_PI) * 3.0;
|
||||
}
|
||||
m_wieldnode->setPosition(wield_position);
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
@@ -538,7 +554,7 @@ void Camera::drawWieldedTool()
|
||||
// Draw the wielded node (in a separate scene manager)
|
||||
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
|
||||
cam->setAspectRatio(m_cameranode->getAspectRatio());
|
||||
cam->setFOV(72.0*PI/180.0);
|
||||
cam->setFOV(72.0*M_PI/180.0);
|
||||
cam->setNearValue(0.1);
|
||||
cam->setFarValue(100);
|
||||
m_wieldmgr->drawAll();
|
||||
|
||||
@@ -20,11 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CAMERA_HEADER
|
||||
#define CAMERA_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "inventory.h"
|
||||
#include "mesh.h"
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include "util/numeric.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
|
||||
class LocalPlayer;
|
||||
|
||||
@@ -19,10 +19,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "chat.h"
|
||||
#include "debug.h"
|
||||
#include "utility.h"
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include "util/string.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
ChatBuffer::ChatBuffer(u32 scrollback):
|
||||
m_scrollback(scrollback),
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CHAT_HEADER
|
||||
#define CHAT_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
|
||||
// Chat console related classes, only used by the client
|
||||
|
||||
@@ -18,7 +18,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "utility.h"
|
||||
#include <iostream>
|
||||
#include "clientserver.h"
|
||||
#include "jmutexautolock.h"
|
||||
@@ -40,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "clientmap.h"
|
||||
#include "filecache.h"
|
||||
#include "sound.h"
|
||||
#include "utility_string.h"
|
||||
#include "util/string.h"
|
||||
#include "hex.h"
|
||||
|
||||
static std::string getMediaCacheDir()
|
||||
@@ -1689,6 +1688,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
infostream<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_INVENTORY_FORMSPEC)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
// Store formspec in LocalPlayer
|
||||
Player *player = m_env.getLocalPlayer();
|
||||
assert(player != NULL);
|
||||
player->inventory_formspec = deSerializeLongString(is);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
|
||||
@@ -22,18 +22,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "connection.h"
|
||||
#include "environment.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "jmutex.h"
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "clientobject.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
#include "gamedef.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "filesys.h"
|
||||
#include "filecache.h"
|
||||
#include "localplayer.h"
|
||||
#include "util/pointedthing.h"
|
||||
|
||||
struct MeshMakeData;
|
||||
class MapBlockMesh;
|
||||
|
||||
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapblock.h"
|
||||
#include "profiler.h"
|
||||
#include "settings.h"
|
||||
#include "util/mathconstants.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -46,7 +47,7 @@ ClientMap::ClientMap(
|
||||
m_control(control),
|
||||
m_camera_position(0,0,0),
|
||||
m_camera_direction(0,0,1),
|
||||
m_camera_fov(PI)
|
||||
m_camera_fov(M_PI)
|
||||
{
|
||||
m_camera_mutex.Init();
|
||||
assert(m_camera_mutex.IsInitialized());
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTMAP_HEADER
|
||||
#define CLIENTMAP_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "map.h"
|
||||
|
||||
struct MapDrawControl
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTOBJECT_HEADER
|
||||
#define CLIENTOBJECT_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "activeobject.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTSERVER_HEADER
|
||||
#define CLIENTSERVER_HEADER
|
||||
|
||||
#include "utility.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
/*
|
||||
changes by PROTOCOL_VERSION:
|
||||
@@ -54,9 +54,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
PROTOCOL_VERSION 10:
|
||||
TOCLIENT_PRIVILEGES
|
||||
Version raised to force 'fly' and 'fast' privileges into effect.
|
||||
Node metadata change (came in later; somewhat incompatible)
|
||||
PROTOCOL_VERSION 11:
|
||||
TileDef in ContentFeatures
|
||||
Nodebox drawtype
|
||||
Added after a release: TOCLIENT_INVENTORY_FORMSPEC
|
||||
*/
|
||||
|
||||
#define PROTOCOL_VERSION 10
|
||||
#define PROTOCOL_VERSION 11
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
@@ -304,6 +309,13 @@ enum ToClientCommand
|
||||
u16 len
|
||||
u8[len] privilege
|
||||
*/
|
||||
|
||||
TOCLIENT_INVENTORY_FORMSPEC = 0x42,
|
||||
/*
|
||||
u16 command
|
||||
u32 len
|
||||
u8[len] formspec
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTSIMPLEOBJECT_HEADER
|
||||
#define CLIENTSIMPLEOBJECT_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
class ClientEnvironment;
|
||||
|
||||
class ClientSimpleObject
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLOUDS_HEADER
|
||||
#define CLOUDS_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <iostream>
|
||||
|
||||
class Clouds : public scene::ISceneNode
|
||||
|
||||
@@ -22,32 +22,249 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "map.h"
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "log.h"
|
||||
#include <vector>
|
||||
#include "util/timetaker.h"
|
||||
#include "main.h" // g_profiler
|
||||
#include "profiler.h"
|
||||
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// The time after which the collision occurs is stored in dtime.
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime)
|
||||
{
|
||||
//TimeTaker tt("axisAlignedCollision");
|
||||
|
||||
f32 xsize = (staticbox.MaxEdge.X - staticbox.MinEdge.X);
|
||||
f32 ysize = (staticbox.MaxEdge.Y - staticbox.MinEdge.Y);
|
||||
f32 zsize = (staticbox.MaxEdge.Z - staticbox.MinEdge.Z);
|
||||
|
||||
aabb3f relbox(
|
||||
movingbox.MinEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MinEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MinEdge.Z - staticbox.MinEdge.Z,
|
||||
movingbox.MaxEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MaxEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MaxEdge.Z - staticbox.MinEdge.Z
|
||||
);
|
||||
|
||||
if(speed.X > 0) // Check for collision with X- plane
|
||||
{
|
||||
if(relbox.MaxEdge.X <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.X / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MinEdge.X > xsize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.X < 0) // Check for collision with X+ plane
|
||||
{
|
||||
if(relbox.MinEdge.X >= xsize - d)
|
||||
{
|
||||
dtime = (xsize - relbox.MinEdge.X) / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MaxEdge.X < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Y > 0) // Check for collision with Y- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Y <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Y / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MinEdge.Y > ysize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.Y < 0) // Check for collision with Y+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Y >= ysize - d)
|
||||
{
|
||||
dtime = (ysize - relbox.MinEdge.Y) / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MaxEdge.Y < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Z > 0) // Check for collision with Z- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Z <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Z / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MinEdge.Z > zsize)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
else if(speed.Z < 0) // Check for collision with Z+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Z >= zsize - d)
|
||||
{
|
||||
dtime = (zsize - relbox.MinEdge.Z) / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MaxEdge.Z < 0)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d)
|
||||
{
|
||||
//TimeTaker tt("wouldCollideWithCeiling");
|
||||
|
||||
assert(y_increase >= 0);
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = staticboxes.begin();
|
||||
i != staticboxes.end(); i++)
|
||||
{
|
||||
const aabb3f& staticbox = *i;
|
||||
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
|
||||
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
|
||||
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
|
||||
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
|
||||
(movingbox.MinEdge.Z < staticbox.MaxEdge.Z) &&
|
||||
(movingbox.MaxEdge.Z > staticbox.MinEdge.Z))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
//TimeTaker tt("collisionMoveSimple");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
|
||||
|
||||
collisionMoveResult result;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
/*
|
||||
Calculate new velocity
|
||||
*/
|
||||
speed_f += accel_f * dtime;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
if(speed_f.getLength() == 0)
|
||||
return result;
|
||||
|
||||
v3f oldpos_f = pos_f;
|
||||
v3s16 oldpos_i = floatToInt(oldpos_f, BS);
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
Collect node boxes in movement range
|
||||
*/
|
||||
pos_f += speed_f * dtime;
|
||||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
{
|
||||
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
||||
|
||||
v3s16 oldpos_i = floatToInt(pos_f, BS);
|
||||
v3s16 newpos_i = floatToInt(pos_f + speed_f * dtime, BS);
|
||||
s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1;
|
||||
s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1;
|
||||
s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1;
|
||||
s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1;
|
||||
|
||||
for(s16 x = min_x; x <= max_x; x++)
|
||||
for(s16 y = min_y; y <= max_y; y++)
|
||||
for(s16 z = min_z; z <= max_z; z++)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> nodeboxes = n.getNodeBoxes(gamedef->ndef());
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = nodeboxes.begin();
|
||||
i != nodeboxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += v3f(x, y, z)*BS;
|
||||
box.MaxEdge += v3f(x, y, z)*BS;
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(false);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Collide with unloaded nodes
|
||||
aabb3f box = getNodeBox(v3s16(x,y,z), BS);
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(true);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
} // tt2
|
||||
|
||||
assert(cboxes.size() == is_unloaded.size());
|
||||
assert(cboxes.size() == is_step_up.size());
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
// position in nodes
|
||||
v3s16 pos_i = floatToInt(pos_f, BS);
|
||||
|
||||
|
||||
/*
|
||||
Collision uncertainty radius
|
||||
Make it a bit larger than the maximum distance of movement
|
||||
@@ -58,49 +275,129 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
|
||||
// This should always apply, otherwise there are glitches
|
||||
assert(d > pos_max_d);
|
||||
|
||||
/*
|
||||
Calculate collision box
|
||||
*/
|
||||
core::aabbox3d<f32> box = box_0;
|
||||
box.MaxEdge += pos_f;
|
||||
box.MinEdge += pos_f;
|
||||
core::aabbox3d<f32> oldbox = box_0;
|
||||
oldbox.MaxEdge += oldpos_f;
|
||||
oldbox.MinEdge += oldpos_f;
|
||||
|
||||
/*
|
||||
If the object lies on a walkable node, this is set to true.
|
||||
*/
|
||||
result.touching_ground = false;
|
||||
|
||||
/*
|
||||
Go through every node around the object
|
||||
*/
|
||||
s16 min_x = (box_0.MinEdge.X / BS) - 2;
|
||||
s16 min_y = (box_0.MinEdge.Y / BS) - 2;
|
||||
s16 min_z = (box_0.MinEdge.Z / BS) - 2;
|
||||
s16 max_x = (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = (box_0.MaxEdge.Z / BS) + 1;
|
||||
for(s16 y = oldpos_i.Y + min_y; y <= oldpos_i.Y + max_y; y++)
|
||||
for(s16 z = oldpos_i.Z + min_z; z <= oldpos_i.Z + max_z; z++)
|
||||
for(s16 x = oldpos_i.X + min_x; x <= oldpos_i.X + max_x; x++)
|
||||
int loopcount = 0;
|
||||
|
||||
while(dtime > BS*1e-10)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
//TimeTaker tt3("collisionMoveSimple dtime loop");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG);
|
||||
|
||||
// Avoid infinite loop
|
||||
loopcount++;
|
||||
if(loopcount >= 100)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, aborting to avoid infiniite loop"<<std::endl;
|
||||
dtime = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
aabb3f movingbox = box_0;
|
||||
movingbox.MinEdge += pos_f;
|
||||
movingbox.MaxEdge += pos_f;
|
||||
|
||||
int nearest_collided = -1;
|
||||
f32 nearest_dtime = dtime;
|
||||
u32 nearest_boxindex = -1;
|
||||
|
||||
/*
|
||||
Go through every nodebox, find nearest collision
|
||||
*/
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
// Ignore if already stepped up this nodebox.
|
||||
if(is_step_up[boxindex])
|
||||
continue;
|
||||
|
||||
// Find nearest collision of the two boxes (raytracing-like)
|
||||
f32 dtime_tmp;
|
||||
int collided = axisAlignedCollision(
|
||||
cboxes[boxindex], movingbox, speed_f, d, dtime_tmp);
|
||||
|
||||
if(collided == -1 || dtime_tmp >= nearest_dtime)
|
||||
continue;
|
||||
|
||||
nearest_dtime = dtime_tmp;
|
||||
nearest_collided = collided;
|
||||
nearest_boxindex = boxindex;
|
||||
}
|
||||
|
||||
if(nearest_collided == -1)
|
||||
{
|
||||
// No collision with any collision box.
|
||||
pos_f += speed_f * dtime;
|
||||
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, a collision occurred.
|
||||
|
||||
const aabb3f& cbox = cboxes[nearest_boxindex];
|
||||
|
||||
// Check for stairs.
|
||||
bool step_up = (nearest_collided != 1) && // must not be Y direction
|
||||
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||
(!wouldCollideWithCeiling(cboxes, movingbox,
|
||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||
d));
|
||||
|
||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||
if(nearest_dtime < 0)
|
||||
{
|
||||
// Handle negative nearest_dtime (can be caused by the d allowance)
|
||||
if(!step_up)
|
||||
{
|
||||
if(nearest_collided == 0)
|
||||
pos_f.X += speed_f.X * nearest_dtime;
|
||||
if(nearest_collided == 1)
|
||||
pos_f.Y += speed_f.Y * nearest_dtime;
|
||||
if(nearest_collided == 2)
|
||||
pos_f.Z += speed_f.Z * nearest_dtime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos_f += speed_f * nearest_dtime;
|
||||
dtime -= nearest_dtime;
|
||||
}
|
||||
|
||||
// Set the speed component that caused the collision to zero
|
||||
if(step_up)
|
||||
{
|
||||
// Special case: Handle stairs
|
||||
is_step_up[nearest_boxindex] = true;
|
||||
}
|
||||
else if(nearest_collided == 0) // X
|
||||
{
|
||||
speed_f.X = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
else if(nearest_collided == 1) // Y
|
||||
{
|
||||
speed_f.Y = 0;
|
||||
result.collides = true;
|
||||
}
|
||||
else if(nearest_collided == 2) // Z
|
||||
{
|
||||
speed_f.Z = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Final touches: Check if standing on ground, step up stairs.
|
||||
*/
|
||||
aabb3f box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
const aabb3f& cbox = cboxes[boxindex];
|
||||
|
||||
/*
|
||||
See if the object is touching ground.
|
||||
|
||||
@@ -111,112 +408,50 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
Use 0.15*BS so that it is easier to get on a node.
|
||||
*/
|
||||
if(
|
||||
//fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < d
|
||||
fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS
|
||||
&& nodebox.MaxEdge.X-d > box.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < box.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > box.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < box.MaxEdge.Z
|
||||
cbox.MaxEdge.X-d > box.MinEdge.X &&
|
||||
cbox.MinEdge.X+d < box.MaxEdge.X &&
|
||||
cbox.MaxEdge.Z-d > box.MinEdge.Z &&
|
||||
cbox.MinEdge.Z+d < box.MaxEdge.Z
|
||||
){
|
||||
result.touching_ground = true;
|
||||
}
|
||||
|
||||
// If object doesn't intersect with node, ignore node.
|
||||
if(box.intersectsWithBox(nodebox) == false)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Go through every axis
|
||||
*/
|
||||
v3f dirs[3] = {
|
||||
v3f(0,0,1), // back-front
|
||||
v3f(0,1,0), // top-bottom
|
||||
v3f(1,0,0), // right-left
|
||||
};
|
||||
for(u16 i=0; i<3; i++)
|
||||
{
|
||||
/*
|
||||
Calculate values along the axis
|
||||
*/
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 objectmax = box.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 objectmin = box.MinEdge.dotProduct(dirs[i]);
|
||||
f32 objectmax_old = oldbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 objectmin_old = oldbox.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
/*
|
||||
Check collision for the axis.
|
||||
Collision happens when object is going through a surface.
|
||||
*/
|
||||
bool negative_axis_collides =
|
||||
(nodemax > objectmin && nodemax <= objectmin_old + d
|
||||
&& speed_f.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < objectmax && nodemin >= objectmax_old - d
|
||||
&& speed_f.dotProduct(dirs[i]) > 0);
|
||||
bool main_axis_collides =
|
||||
negative_axis_collides || positive_axis_collides;
|
||||
|
||||
/*
|
||||
Check overlap of object and node in other axes
|
||||
*/
|
||||
bool other_axes_overlap = true;
|
||||
for(u16 j=0; j<3; j++)
|
||||
if(is_step_up[boxindex])
|
||||
{
|
||||
if(j == i)
|
||||
continue;
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||
f32 objectmax = box.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 objectmin = box.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > objectmin && nodemin + d < objectmax))
|
||||
{
|
||||
other_axes_overlap = false;
|
||||
break;
|
||||
}
|
||||
pos_f.Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
|
||||
box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
}
|
||||
|
||||
/*
|
||||
If this is a collision, revert the pos_f in the main
|
||||
direction.
|
||||
*/
|
||||
if(other_axes_overlap && main_axis_collides)
|
||||
if(fabs(cbox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS)
|
||||
{
|
||||
speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
|
||||
pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
|
||||
pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
|
||||
result.collides = true;
|
||||
result.touching_ground = true;
|
||||
if(is_unloaded[boxindex])
|
||||
result.standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
}
|
||||
} // xyz
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This doesn't seem to work and isn't used
|
||||
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
collisionMoveResult final_result;
|
||||
//TimeTaker tt("collisionMovePrecise");
|
||||
ScopeProfiler sp(g_profiler, "collisionMovePrecise avg", SPT_AVG);
|
||||
|
||||
collisionMoveResult final_result;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
if(speed_f.getLength() == 0)
|
||||
return final_result;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
// Don't allow overly huge dtime
|
||||
if(dtime > 2.0)
|
||||
dtime = 2.0;
|
||||
|
||||
|
||||
f32 dtime_downcount = dtime;
|
||||
|
||||
u32 loopcount = 0;
|
||||
@@ -224,6 +459,16 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = 1.0;
|
||||
if(speed_f.getLength() != 0)
|
||||
dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime_downcount > dtime_max_increment)
|
||||
{
|
||||
@@ -242,17 +487,20 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
}
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(map, gamedef,
|
||||
pos_max_d, box_0, dtime_part, pos_f, speed_f);
|
||||
pos_max_d, box_0, stepheight, dtime_part,
|
||||
pos_f, speed_f, accel_f);
|
||||
|
||||
if(result.touching_ground)
|
||||
final_result.touching_ground = true;
|
||||
if(result.collides)
|
||||
final_result.collides = true;
|
||||
if(result.collides_xz)
|
||||
final_result.collides_xz = true;
|
||||
if(result.standing_on_unloaded)
|
||||
final_result.standing_on_unloaded = true;
|
||||
}
|
||||
while(dtime_downcount > 0.001);
|
||||
|
||||
|
||||
return final_result;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef COLLISION_HEADER
|
||||
#define COLLISION_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <vector>
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
@@ -29,22 +30,47 @@ struct collisionMoveResult
|
||||
{
|
||||
bool touching_ground;
|
||||
bool collides;
|
||||
bool collides_xz;
|
||||
bool standing_on_unloaded;
|
||||
|
||||
collisionMoveResult():
|
||||
touching_ground(false),
|
||||
collides(false)
|
||||
collides(false),
|
||||
collides_xz(false),
|
||||
standing_on_unloaded(false)
|
||||
{}
|
||||
};
|
||||
|
||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
|
||||
#if 0
|
||||
// This doesn't seem to work and isn't used
|
||||
// Moves using as many iterations as needed
|
||||
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
#endif
|
||||
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// dtime receives time until first collision, invalid if -1 is returned
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime);
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d);
|
||||
|
||||
|
||||
enum CollisionType
|
||||
{
|
||||
|
||||
@@ -22,10 +22,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serialization.h"
|
||||
#include "log.h"
|
||||
#include "porting.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/string.h"
|
||||
|
||||
namespace con
|
||||
{
|
||||
|
||||
static u16 readPeerId(u8 *packetdata)
|
||||
{
|
||||
return readU16(&packetdata[4]);
|
||||
}
|
||||
static u8 readChannel(u8 *packetdata)
|
||||
{
|
||||
return readU8(&packetdata[6]);
|
||||
}
|
||||
|
||||
BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
|
||||
u32 protocol_id, u16 sender_peer_id, u8 channel)
|
||||
{
|
||||
|
||||
@@ -20,14 +20,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CONNECTION_HEADER
|
||||
#define CONNECTION_HEADER
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "debug.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "socket.h"
|
||||
#include "utility.h"
|
||||
#include "exceptions.h"
|
||||
#include "constants.h"
|
||||
#include "util/pointer.h"
|
||||
#include "util/container.h"
|
||||
#include "util/thread.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace con
|
||||
{
|
||||
@@ -107,15 +108,6 @@ class ProcessedSilentlyException : public BaseException
|
||||
{}
|
||||
};
|
||||
|
||||
inline u16 readPeerId(u8 *packetdata)
|
||||
{
|
||||
return readU16(&packetdata[4]);
|
||||
}
|
||||
inline u8 readChannel(u8 *packetdata)
|
||||
{
|
||||
return readU8(&packetdata[6]);
|
||||
}
|
||||
|
||||
#define SEQNUM_MAX 65535
|
||||
inline bool seqnum_higher(u16 higher, u16 lower)
|
||||
{
|
||||
|
||||
@@ -24,11 +24,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
All kinds of constants.
|
||||
|
||||
Cross-platform compatibility crap should go in porting.h.
|
||||
|
||||
Some things here are legacy crap.
|
||||
*/
|
||||
|
||||
//#define HAXMODE 0
|
||||
|
||||
#define DEBUGFILE "debug.txt"
|
||||
/*
|
||||
Connection
|
||||
*/
|
||||
|
||||
// Define for simulating the quirks of sending through internet.
|
||||
// Causes the socket class to deliberately drop random packets.
|
||||
@@ -42,63 +44,50 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// resend_timeout = avg_rtt * this
|
||||
#define RESEND_TIMEOUT_FACTOR 4
|
||||
|
||||
#define PI 3.14159
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's
|
||||
// going near the limit or not, so this is lower.
|
||||
#define MAP_GENERATION_LIMIT (31000)
|
||||
|
||||
// Size of node in rendering units
|
||||
#define BS (10.0)
|
||||
|
||||
#define MAP_BLOCKSIZE 16
|
||||
/*
|
||||
This makes mesh updates too slow, as many meshes are updated during
|
||||
the main loop (related to TempMods and day/night)
|
||||
Server
|
||||
*/
|
||||
//#define MAP_BLOCKSIZE 32
|
||||
|
||||
// Sectors are split to SECTOR_HEIGHTMAP_SPLIT^2 heightmaps
|
||||
#define SECTOR_HEIGHTMAP_SPLIT (MAP_BLOCKSIZE/8)
|
||||
|
||||
// Time after building, during which the following limit
|
||||
// is in use
|
||||
//#define FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING 2.0
|
||||
// This many blocks are sent when player is building
|
||||
#define LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS 0
|
||||
// Override for the previous one when distance of block
|
||||
// is very low
|
||||
// Override for the previous one when distance of block is very low
|
||||
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1
|
||||
|
||||
/*
|
||||
Map-related things
|
||||
*/
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's going near
|
||||
// the limit or not, so this is lower.
|
||||
#define MAP_GENERATION_LIMIT (31000)
|
||||
|
||||
// Size of node in floating-point units
|
||||
// The original idea behind this is to disallow plain casts between
|
||||
// floating-point and integer positions, which potentially give wrong
|
||||
// results. (negative coordinates, values between nodes, ...)
|
||||
// Use floatToInt(p, BS) and intToFloat(p, BS).
|
||||
#define BS (10.0)
|
||||
|
||||
// Dimension of a MapBlock
|
||||
#define MAP_BLOCKSIZE 16
|
||||
// This makes mesh updates too slow, as many meshes are updated during
|
||||
// the main loop (related to TempMods and day/night)
|
||||
//#define MAP_BLOCKSIZE 32
|
||||
|
||||
/*
|
||||
Old stuff that shouldn't be hardcoded
|
||||
*/
|
||||
|
||||
// Size of player's main inventory
|
||||
#define PLAYER_INVENTORY_SIZE (8*4)
|
||||
|
||||
#define SIGN_TEXT_MAX_LENGTH 50
|
||||
|
||||
// Whether to catch all std::exceptions.
|
||||
// Assert will be called on such an event.
|
||||
// In debug mode, leave these for the debugger and don't catch them.
|
||||
#ifdef NDEBUG
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#else
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
Collecting active blocks is stopped after object data
|
||||
size reaches this
|
||||
*/
|
||||
#define MAX_OBJECTDATA_SIZE 450
|
||||
|
||||
/*
|
||||
This is good to be a bit different than 0 so that water level
|
||||
is not between two MapBlocks
|
||||
This is good to be a bit different than 0 so that water level is not
|
||||
between two MapBlocks
|
||||
*/
|
||||
#define WATER_LEVEL 1
|
||||
|
||||
// Length of cracking animation in count of images
|
||||
#define CRACK_ANIMATION_LENGTH 5
|
||||
|
||||
// Maximum hit points of a player
|
||||
#define PLAYER_MAX_HP 20
|
||||
|
||||
|
||||
@@ -30,13 +30,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "clientobject.h"
|
||||
#include "content_object.h"
|
||||
#include "mesh.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
#include "itemdef.h"
|
||||
#include "tool.h"
|
||||
#include "content_cso.h"
|
||||
#include "sound.h"
|
||||
#include "nodedef.h"
|
||||
#include "localplayer.h"
|
||||
#include "util/numeric.h" // For IntervalLimiter
|
||||
#include "util/serialize.h"
|
||||
#include "util/mathconstants.h"
|
||||
|
||||
class Settings;
|
||||
struct ToolCapabilities;
|
||||
|
||||
@@ -879,22 +882,24 @@ class GenericCAO : public ClientActiveObject
|
||||
box.MinEdge *= BS;
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||
f32 pos_max_d = BS*0.125; // Distance per iteration
|
||||
f32 stepheight = 0;
|
||||
v3f p_pos = m_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||
moveresult = collisionMoveSimple(&env->getMap(), gamedef,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
m_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
m_acceleration = p_acceleration;
|
||||
|
||||
bool is_end_position = moveresult.collides;
|
||||
pos_translator.update(m_position, is_end_position, dtime);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
|
||||
m_velocity += dtime * m_acceleration;
|
||||
} else {
|
||||
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
||||
m_velocity += dtime * m_acceleration;
|
||||
@@ -935,7 +940,7 @@ class GenericCAO : public ClientActiveObject
|
||||
}
|
||||
}
|
||||
if(fabs(m_prop.automatic_rotate) > 0.001){
|
||||
m_yaw += dtime * m_prop.automatic_rotate * 180 / PI;
|
||||
m_yaw += dtime * m_prop.automatic_rotate * 180 / M_PI;
|
||||
updateNodePos();
|
||||
}
|
||||
}
|
||||
@@ -961,7 +966,7 @@ class GenericCAO : public ClientActiveObject
|
||||
else if(cam_to_entity.Y < -0.75)
|
||||
col += 4;
|
||||
else{
|
||||
float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
|
||||
float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / M_PI * 180.;
|
||||
float dir = mob_dir - m_yaw;
|
||||
dir = wrapDegrees_180(dir);
|
||||
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CONTENT_CSO_HEADER
|
||||
#define CONTENT_CSO_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "clientsimpleobject.h"
|
||||
|
||||
ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr,
|
||||
|
||||
@@ -25,6 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "tile.h"
|
||||
#include "gamedef.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
// Create a cuboid.
|
||||
// collector - the MeshCollector for the resulting polygons
|
||||
@@ -471,7 +474,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
pa_liquid.x0(), pa_liquid.y0()),
|
||||
};
|
||||
|
||||
// This fixes a strange bug
|
||||
// To get backface culling right, the vertices need to go
|
||||
// clockwise around the front of the face. And we happened to
|
||||
// calculate corner levels in exact reverse order.
|
||||
s32 corner_resolve[4] = {3,2,1,0};
|
||||
|
||||
for(s32 i=0; i<4; i++)
|
||||
@@ -482,6 +487,52 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
vertices[i].Pos.Y += corner_levels[j];
|
||||
vertices[i].Pos += intToFloat(p, BS);
|
||||
}
|
||||
|
||||
// Default downwards-flowing texture animation goes from
|
||||
// -Z towards +Z, thus the direction is +Z.
|
||||
// Rotate texture to make animation go in flow direction
|
||||
// Positive if liquid moves towards +Z
|
||||
int dz = (corner_levels[side_corners[2][0]] +
|
||||
corner_levels[side_corners[2][1]] <
|
||||
corner_levels[side_corners[3][0]] +
|
||||
corner_levels[side_corners[3][1]]);
|
||||
// Positive if liquid moves towards +X
|
||||
int dx = (corner_levels[side_corners[0][0]] +
|
||||
corner_levels[side_corners[0][1]] <
|
||||
corner_levels[side_corners[1][0]] +
|
||||
corner_levels[side_corners[1][1]]);
|
||||
// -X
|
||||
if(-dx >= abs(dz))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = t;
|
||||
}
|
||||
// +X
|
||||
if(dx >= abs(dz))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
}
|
||||
// -Z
|
||||
if(-dz >= abs(dx))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
@@ -976,6 +1027,63 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
collector.append(tile, vertices, 4, indices, 6);
|
||||
break;}
|
||||
case NDT_NODEBOX:
|
||||
{
|
||||
static const v3s16 tile_dirs[6] = {
|
||||
v3s16(0, 1, 0),
|
||||
v3s16(0, -1, 0),
|
||||
v3s16(1, 0, 0),
|
||||
v3s16(-1, 0, 0),
|
||||
v3s16(0, 0, 1),
|
||||
v3s16(0, 0, -1)
|
||||
};
|
||||
|
||||
TileSpec tiles[6];
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
// Handles facedir rotation for textures
|
||||
tiles[i] = getNodeTile(n, p, tile_dirs[i], data);
|
||||
}
|
||||
|
||||
u16 l = getInteriorLight(n, 0, data);
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
v3f pos = intToFloat(p, BS);
|
||||
|
||||
std::vector<aabb3f> boxes = n.getNodeBoxes(nodedef);
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
|
||||
// Compute texture coords
|
||||
f32 tx1 = (i->MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (i->MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (i->MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (i->MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (i->MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (i->MaxEdge.Z/BS)+0.5;
|
||||
f32 txc[24] = {
|
||||
// up
|
||||
tx1, 1-tz2, tx2, 1-tz1,
|
||||
// down
|
||||
tx1, tz1, tx2, tz2,
|
||||
// right
|
||||
tz1, 1-ty2, tz2, 1-ty1,
|
||||
// left
|
||||
1-tz2, 1-ty2, 1-tz1, 1-ty1,
|
||||
// back
|
||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||
// front
|
||||
tx1, 1-ty2, tx2, 1-ty1,
|
||||
};
|
||||
|
||||
makeCuboid(&collector, box, tiles, 6, c, txc);
|
||||
}
|
||||
break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "content_mapnode.h"
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "mapnode.h"
|
||||
#include "nodedef.h"
|
||||
#include "utility.h"
|
||||
#include "nameidmapping.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_nodemeta.h"
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "utility.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/string.h"
|
||||
#include "constants.h" // MAP_BLOCKSIZE
|
||||
#include <sstream>
|
||||
|
||||
#define NODEMETA_GENERIC 1
|
||||
|
||||
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "player.h"
|
||||
#include "scriptapi.h"
|
||||
#include "genericobject.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
@@ -141,6 +142,9 @@ TestSAO proto_TestSAO(NULL, v3f(0,0,0));
|
||||
|
||||
/*
|
||||
ItemSAO
|
||||
|
||||
DEPRECATED: New dropped items are implemented in Lua; see
|
||||
builtin/item_entity.lua.
|
||||
*/
|
||||
|
||||
class ItemSAO : public ServerActiveObject
|
||||
@@ -202,9 +206,12 @@ class ItemSAO : public ServerActiveObject
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
@@ -448,16 +455,18 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||
v3f p_pos = getBasePosition();
|
||||
f32 stepheight = 0; // Maximum climbable step height
|
||||
v3f p_pos = m_base_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
setBasePosition(p_pos);
|
||||
m_base_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
|
||||
m_velocity += dtime * m_acceleration;
|
||||
m_acceleration = p_acceleration;
|
||||
} else {
|
||||
m_base_position += dtime * m_velocity + 0.5 * dtime
|
||||
* dtime * m_acceleration;
|
||||
@@ -755,6 +764,8 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||
m_last_good_position(0,0,0),
|
||||
m_last_good_position_age(0),
|
||||
m_time_from_last_punch(0),
|
||||
m_nocheat_dig_pos(32767, 32767, 32767),
|
||||
m_nocheat_dig_time(0),
|
||||
m_wield_index(0),
|
||||
m_position_not_sent(false),
|
||||
m_armor_groups_sent(false),
|
||||
@@ -865,8 +876,9 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
}
|
||||
|
||||
m_time_from_last_punch += dtime;
|
||||
m_nocheat_dig_time += dtime;
|
||||
|
||||
if(m_is_singleplayer)
|
||||
if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
|
||||
{
|
||||
m_last_good_position = m_player->getPosition();
|
||||
m_last_good_position_age = 0;
|
||||
@@ -879,7 +891,8 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
NOTE: Actually the server should handle player physics like the
|
||||
client does and compare player's position to what is calculated
|
||||
on our side. This is required when eg. players fly due to an
|
||||
explosion.
|
||||
explosion. Altough a node-based alternative might be possible
|
||||
too, and much more lightweight.
|
||||
*/
|
||||
|
||||
float player_max_speed = 0;
|
||||
|
||||
@@ -173,6 +173,9 @@ class PlayerSAO : public ServerActiveObject
|
||||
{
|
||||
return m_peer_id;
|
||||
}
|
||||
|
||||
// Cheat prevention
|
||||
|
||||
v3f getLastGoodPosition() const
|
||||
{
|
||||
return m_last_good_position;
|
||||
@@ -183,6 +186,26 @@ class PlayerSAO : public ServerActiveObject
|
||||
m_time_from_last_punch = 0.0;
|
||||
return r;
|
||||
}
|
||||
void noCheatDigStart(v3s16 p)
|
||||
{
|
||||
m_nocheat_dig_pos = p;
|
||||
m_nocheat_dig_time = 0;
|
||||
}
|
||||
v3s16 getNoCheatDigPos()
|
||||
{
|
||||
return m_nocheat_dig_pos;
|
||||
}
|
||||
float getNoCheatDigTime()
|
||||
{
|
||||
return m_nocheat_dig_time;
|
||||
}
|
||||
void noCheatDigEnd()
|
||||
{
|
||||
m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
|
||||
}
|
||||
|
||||
// Other
|
||||
|
||||
void updatePrivileges(const std::set<std::string> &privs,
|
||||
bool is_singleplayer)
|
||||
{
|
||||
@@ -196,9 +219,14 @@ class PlayerSAO : public ServerActiveObject
|
||||
Player *m_player;
|
||||
u16 m_peer_id;
|
||||
Inventory *m_inventory;
|
||||
|
||||
// Cheat prevention
|
||||
v3f m_last_good_position;
|
||||
float m_last_good_position_age;
|
||||
float m_time_from_last_punch;
|
||||
v3s16 m_nocheat_dig_pos;
|
||||
float m_nocheat_dig_time;
|
||||
|
||||
int m_wield_index;
|
||||
bool m_position_not_sent;
|
||||
ItemGroupList m_armor_groups;
|
||||
|
||||
@@ -23,9 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include "utility.h"
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
// Check if input matches recipe
|
||||
// Takes recipe groups into account
|
||||
@@ -35,7 +35,7 @@ static bool inputItemMatchesRecipe(const std::string &inp_name,
|
||||
// Exact name
|
||||
if(inp_name == rec_name)
|
||||
return true;
|
||||
|
||||
|
||||
// Group
|
||||
if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
|
||||
std::string rec_group = rec_name.substr(6);
|
||||
@@ -43,7 +43,7 @@ static bool inputItemMatchesRecipe(const std::string &inp_name,
|
||||
if(itemgroup_get(def.groups, rec_group) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Didn't match
|
||||
return false;
|
||||
}
|
||||
@@ -84,6 +84,20 @@ static std::vector<std::string> craftGetItemNames(
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert a list of item names, to ItemStacks.
|
||||
static std::vector<ItemStack> craftGetItems(
|
||||
const std::vector<std::string> &items, IGameDef *gamedef)
|
||||
{
|
||||
std::vector<ItemStack> result;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++)
|
||||
{
|
||||
result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute bounding rectangle given a matrix of items
|
||||
// Returns false if every item is ""
|
||||
static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
|
||||
@@ -439,6 +453,11 @@ CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -507,6 +526,11 @@ CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDe
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -625,6 +649,13 @@ CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameD
|
||||
return CraftOutput(repaired.getItemString(), 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<ItemStack> stack;
|
||||
stack.push_back(ItemStack());
|
||||
return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
|
||||
}
|
||||
|
||||
void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
@@ -680,6 +711,13 @@ CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef
|
||||
return CraftOutput(output, cooktime);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<std::string> rec;
|
||||
rec.push_back(recipe);
|
||||
return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -744,6 +782,13 @@ CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *ga
|
||||
return CraftOutput("", burntime);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<std::string> rec;
|
||||
rec.push_back(recipe);
|
||||
return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -837,6 +882,47 @@ class CCraftDefManager: public IWritableCraftDefManager
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const
|
||||
{
|
||||
CraftOutput tmpout;
|
||||
tmpout.item = "";
|
||||
tmpout.time = 0;
|
||||
|
||||
// If output item is empty, abort.
|
||||
if(output.item.empty())
|
||||
return false;
|
||||
|
||||
// Walk crafting definitions from back to front, so that later
|
||||
// definitions can override earlier ones.
|
||||
for(std::vector<CraftDefinition*>::const_reverse_iterator
|
||||
i = m_craft_definitions.rbegin();
|
||||
i != m_craft_definitions.rend(); i++)
|
||||
{
|
||||
CraftDefinition *def = *i;
|
||||
|
||||
/*infostream<<"Checking "<<input.dump()<<std::endl
|
||||
<<" against "<<def->dump()<<std::endl;*/
|
||||
|
||||
try {
|
||||
tmpout = def->getOutput(input, gamedef);
|
||||
if(tmpout.item.substr(0,output.item.length()) == output.item)
|
||||
{
|
||||
// Get output, then decrement input (if requested)
|
||||
input = def->getInput(output, gamedef);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"getCraftResult: ERROR: "
|
||||
<<"Serialization error in recipe "
|
||||
<<def->dump()<<std::endl;
|
||||
// then go on with the next craft definition
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual std::string dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
||||
@@ -130,6 +130,8 @@ class CraftDefinition
|
||||
// Returns the output structure, meaning depends on crafting method
|
||||
// The implementation can assume that check(input) returns true
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||
// the inverse of the above
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
|
||||
// Decreases count of every input item
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
|
||||
|
||||
@@ -164,6 +166,7 @@ class CraftDefinitionShaped: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -205,6 +208,7 @@ class CraftDefinitionShapeless: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -242,6 +246,7 @@ class CraftDefinitionToolRepair: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -281,6 +286,7 @@ class CraftDefinitionCooking: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -320,6 +326,7 @@ class CraftDefinitionFuel: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -349,6 +356,8 @@ class ICraftDefManager
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
@@ -365,6 +374,8 @@ class IWritableCraftDefManager : public ICraftDefManager
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
|
||||
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
/*
|
||||
Debug output
|
||||
|
||||
13
src/debug.h
13
src/debug.h
@@ -24,10 +24,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <iostream>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <irrMap.h>
|
||||
#include "threads.h"
|
||||
#include "gettime.h"
|
||||
#include "constants.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -39,6 +39,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#else
|
||||
#endif
|
||||
|
||||
// Whether to catch all std::exceptions.
|
||||
// Assert will be called on such an event.
|
||||
// In debug mode, leave these for the debugger and don't catch them.
|
||||
#ifdef NDEBUG
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#else
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
Debug output
|
||||
*/
|
||||
|
||||
@@ -103,6 +103,7 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("console_alpha", "200");
|
||||
settings->setDefault("enable_sound", "true");
|
||||
settings->setDefault("sound_volume", "0.8");
|
||||
settings->setDefault("desynchronize_mapblock_texture_animation", "true");
|
||||
|
||||
// Server stuff
|
||||
// "map-dir" doesn't exist by default.
|
||||
@@ -119,6 +120,8 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("default_privs", "interact, shout");
|
||||
settings->setDefault("unlimited_player_transfer_distance", "true");
|
||||
settings->setDefault("enable_pvp", "true");
|
||||
settings->setDefault("disallow_empty_password", "false");
|
||||
settings->setDefault("disable_anticheat", "false");
|
||||
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
|
||||
@@ -31,12 +31,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "player.h"
|
||||
#include "map.h"
|
||||
#include <ostream>
|
||||
#include "utility.h"
|
||||
#include "activeobject.h"
|
||||
#include "util/container.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
|
||||
@@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
distance according to map seed
|
||||
*/
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
|
||||
#define FARMESH_MATERIAL_COUNT 2
|
||||
|
||||
|
||||
@@ -19,15 +19,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "filecache.h"
|
||||
|
||||
#include "clientserver.h"
|
||||
#include "log.h"
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "hex.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
bool FileCache::loadByPath(const std::string &path, std::ostream &os)
|
||||
{
|
||||
|
||||
378
src/game.cpp
378
src/game.cpp
@@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "game.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
@@ -61,17 +61,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#endif
|
||||
#include "event_manager.h"
|
||||
#include <list>
|
||||
|
||||
/*
|
||||
Setting this to 1 enables a special camera mode that forces
|
||||
the renderers to think that the camera statically points from
|
||||
the starting place to a static direction.
|
||||
|
||||
This allows one to move around with the player and see what
|
||||
is actually drawn behind solid things and behind the player.
|
||||
*/
|
||||
#define FIELD_OF_VIEW_TEST 0
|
||||
|
||||
#include "util/directiontables.h"
|
||||
|
||||
/*
|
||||
Text input system
|
||||
@@ -154,6 +144,22 @@ class NodeMetadataFormSource: public IFormSource
|
||||
v3s16 m_p;
|
||||
};
|
||||
|
||||
class PlayerInventoryFormSource: public IFormSource
|
||||
{
|
||||
public:
|
||||
PlayerInventoryFormSource(Client *client):
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
std::string getForm()
|
||||
{
|
||||
LocalPlayer* player = m_client->getEnv().getLocalPlayer();
|
||||
return player->inventory_formspec;
|
||||
}
|
||||
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/*
|
||||
Hotbar draw routine
|
||||
*/
|
||||
@@ -305,14 +311,12 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
core::line3d<f32> shootline, f32 d,
|
||||
bool liquids_pointable,
|
||||
bool look_for_object,
|
||||
core::aabbox3d<f32> &hilightbox,
|
||||
bool &should_show_hilightbox,
|
||||
std::vector<aabb3f> &hilightboxes,
|
||||
ClientActiveObject *&selected_object)
|
||||
{
|
||||
PointedThing result;
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(0,0,0,0,0,0);
|
||||
should_show_hilightbox = false;
|
||||
hilightboxes.clear();
|
||||
selected_object = NULL;
|
||||
|
||||
INodeDefManager *nodedef = client->getNodeDefManager();
|
||||
@@ -323,27 +327,27 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
{
|
||||
selected_object = client->getSelectedActiveObject(d*BS,
|
||||
camera_position, shootline);
|
||||
}
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
core::aabbox3d<f32> *selection_box
|
||||
= selected_object->getSelectionBox();
|
||||
// Box should exist because object was returned in the
|
||||
// first place
|
||||
assert(selection_box);
|
||||
|
||||
v3f pos = selected_object->getPosition();
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
if(selected_object->doShowSelectionBox())
|
||||
{
|
||||
aabb3f *selection_box = selected_object->getSelectionBox();
|
||||
// Box should exist because object was
|
||||
// returned in the first place
|
||||
assert(selection_box);
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos
|
||||
);
|
||||
v3f pos = selected_object->getPosition();
|
||||
hilightboxes.push_back(aabb3f(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos));
|
||||
}
|
||||
|
||||
should_show_hilightbox = selected_object->doShowSelectionBox();
|
||||
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// That didn't work, try to find a pointed at node
|
||||
@@ -363,6 +367,14 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
|
||||
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
|
||||
|
||||
// Prevent signed number overflow
|
||||
if(yend==32767)
|
||||
yend=32766;
|
||||
if(zend==32767)
|
||||
zend=32766;
|
||||
if(xend==32767)
|
||||
xend=32766;
|
||||
|
||||
for(s16 y = ystart; y <= yend; y++)
|
||||
for(s16 z = zstart; z <= zend; z++)
|
||||
for(s16 x = xstart; x <= xend; x++)
|
||||
@@ -379,196 +391,64 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
if(!isPointableNode(n, client, liquids_pointable))
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
|
||||
|
||||
v3s16 np(x,y,z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
f32 d = 0.01;
|
||||
|
||||
v3s16 dirs[6] = {
|
||||
v3s16(0,0,1), // back
|
||||
v3s16(0,1,0), // top
|
||||
v3s16(1,0,0), // right
|
||||
v3s16(0,0,-1), // front
|
||||
v3s16(0,-1,0), // bottom
|
||||
v3s16(-1,0,0), // left
|
||||
};
|
||||
|
||||
const ContentFeatures &f = nodedef->get(n);
|
||||
|
||||
if(f.selection_box.type == NODEBOX_FIXED)
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
core::aabbox3d<f32> box = f.selection_box.fixed;
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
v3s16 facedirs[6] = {
|
||||
v3s16(-1,0,0),
|
||||
v3s16(1,0,0),
|
||||
v3s16(0,-1,0),
|
||||
v3s16(0,1,0),
|
||||
v3s16(0,0,-1),
|
||||
v3s16(0,0,1),
|
||||
};
|
||||
|
||||
core::aabbox3d<f32> faceboxes[6] = {
|
||||
// X-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MinEdge.X+d, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// X+
|
||||
core::aabbox3d<f32>(
|
||||
box.MaxEdge.X-d, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Y-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MinEdge.Y+d, box.MaxEdge.Z
|
||||
),
|
||||
// Y+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MaxEdge.Y-d, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Z-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MinEdge.Z+d
|
||||
),
|
||||
// Z+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MaxEdge.Z-d,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
};
|
||||
|
||||
for(u16 i=0; i<6; i++)
|
||||
for(u16 j=0; j<6; j++)
|
||||
{
|
||||
v3f facedir_f(facedirs[i].X, facedirs[i].Y, facedirs[i].Z);
|
||||
v3f centerpoint = npf + facedir_f * BS/2;
|
||||
v3s16 facedir = g_6dirs[j];
|
||||
aabb3f facebox = box;
|
||||
|
||||
f32 d = 0.001*BS;
|
||||
if(facedir.X > 0)
|
||||
facebox.MinEdge.X = facebox.MaxEdge.X-d;
|
||||
else if(facedir.X < 0)
|
||||
facebox.MaxEdge.X = facebox.MinEdge.X+d;
|
||||
else if(facedir.Y > 0)
|
||||
facebox.MinEdge.Y = facebox.MaxEdge.Y-d;
|
||||
else if(facedir.Y < 0)
|
||||
facebox.MaxEdge.Y = facebox.MinEdge.Y+d;
|
||||
else if(facedir.Z > 0)
|
||||
facebox.MinEdge.Z = facebox.MaxEdge.Z-d;
|
||||
else if(facedir.Z < 0)
|
||||
facebox.MaxEdge.Z = facebox.MinEdge.Z+d;
|
||||
|
||||
v3f centerpoint = facebox.getCenter();
|
||||
f32 distance = (centerpoint - camera_position).getLength();
|
||||
if(distance >= mindistance)
|
||||
continue;
|
||||
if(!faceboxes[i].intersectsWithLine(shootline))
|
||||
if(!facebox.intersectsWithLine(shootline))
|
||||
continue;
|
||||
|
||||
v3s16 np_above = np + facedir;
|
||||
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np+facedirs[i];
|
||||
result.node_abovesurface = np_above;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
}
|
||||
else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS/2 - BS/6 - BS/20;
|
||||
v3f cpf = npf + dir_f;
|
||||
f32 distance = (cpf - camera_position).getLength();
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
// top
|
||||
if(dir == v3s16(0,1,0)){
|
||||
box = f.selection_box.wall_top;
|
||||
}
|
||||
// bottom
|
||||
else if(dir == v3s16(0,-1,0)){
|
||||
box = f.selection_box.wall_bottom;
|
||||
}
|
||||
// side
|
||||
else{
|
||||
v3f vertices[2] =
|
||||
hilightboxes.clear();
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i2 = boxes.begin();
|
||||
i2 != boxes.end(); i2++)
|
||||
{
|
||||
f.selection_box.wall_side.MinEdge,
|
||||
f.selection_box.wall_side.MaxEdge
|
||||
};
|
||||
|
||||
for(s32 i=0; i<2; i++)
|
||||
{
|
||||
if(dir == v3s16(-1,0,0))
|
||||
vertices[i].rotateXZBy(0);
|
||||
if(dir == v3s16(1,0,0))
|
||||
vertices[i].rotateXZBy(180);
|
||||
if(dir == v3s16(0,0,-1))
|
||||
vertices[i].rotateXZBy(90);
|
||||
if(dir == v3s16(0,0,1))
|
||||
vertices[i].rotateXZBy(-90);
|
||||
}
|
||||
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
}
|
||||
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
aabb3f box = *i2;
|
||||
box.MinEdge += npf + v3f(-d,-d,-d);
|
||||
box.MaxEdge += npf + v3f(d,d,d);
|
||||
hilightboxes.push_back(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // NODEBOX_REGULAR
|
||||
{
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
v3f centerpoint = npf + dir_f * BS/2;
|
||||
f32 distance =
|
||||
(centerpoint - camera_position).getLength();
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np + dirs[i];
|
||||
mindistance = distance;
|
||||
|
||||
//hilightbox = facebox;
|
||||
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(np, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
hilightbox = nodebox;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
} // if distance < mindistance
|
||||
} // for dirs
|
||||
} // regular block
|
||||
} // for coords
|
||||
|
||||
return result;
|
||||
@@ -1236,6 +1116,16 @@ void the_game(
|
||||
*/
|
||||
Inventory local_inventory(itemdef);
|
||||
|
||||
/*
|
||||
Find out size of crack animation
|
||||
*/
|
||||
int crack_animation_length = 5;
|
||||
{
|
||||
video::ITexture *t = tsrc->getTextureRaw("crack_anylength.png");
|
||||
v2u32 size = t->getOriginalSize();
|
||||
crack_animation_length = size.Y / size.X;
|
||||
}
|
||||
|
||||
/*
|
||||
Add some gui stuff
|
||||
*/
|
||||
@@ -1515,7 +1405,7 @@ void the_game(
|
||||
hotbar_imagesize = 64;
|
||||
|
||||
// Hilight boxes collected during the loop and displayed
|
||||
core::list< core::aabbox3d<f32> > hilightboxes;
|
||||
std::vector<aabb3f> hilightboxes;
|
||||
|
||||
// Info text
|
||||
std::wstring infotext;
|
||||
@@ -1597,14 +1487,10 @@ void the_game(
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setCurrentPlayer();
|
||||
|
||||
menu->setFormSpec(
|
||||
"invsize[8,7.5;]"
|
||||
//"image[1,0.6;1,2;player.png]"
|
||||
"list[current_player;main;0,3.5;8,4;]"
|
||||
"list[current_player;craft;3,0;3,3;]"
|
||||
"list[current_player;craftpreview;7,1;1,1;]"
|
||||
, inventoryloc);
|
||||
|
||||
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
|
||||
assert(src);
|
||||
menu->setFormSpec(src->getForm(), inventoryloc);
|
||||
menu->setFormSource(new PlayerInventoryFormSource(&client));
|
||||
menu->drop();
|
||||
}
|
||||
else if(input->wasKeyDown(EscapeKey))
|
||||
@@ -2128,8 +2014,6 @@ void the_game(
|
||||
core::line3d<f32> shootline(camera_position,
|
||||
camera_position + camera_direction * BS * (d+1));
|
||||
|
||||
core::aabbox3d<f32> hilightbox;
|
||||
bool should_show_hilightbox = false;
|
||||
ClientActiveObject *selected_object = NULL;
|
||||
|
||||
PointedThing pointed = getPointedThing(
|
||||
@@ -2138,7 +2022,7 @@ void the_game(
|
||||
camera_position, shootline, d,
|
||||
playeritem_liquids_pointable, !ldown_for_dig,
|
||||
// output
|
||||
hilightbox, should_show_hilightbox,
|
||||
hilightboxes,
|
||||
selected_object);
|
||||
|
||||
if(pointed != pointed_old)
|
||||
@@ -2147,12 +2031,6 @@ void the_game(
|
||||
//dstream<<"Pointing at "<<pointed.dump()<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Visualize selection
|
||||
*/
|
||||
if(should_show_hilightbox)
|
||||
hilightboxes.push_back(hilightbox);
|
||||
|
||||
/*
|
||||
Stop digging when
|
||||
- releasing left mouse button
|
||||
@@ -2217,7 +2095,7 @@ void the_game(
|
||||
infotext = narrow_to_wide(meta->getString("infotext"));
|
||||
} else {
|
||||
MapNode n = map.getNode(nodepos);
|
||||
if(nodedef->get(n).tname_tiles[0] == "unknown_block.png"){
|
||||
if(nodedef->get(n).tiledef[0].name == "unknown_block.png"){
|
||||
infotext = L"Unknown node: ";
|
||||
infotext += narrow_to_wide(nodedef->get(n).name);
|
||||
}
|
||||
@@ -2242,7 +2120,9 @@ void the_game(
|
||||
ldown_for_dig = true;
|
||||
}
|
||||
MapNode n = client.getEnv().getClientMap().getNode(nodepos);
|
||||
|
||||
|
||||
// NOTE: Similar piece of code exists on the server side for
|
||||
// cheat detection.
|
||||
// Get digging parameters
|
||||
DigParams params = getDigParams(nodedef->get(n).groups,
|
||||
&playeritem_toolcap);
|
||||
@@ -2282,20 +2162,20 @@ void the_game(
|
||||
|
||||
if(dig_time_complete >= 0.001)
|
||||
{
|
||||
dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
|
||||
dig_index = (u16)((float)crack_animation_length
|
||||
* dig_time/dig_time_complete);
|
||||
}
|
||||
// This is for torches
|
||||
else
|
||||
{
|
||||
dig_index = CRACK_ANIMATION_LENGTH;
|
||||
dig_index = crack_animation_length;
|
||||
}
|
||||
|
||||
|
||||
// Don't show cracks if not diggable
|
||||
if(dig_time_complete >= 100000.0)
|
||||
{
|
||||
}
|
||||
else if(dig_index < CRACK_ANIMATION_LENGTH)
|
||||
else if(dig_index < crack_animation_length)
|
||||
{
|
||||
//TimeTaker timer("client.setTempMod");
|
||||
//infostream<<"dig_index="<<dig_index<<std::endl;
|
||||
@@ -2313,7 +2193,7 @@ void the_game(
|
||||
digging = false;
|
||||
|
||||
nodig_delay_timer = dig_time_complete
|
||||
/ (float)CRACK_ANIMATION_LENGTH;
|
||||
/ (float)crack_animation_length;
|
||||
|
||||
// We don't want a corresponding delay to
|
||||
// very time consuming nodes
|
||||
@@ -2377,8 +2257,41 @@ void the_game(
|
||||
// Otherwise report right click to server
|
||||
else
|
||||
{
|
||||
// Report to server
|
||||
client.interact(3, pointed);
|
||||
camera.setDigging(1); // right click animation
|
||||
|
||||
// If the wielded item has node placement prediction,
|
||||
// make that happen
|
||||
const ItemDefinition &def =
|
||||
playeritem.getDefinition(itemdef);
|
||||
if(def.node_placement_prediction != "")
|
||||
do{ // breakable
|
||||
verbosestream<<"Node placement prediction for "
|
||||
<<playeritem.name<<" is "
|
||||
<<def.node_placement_prediction<<std::endl;
|
||||
v3s16 p = neighbourpos;
|
||||
content_t id;
|
||||
bool found =
|
||||
nodedef->getId(def.node_placement_prediction, id);
|
||||
if(!found){
|
||||
errorstream<<"Node placement prediction failed for "
|
||||
<<playeritem.name<<" (places "
|
||||
<<def.node_placement_prediction
|
||||
<<") - Name not known"<<std::endl;
|
||||
break;
|
||||
}
|
||||
MapNode n(id);
|
||||
try{
|
||||
// This triggers the required mesh update too
|
||||
client.addNode(p, n);
|
||||
}catch(InvalidPositionException &e){
|
||||
errorstream<<"Node placement prediction failed for "
|
||||
<<playeritem.name<<" (places "
|
||||
<<def.node_placement_prediction
|
||||
<<") - Position not loaded"<<std::endl;
|
||||
}
|
||||
}while(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2786,9 +2699,10 @@ void the_game(
|
||||
|
||||
if(show_hud)
|
||||
{
|
||||
for(core::list<aabb3f>::Iterator i=hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
/*infostream<<"hilightbox min="
|
||||
<<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
|
||||
<<" max="
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GAME_HEADER
|
||||
#define GAME_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <string>
|
||||
#include "keycode.h"
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "genericobject.h"
|
||||
#include "utility.h"
|
||||
#include <sstream>
|
||||
#include "util/serialize.h"
|
||||
|
||||
std::string gob_cmd_set_properties(const ObjectProperties &prop)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define GENERICOBJECT_HEADER
|
||||
|
||||
#include <string>
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <iostream>
|
||||
|
||||
#define GENERIC_CMD_SET_PROPERTIES 0
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GETTIME_HEADER
|
||||
#define GETTIME_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
/*
|
||||
Get a millisecond counter value.
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUICHATCONSOLE_HEADER
|
||||
#define GUICHATCONSOLE_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "chat.h"
|
||||
|
||||
class Client;
|
||||
|
||||
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUICONFIRMMENU_HEADER
|
||||
#define GUICONFIRMMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
struct ConfirmDest
|
||||
|
||||
@@ -27,8 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include <IGUIListBox.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#include "util/string.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUICREATEWORLD_HEADER
|
||||
#define GUICREATEWORLD_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
#include "subgame.h"
|
||||
|
||||
|
||||
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUIMESSAGEMENU_HEADER
|
||||
#define GUIMESSAGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
class IRespawnInitiator
|
||||
|
||||
@@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IGUIFont.h>
|
||||
#include "log.h"
|
||||
#include "tile.h" // ITextureSource
|
||||
#include "util/string.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
void drawItemStack(video::IVideoDriver *driver,
|
||||
gui::IGUIFont *font,
|
||||
|
||||
@@ -21,10 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUIINVENTORYMENU_HEADER
|
||||
#define GUIINVENTORYMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "inventory.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "utility.h"
|
||||
#include "modalMenu.h"
|
||||
|
||||
class IGameDef;
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
#ifndef GUIKEYCHANGEMENU_HEADER
|
||||
#define GUIKEYCHANGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "utility.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "client.h"
|
||||
#include "gettext.h"
|
||||
|
||||
@@ -36,9 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// For IGameCallback
|
||||
#include "guiPauseMenu.h"
|
||||
#include "gettext.h"
|
||||
#include "utility.h"
|
||||
#include "tile.h" // getTexturePath
|
||||
#include "filesys.h"
|
||||
#include "util/string.h"
|
||||
|
||||
struct CreateWorldDestMainMenu : public CreateWorldDest
|
||||
{
|
||||
@@ -586,14 +586,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 620, 250);
|
||||
rect += m_topleft_client + v2s32(130+14, 50+35);
|
||||
core::rect<s32> rect(0, 0, 454, 250);
|
||||
rect += m_topleft_client + v2s32(110, 50+35);
|
||||
Environment->addStaticText(narrow_to_wide(
|
||||
"Minetest-c55 " VERSION_STRING "\n"
|
||||
"http://minetest.net/\n"
|
||||
"\n"
|
||||
"by Perttu Ahola <celeron55@gmail.com>\n"
|
||||
"and contributors"
|
||||
"and contributors: tango_, kahrl (kaaaaaahrl?), erlehmann (the hippie), SpeedProg, JacobF (sqlite worlds), teddydestodes, marktraceur, darkrose, Jonathan Neuschäfer (who the hell?), Felix Krausse (broke liquids, IIRC), sfan5... and >10 more random people."
|
||||
).c_str(), rect, false, true, this, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUIMAINMENU_HEADER
|
||||
#define GUIMAINMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUIMESSAGEMENU_HEADER
|
||||
#define GUIMESSAGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
class GUIMessageMenu : public GUIModalMenu
|
||||
|
||||
@@ -19,9 +19,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#ifndef GUIPASSWORDCHANGE_HEADER
|
||||
#define GUIPASSWORDCHANGE_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include "client.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#include "util/string.h"
|
||||
|
||||
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUIPAUSEMENU_HEADER
|
||||
#define GUIPAUSEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
|
||||
class IGameCallback
|
||||
|
||||
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef GUITEXTINPUTMENU_HEADER
|
||||
#define GUITEXTINPUTMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
struct TextDest
|
||||
|
||||
@@ -19,7 +19,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "inventory.h"
|
||||
#include "serialization.h"
|
||||
#include "utility.h"
|
||||
#include "debug.h"
|
||||
#include <sstream>
|
||||
#include "log.h"
|
||||
@@ -27,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "strfnd.h"
|
||||
#include "content_mapnode.h" // For loading legacy MaterialItems
|
||||
#include "nameidmapping.h" // For loading legacy MaterialItems
|
||||
#include "util/serialize.h"
|
||||
#include "util/string.h"
|
||||
|
||||
/*
|
||||
ItemStack
|
||||
|
||||
@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "debug.h"
|
||||
#include "itemdef.h"
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serverobject.h"
|
||||
#include "main.h" // for g_settings
|
||||
#include "settings.h"
|
||||
#include "utility.h"
|
||||
#include "craftdef.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
30
src/irr_aabb3d.h
Normal file
30
src/irr_aabb3d.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <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 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef IRR_AABB3D_HEADER
|
||||
#define IRR_AABB3D_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
#include <aabbox3d.h>
|
||||
|
||||
typedef core::aabbox3d<f32> aabb3f;
|
||||
|
||||
#endif
|
||||
|
||||
34
src/irr_v2d.h
Normal file
34
src/irr_v2d.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <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 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef IRR_V2D_HEADER
|
||||
#define IRR_V2D_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
#include <vector2d.h>
|
||||
|
||||
typedef core::vector2d<f32> v2f;
|
||||
typedef core::vector2d<s16> v2s16;
|
||||
typedef core::vector2d<s32> v2s32;
|
||||
typedef core::vector2d<u32> v2u32;
|
||||
typedef core::vector2d<f32> v2f32;
|
||||
|
||||
#endif
|
||||
|
||||
32
src/irr_v3d.h
Normal file
32
src/irr_v3d.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <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 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef IRR_V3D_HEADER
|
||||
#define IRR_V3D_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
#include <vector3d.h>
|
||||
|
||||
typedef core::vector3df v3f;
|
||||
typedef core::vector3d<s16> v3s16;
|
||||
typedef core::vector3d<s32> v3s32;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <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
|
||||
@@ -21,25 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define IRRLICHTTYPES_HEADER
|
||||
|
||||
#include <irrTypes.h>
|
||||
#include <vector2d.h>
|
||||
#include <vector3d.h>
|
||||
#include <irrMap.h>
|
||||
#include <irrList.h>
|
||||
#include <irrArray.h>
|
||||
#include <aabbox3d.h>
|
||||
#include <SColor.h>
|
||||
|
||||
using namespace irr;
|
||||
typedef core::vector3df v3f;
|
||||
typedef core::vector3d<s16> v3s16;
|
||||
typedef core::vector3d<s32> v3s32;
|
||||
|
||||
typedef core::vector2d<f32> v2f;
|
||||
typedef core::vector2d<s16> v2s16;
|
||||
typedef core::vector2d<s32> v2s32;
|
||||
typedef core::vector2d<u32> v2u32;
|
||||
typedef core::vector2d<f32> v2f32;
|
||||
|
||||
typedef core::aabbox3d<f32> aabb3f;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
|
||||
35
src/irrlichttypes_bloated.h
Normal file
35
src/irrlichttypes_bloated.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <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 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef IRRLICHTTYPES_BLOATED_HEADER
|
||||
#define IRRLICHTTYPES_BLOATED_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
#include "irr_v2d.h"
|
||||
#include "irr_v3d.h"
|
||||
#include "irr_aabb3d.h"
|
||||
|
||||
#include <irrMap.h>
|
||||
#include <irrList.h>
|
||||
#include <irrArray.h>
|
||||
#include <SColor.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,13 +17,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_IRRLICHT_HEADER
|
||||
#define COMMON_IRRLICHT_HEADER
|
||||
#ifndef IRRLICHTTYPES_EXTRABLOATED_HEADER
|
||||
#define IRRLICHTTYPES_EXTRABLOATED_HEADER
|
||||
|
||||
#define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\
|
||||
video::SColor(255,30,30,30));d->endScene();}
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
|
||||
#ifndef SERVER
|
||||
#include <IMesh.h>
|
||||
@@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "log.h"
|
||||
#include "utility.h"
|
||||
#include "util/serialize.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
@@ -70,6 +70,7 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
||||
*def.tool_capabilities);
|
||||
}
|
||||
groups = def.groups;
|
||||
node_placement_prediction = def.node_placement_prediction;
|
||||
#ifndef SERVER
|
||||
inventory_texture = def.inventory_texture;
|
||||
if(def.wield_mesh)
|
||||
@@ -115,6 +116,8 @@ void ItemDefinition::reset()
|
||||
}
|
||||
groups.clear();
|
||||
|
||||
node_placement_prediction = "";
|
||||
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
if(wield_mesh)
|
||||
@@ -150,6 +153,7 @@ void ItemDefinition::serialize(std::ostream &os) const
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
os<<serializeString(node_placement_prediction);
|
||||
}
|
||||
|
||||
void ItemDefinition::deSerialize(std::istream &is)
|
||||
@@ -184,6 +188,11 @@ void ItemDefinition::deSerialize(std::istream &is)
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
// If you add anything here, insert it primarily inside the try-catch
|
||||
// block to not need to increase the version.
|
||||
try{
|
||||
node_placement_prediction = deSerializeString(is);
|
||||
}catch(SerializationError &e) {};
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -442,7 +451,7 @@ class CItemDefManager: public IWritableItemDefManager
|
||||
if(def->inventory_texture == NULL)
|
||||
{
|
||||
def->inventory_texture =
|
||||
tsrc->getTextureRaw(f.tname_tiles[0]);
|
||||
tsrc->getTextureRaw(f.tiledef[0].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef ITEMDEF_HEADER
|
||||
#define ITEMDEF_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
@@ -67,6 +67,11 @@ struct ItemDefinition
|
||||
ToolCapabilities *tool_capabilities;
|
||||
ItemGroupList groups;
|
||||
|
||||
// Client shall immediately place this node when player places the item.
|
||||
// Server will update the precise end result a moment later.
|
||||
// "" = no prediction
|
||||
std::string node_placement_prediction;
|
||||
|
||||
/*
|
||||
Cached stuff
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef ITEMGROUP_HEADER
|
||||
#define ITEMGROUP_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -258,9 +258,10 @@ KeyPress::KeyPress(const char *name)
|
||||
try {
|
||||
Key = keyname_to_keycode(name);
|
||||
m_name = name;
|
||||
if (strlen(name) > 8)
|
||||
mbtowc(&Char, name + 8, 1);
|
||||
else
|
||||
if (strlen(name) > 8) {
|
||||
int chars_read = mbtowc(&Char, name + 8, 1);
|
||||
assert (chars_read == 1 && "unexpected multibyte character");
|
||||
} else
|
||||
Char = L'\0';
|
||||
return;
|
||||
} catch (UnknownKeycode &e) {};
|
||||
@@ -270,7 +271,8 @@ KeyPress::KeyPress(const char *name)
|
||||
m_name += name;
|
||||
try {
|
||||
Key = keyname_to_keycode(m_name.c_str());
|
||||
mbtowc(&Char, name, 1);
|
||||
int chars_read = mbtowc(&Char, name, 1);
|
||||
assert (chars_read == 1 && "unexpected multibyte character");
|
||||
return;
|
||||
} catch (UnknownKeycode &e) {};
|
||||
}
|
||||
@@ -279,7 +281,8 @@ KeyPress::KeyPress(const char *name)
|
||||
|
||||
Key = irr::KEY_KEY_CODES_COUNT;
|
||||
|
||||
mbtowc(&Char, name, 1);
|
||||
int mbtowc_ret = mbtowc(&Char, name, 1);
|
||||
assert (mbtowc_ret == 1 && "unexpected multibyte character");
|
||||
m_name = name[0];
|
||||
}
|
||||
|
||||
@@ -290,9 +293,9 @@ KeyPress::KeyPress(const irr::SEvent::SKeyInput &in)
|
||||
if (valid_kcode(Key)) {
|
||||
m_name = KeyNames[Key];
|
||||
} else {
|
||||
size_t maxlen = wctomb(NULL, Char);
|
||||
m_name.resize(maxlen+1, '\0');
|
||||
wctomb(&m_name[0], Char);
|
||||
m_name.resize(MB_CUR_MAX+1, '\0');
|
||||
int written = wctomb(&m_name[0], Char);
|
||||
assert (written >= 0 && "unexpected multibyte character");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef KEYCODE_HEADER
|
||||
#define KEYCODE_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <IEventReceiver.h>
|
||||
#include <string>
|
||||
|
||||
/* A key press, consisting of either an Irrlicht keycode
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef LIGHT_HEADER
|
||||
#define LIGHT_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "debug.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "localplayer.h"
|
||||
|
||||
#include "main.h" // For g_settings
|
||||
#include "event.h"
|
||||
#include "collision.h"
|
||||
@@ -25,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "settings.h"
|
||||
#include "map.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
/*
|
||||
LocalPlayer
|
||||
@@ -33,7 +35,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
||||
Player(gamedef),
|
||||
m_sneak_node(32767,32767,32767),
|
||||
m_sneak_node_exists(false)
|
||||
m_sneak_node_exists(false),
|
||||
m_old_node_below(32767,32767,32767),
|
||||
m_old_node_below_type("air"),
|
||||
m_need_to_get_new_sneak_node(true)
|
||||
{
|
||||
// Initialize hp to 0, so that no hearts will be shown if server
|
||||
// doesn't support health points
|
||||
@@ -50,24 +55,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
v3f position = getPosition();
|
||||
v3f oldpos = position;
|
||||
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
||||
|
||||
v3f old_speed = m_speed;
|
||||
|
||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
*/
|
||||
position += m_speed * dtime;
|
||||
|
||||
// Skip collision detection if a special movement mode is used
|
||||
bool fly_allowed = m_gamedef->checkLocalPrivilege("fly");
|
||||
bool free_move = fly_allowed && g_settings->getBool("free_move");
|
||||
if(free_move)
|
||||
{
|
||||
position += m_speed * dtime;
|
||||
setPosition(position);
|
||||
return;
|
||||
}
|
||||
@@ -76,9 +72,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
// Player position in nodes
|
||||
v3s16 pos_i = floatToInt(position, BS);
|
||||
|
||||
/*
|
||||
Check if player is in water (the oscillating value)
|
||||
*/
|
||||
@@ -145,13 +138,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
// Maximum distance over border for sneaking
|
||||
f32 sneak_max = BS*0.4;
|
||||
|
||||
/*
|
||||
If sneaking, player has larger collision radius to keep from
|
||||
falling
|
||||
*/
|
||||
/*if(control.sneak)
|
||||
player_radius = sneak_max + d*1.1;*/
|
||||
|
||||
/*
|
||||
If sneaking, keep in range from the last walked node and don't
|
||||
fall off from it
|
||||
@@ -168,22 +154,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
{
|
||||
position.Y = min_y;
|
||||
|
||||
//v3f old_speed = m_speed;
|
||||
|
||||
if(m_speed.Y < 0)
|
||||
m_speed.Y = 0;
|
||||
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
info.speed = m_speed.Y - old_speed.Y;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,22 +163,22 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Calculate player collision box (new and old)
|
||||
*/
|
||||
core::aabbox3d<f32> playerbox(
|
||||
position.X - player_radius,
|
||||
position.Y - 0.0,
|
||||
position.Z - player_radius,
|
||||
position.X + player_radius,
|
||||
position.Y + player_height,
|
||||
position.Z + player_radius
|
||||
);
|
||||
core::aabbox3d<f32> playerbox_old(
|
||||
oldpos.X - player_radius,
|
||||
oldpos.Y - 0.0,
|
||||
oldpos.Z - player_radius,
|
||||
oldpos.X + player_radius,
|
||||
oldpos.Y + player_height,
|
||||
oldpos.Z + player_radius
|
||||
-player_radius,
|
||||
0.0,
|
||||
-player_radius,
|
||||
player_radius,
|
||||
player_height,
|
||||
player_radius
|
||||
);
|
||||
|
||||
float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2);
|
||||
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
|
||||
pos_max_d, playerbox, player_stepheight, dtime,
|
||||
position, m_speed, accel_f);
|
||||
|
||||
/*
|
||||
If the player's feet touch the topside of any node, this is
|
||||
set to true.
|
||||
@@ -214,159 +186,32 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Player is allowed to jump when this is true.
|
||||
*/
|
||||
bool touching_ground_was = touching_ground;
|
||||
touching_ground = false;
|
||||
|
||||
/*std::cout<<"Checking collisions for ("
|
||||
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
|
||||
<<") -> ("
|
||||
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
|
||||
<<"):"<<std::endl;*/
|
||||
|
||||
bool standing_on_unloaded = false;
|
||||
|
||||
/*
|
||||
Go through every node around the player
|
||||
*/
|
||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
bool is_unloaded = false;
|
||||
try{
|
||||
// Player collides into walkable nodes
|
||||
if(nodemgr->get(map.getNode(v3s16(x,y,z))).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
is_unloaded = true;
|
||||
// Doing nothing here will block the player from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
/*
|
||||
See if the player is touching ground.
|
||||
|
||||
Player touches ground if player's minimum Y is near node's
|
||||
maximum Y and player's X-Z-area overlaps with the node's
|
||||
X-Z-area.
|
||||
|
||||
Use 0.15*BS so that it is easier to get on a node.
|
||||
*/
|
||||
if(
|
||||
//fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < d
|
||||
fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < 0.15*BS
|
||||
&& nodebox.MaxEdge.X-d > playerbox.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < playerbox.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > playerbox.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z
|
||||
){
|
||||
touching_ground = true;
|
||||
if(is_unloaded)
|
||||
standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
// If player doesn't intersect with node, ignore node.
|
||||
if(playerbox.intersectsWithBox(nodebox) == false)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Go through every axis
|
||||
*/
|
||||
v3f dirs[3] = {
|
||||
v3f(0,0,1), // back-front
|
||||
v3f(0,1,0), // top-bottom
|
||||
v3f(1,0,0), // right-left
|
||||
};
|
||||
for(u16 i=0; i<3; i++)
|
||||
{
|
||||
/*
|
||||
Calculate values along the axis
|
||||
*/
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax = playerbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin = playerbox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax_old = playerbox_old.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin_old = playerbox_old.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
/*
|
||||
Check collision for the axis.
|
||||
Collision happens when player is going through a surface.
|
||||
*/
|
||||
/*f32 neg_d = d;
|
||||
f32 pos_d = d;
|
||||
// Make it easier to get on top of a node
|
||||
if(i == 1)
|
||||
neg_d = 0.15*BS;
|
||||
bool negative_axis_collides =
|
||||
(nodemax > playermin && nodemax <= playermin_old + neg_d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < playermax && nodemin >= playermax_old - pos_d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0);*/
|
||||
bool negative_axis_collides =
|
||||
(nodemax > playermin && nodemax <= playermin_old + d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < playermax && nodemin >= playermax_old - d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0);
|
||||
bool main_axis_collides =
|
||||
negative_axis_collides || positive_axis_collides;
|
||||
|
||||
/*
|
||||
Check overlap of player and node in other axes
|
||||
*/
|
||||
bool other_axes_overlap = true;
|
||||
for(u16 j=0; j<3; j++)
|
||||
{
|
||||
if(j == i)
|
||||
continue;
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||
f32 playermax = playerbox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 playermin = playerbox.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > playermin && nodemin + d < playermax))
|
||||
{
|
||||
other_axes_overlap = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If this is a collision, revert the position in the main
|
||||
direction.
|
||||
*/
|
||||
if(other_axes_overlap && main_axis_collides)
|
||||
{
|
||||
//v3f old_speed = m_speed;
|
||||
|
||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
info.speed = m_speed.Y - old_speed.Y;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
} // xyz
|
||||
touching_ground = result.touching_ground;
|
||||
|
||||
bool standing_on_unloaded = result.standing_on_unloaded;
|
||||
|
||||
/*
|
||||
Check the nodes under the player to see from which node the
|
||||
player is sneaking from, if any.
|
||||
player is sneaking from, if any. If the node from under
|
||||
the player has been removed, the player falls.
|
||||
*/
|
||||
v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||
if(m_sneak_node_exists &&
|
||||
nodemgr->get(map.getNodeNoEx(m_old_node_below)).name == "air" &&
|
||||
m_old_node_below_type != "air")
|
||||
{
|
||||
// Old node appears to have been removed; that is,
|
||||
// it wasn't air before but now it is
|
||||
m_need_to_get_new_sneak_node = false;
|
||||
m_sneak_node_exists = false;
|
||||
}
|
||||
else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air")
|
||||
{
|
||||
// We are on something, so make sure to recalculate the sneak
|
||||
// node.
|
||||
m_need_to_get_new_sneak_node = true;
|
||||
}
|
||||
if(m_need_to_get_new_sneak_node)
|
||||
{
|
||||
v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||
v2f player_p2df(position.X, position.Z);
|
||||
@@ -416,17 +261,9 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
}
|
||||
|
||||
bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9);
|
||||
|
||||
if(control.sneak && m_sneak_node_exists)
|
||||
{
|
||||
if(sneak_node_found)
|
||||
m_sneak_node = new_sneak_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sneak_node = new_sneak_node;
|
||||
m_sneak_node_exists = sneak_node_found;
|
||||
}
|
||||
|
||||
m_sneak_node = new_sneak_node;
|
||||
m_sneak_node_exists = sneak_node_found;
|
||||
|
||||
/*
|
||||
If sneaking, the player's collision box can be in air, so
|
||||
@@ -471,6 +308,12 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Update the node last under the player
|
||||
*/
|
||||
m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||
m_old_node_below_type = nodemgr->get(map.getNodeNoEx(m_old_node_below)).name;
|
||||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
|
||||
@@ -95,6 +95,12 @@ class LocalPlayer : public Player
|
||||
v3s16 m_sneak_node;
|
||||
// Whether the player is allowed to sneak
|
||||
bool m_sneak_node_exists;
|
||||
// Node below player, used to determine whether it has been removed,
|
||||
// and its old type
|
||||
v3s16 m_old_node_below;
|
||||
std::string m_old_node_below_type;
|
||||
// Whether recalculation of the sneak node is needed
|
||||
bool m_need_to_get_new_sneak_node;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <locale.h>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "debug.h"
|
||||
#include "test.h"
|
||||
#include "server.h"
|
||||
@@ -68,7 +68,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
#include "mods.h"
|
||||
#include "utility_string.h"
|
||||
#include "util/string.h"
|
||||
#include "subgame.h"
|
||||
#include "quicktune.h"
|
||||
|
||||
@@ -877,6 +877,7 @@ int main(int argc, char *argv[])
|
||||
init_gettext((porting::path_share+DIR_DELIM+".."+DIR_DELIM+"locale").c_str());
|
||||
|
||||
// Initialize debug streams
|
||||
#define DEBUGFILE "debug.txt"
|
||||
#ifdef RUN_IN_PLACE
|
||||
std::string logfile = DEBUGFILE;
|
||||
#else
|
||||
|
||||
@@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapblock.h"
|
||||
#include "main.h"
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "voxel.h"
|
||||
#include "porting.h"
|
||||
#include "mapgen.h"
|
||||
@@ -32,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "profiler.h"
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "mapnode.h"
|
||||
#include "constants.h"
|
||||
#include "voxel.h"
|
||||
#include "utility.h" // Needed for UniqueQueue, a member of Map
|
||||
#include "modifiedstate.h"
|
||||
#include "util/container.h"
|
||||
|
||||
extern "C" {
|
||||
#include "sqlite3.h"
|
||||
|
||||
@@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef SERVER
|
||||
#include "mapblock_mesh.h"
|
||||
#endif
|
||||
#include "util/string.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -409,7 +410,7 @@ void MapBlock::actuallyUpdateDayNightDiff()
|
||||
|
||||
void MapBlock::expireDayNightDiff()
|
||||
{
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
//INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
if(data == NULL){
|
||||
m_day_night_differs = false;
|
||||
@@ -616,9 +617,13 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
*/
|
||||
if(disk)
|
||||
{
|
||||
// Node timers
|
||||
if(version >= 23)
|
||||
m_node_timers.serialize(os);
|
||||
// Version 23 doesn't actually contain node timers
|
||||
// (this field should have not been added)
|
||||
if(version == 23)
|
||||
writeU8(os, 0);
|
||||
// Node timers (uncomment when node timers are taken into use)
|
||||
/*if(version >= 24)
|
||||
m_node_timers.serialize(os);*/
|
||||
|
||||
// Static objects
|
||||
m_static_objects.serialize(os);
|
||||
@@ -698,11 +703,15 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
|
||||
if(disk)
|
||||
{
|
||||
// Node timers
|
||||
if(version >= 23){
|
||||
if(version == 23)
|
||||
// Read unused zero
|
||||
readU8(is);
|
||||
// Uncomment when node timers are taken into use
|
||||
/*else if(version >= 24){
|
||||
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
|
||||
<<": Node timers"<<std::endl);
|
||||
m_node_timers.deSerialize(is);
|
||||
}
|
||||
}*/
|
||||
|
||||
// Static objects
|
||||
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
|
||||
@@ -968,7 +977,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
|
||||
("MapBlock::deSerialize: no enough input data");
|
||||
is_underground = tmp;
|
||||
is.read((char*)*databuf_nodelist, nodecount * ser_length);
|
||||
if(is.gcount() != nodecount * ser_length)
|
||||
if((u32)is.gcount() != nodecount * ser_length)
|
||||
throw SerializationError
|
||||
("MapBlock::deSerialize: no enough input data");
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jmutexautolock.h>
|
||||
#include <exception>
|
||||
#include "debug.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "irr_v3d.h"
|
||||
#include "irr_aabb3d.h"
|
||||
#include "mapnode.h"
|
||||
#include "exceptions.h"
|
||||
#include "serialization.h"
|
||||
@@ -34,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodemetadata.h"
|
||||
#include "nodetimer.h"
|
||||
#include "modifiedstate.h"
|
||||
#include "util/numeric.h" // getContainerPos
|
||||
|
||||
class Map;
|
||||
class NodeMetadataList;
|
||||
|
||||
@@ -27,6 +27,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gamedef.h"
|
||||
#include "mesh.h"
|
||||
#include "content_mapblock.h"
|
||||
#include "noise.h"
|
||||
#include "settings.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
/*
|
||||
MeshMakeData
|
||||
@@ -559,6 +562,11 @@ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
|
||||
spec.material_flags |= MATERIAL_FLAG_CRACK;
|
||||
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
|
||||
}
|
||||
// If animated, replace tile texture with one without texture atlas
|
||||
if(spec.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||
{
|
||||
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
@@ -597,7 +605,46 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
|
||||
0, 5, 0, 2, 0, 3, 1, 4, // facedir = 3
|
||||
};
|
||||
u8 tileindex = dir_to_tile[facedir*8 + dir_i];
|
||||
return getNodeTileN(mn, p, tileindex, data);
|
||||
|
||||
// If not rotated or is side tile, we're done
|
||||
if(facedir == 0 || (tileindex != 0 && tileindex != 1))
|
||||
return getNodeTileN(mn, p, tileindex, data);
|
||||
|
||||
// This is the top or bottom tile, and it shall be rotated; thus rotate it
|
||||
TileSpec spec = getNodeTileN(mn, p, tileindex, data);
|
||||
if(tileindex == 0){
|
||||
if(facedir == 1){ // -90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR270";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
else if(facedir == 2){ // 180
|
||||
spec.texture.pos += spec.texture.size;
|
||||
spec.texture.size *= -1;
|
||||
}
|
||||
else if(facedir == 3){ // 90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR90";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
}
|
||||
else if(tileindex == 1){
|
||||
if(facedir == 1){ // -90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR90";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
else if(facedir == 2){ // 180
|
||||
spec.texture.pos += spec.texture.size;
|
||||
spec.texture.size *= -1;
|
||||
}
|
||||
else if(facedir == 3){ // 90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR270";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
static void getTileInfo(
|
||||
@@ -983,6 +1030,28 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||
crack_basename += "^[crack";
|
||||
m_crack_materials.insert(std::make_pair(i, crack_basename));
|
||||
}
|
||||
// - Texture animation
|
||||
if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||
{
|
||||
ITextureSource *tsrc = data->m_gamedef->tsrc();
|
||||
// Add to MapBlockMesh in order to animate these tiles
|
||||
m_animation_tiles[i] = p.tile;
|
||||
m_animation_frames[i] = 0;
|
||||
if(g_settings->getBool("desynchronize_mapblock_texture_animation")){
|
||||
// Get starting position from noise
|
||||
m_animation_frame_offsets[i] = 100000 * (2.0 + noise3d(
|
||||
data->m_blockpos.X, data->m_blockpos.Y,
|
||||
data->m_blockpos.Z, 0));
|
||||
} else {
|
||||
// Play all synchronized
|
||||
m_animation_frame_offsets[i] = 0;
|
||||
}
|
||||
// Replace tile texture with the first animation frame
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<tsrc->getTextureName(p.tile.texture.id);
|
||||
os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0";
|
||||
p.tile.texture = tsrc->getTexture(os.str());
|
||||
}
|
||||
// - Lighting
|
||||
for(u32 j = 0; j < p.vertices.size(); j++)
|
||||
{
|
||||
@@ -1055,7 +1124,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||
// Check if animation is required for this mesh
|
||||
m_has_animation =
|
||||
!m_crack_materials.empty() ||
|
||||
!m_daynight_diffs.empty();
|
||||
!m_daynight_diffs.empty() ||
|
||||
!m_animation_tiles.empty();
|
||||
}
|
||||
|
||||
MapBlockMesh::~MapBlockMesh()
|
||||
@@ -1094,6 +1164,34 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
|
||||
|
||||
m_last_crack = crack;
|
||||
}
|
||||
|
||||
// Texture animation
|
||||
for(std::map<u32, TileSpec>::iterator
|
||||
i = m_animation_tiles.begin();
|
||||
i != m_animation_tiles.end(); i++)
|
||||
{
|
||||
const TileSpec &tile = i->second;
|
||||
// Figure out current frame
|
||||
int frameoffset = m_animation_frame_offsets[i->first];
|
||||
int frame = (int)(time * 1000 / tile.animation_frame_length_ms
|
||||
+ frameoffset) % tile.animation_frame_count;
|
||||
// If frame doesn't change, skip
|
||||
if(frame == m_animation_frames[i->first])
|
||||
continue;
|
||||
|
||||
m_animation_frames[i->first] = frame;
|
||||
|
||||
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
|
||||
ITextureSource *tsrc = m_gamedef->getTextureSource();
|
||||
|
||||
// Create new texture name from original
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<tsrc->getTextureName(tile.texture.id);
|
||||
os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
|
||||
// Set the texture
|
||||
AtlasPointer ap = tsrc->getTexture(os.str());
|
||||
buf->getMaterial().setTexture(0, ap.atlas);
|
||||
}
|
||||
|
||||
// Day-night transition
|
||||
if(daynight_ratio != m_last_daynight_ratio)
|
||||
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef MAPBLOCK_MESH_HEADER
|
||||
#define MAPBLOCK_MESH_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "tile.h"
|
||||
#include "voxel.h"
|
||||
#include <map>
|
||||
@@ -122,6 +122,12 @@ class MapBlockMesh
|
||||
// Maps mesh buffer (i.e. material) indices to base texture names
|
||||
std::map<u32, std::string> m_crack_materials;
|
||||
|
||||
// Animation info: texture animationi
|
||||
// Maps meshbuffers to TileSpecs
|
||||
std::map<u32, TileSpec> m_animation_tiles;
|
||||
std::map<u32, int> m_animation_frames; // last animation frame
|
||||
std::map<u32, int> m_animation_frame_offsets;
|
||||
|
||||
// Animation info: day/night transitions
|
||||
// Last daynight_ratio value passed to animate()
|
||||
u32 m_last_daynight_ratio;
|
||||
|
||||
@@ -2059,13 +2059,14 @@ void make_block(BlockMakeData *data)
|
||||
|
||||
bool old_is_water = (n->getContent() == c_water_source);
|
||||
// Move mud to new place
|
||||
if(!dropped_to_unknown)
|
||||
if(!dropped_to_unknown) {
|
||||
*n2 = *n;
|
||||
// Set old place to be air (or water)
|
||||
if(old_is_water)
|
||||
*n = MapNode(c_water_source);
|
||||
else
|
||||
*n = MapNode(CONTENT_AIR);
|
||||
// Set old place to be air (or water)
|
||||
if(old_is_water)
|
||||
*n = MapNode(c_water_source);
|
||||
else
|
||||
*n = MapNode(CONTENT_AIR);
|
||||
}
|
||||
|
||||
// Done
|
||||
break;
|
||||
|
||||
@@ -20,8 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef MAPGEN_HEADER
|
||||
#define MAPGEN_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "utility.h" // UniqueQueue
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "util/container.h" // UniqueQueue
|
||||
|
||||
struct BlockMakeData;
|
||||
class MapBlock;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user