Compare commits

..

56 Commits

Author SHA1 Message Date
Perttu Ahola
e3ddbe8c6b Version 0.4.1 2012-07-21 23:14:23 +03:00
Andreas Zwinkau
d085139057 Fix signedness warning in base64.cpp 2012-07-21 22:10:29 +03:00
Andreas Zwinkau
28e7443f9b Fix wctomb use
wctomb(NULL, _) returns "nonzero if the encoding has nontrivial shift state, or zero if the encoding is stateless."

I assume the intentation was to get the size of the target buffer.
Use MB_CUR_MAX for this.
2012-07-21 22:09:17 +03:00
Andreas Zwinkau
e79ad21aeb Remove mbtowc warnings
As mbtowc(_, _, 1) reads at most one char, everything other than a
return value of 1 is an error. Since the input strings are static,
an assert protects against future changes.

Likewise, wctomb should currently never encounter a character, which
actually needs a multibyte representation.
2012-07-21 22:08:20 +03:00
Perttu Ahola
0b61253931 Actually fix facedir-rotated nodes placed using minetest.env:place_node() 2012-07-21 21:23:15 +03:00
Matthew I
a2738dec59 Fix hovering after mining a block underneath you while sneaking 2012-07-21 20:56:56 +03:00
Perttu Ahola
1788709e2d Rotate facedir-rotated top and bottom textures too, and re-implement nodebox side rotation 2012-07-21 20:23:32 +03:00
Perttu Ahola
47d30d12cb Facedir rotation of nodebox textures 2012-07-21 18:59:12 +03:00
Perttu Ahola
43df78102c Check whether node is known before reading definition in __builtin:item:on_step() 2012-07-21 16:36:14 +03:00
Bad-Command
cc10eec6c6 Fix signed overflow in getPointedThing 2012-07-21 16:13:51 +03:00
Perttu Ahola
15bf9a7026 Fix typo in scriptapi.cpp in minetest.get_craft_recipe() 2012-07-21 15:32:46 +03:00
Perttu Ahola
2795f44f03 Server-side checking of digging; disable_anticheat setting 2012-07-21 14:38:49 +03:00
Perttu Ahola
b0ba05c9ac BITCH, THIS IS 0.4.0. 2012-07-21 03:37:07 +03:00
Perttu Ahola
71c6845a94 Define M_PI on MSVC 2012-07-21 03:36:34 +03:00
Perttu Ahola
4b97023251 Add a random-ish contributor list to credit screen 2012-07-21 03:14:58 +03:00
darkrose
369046bbb4 Check for table type when reading groups from Lua 2012-07-21 02:35:45 +03:00
darkrose
38580fbee7 Add minetest.get_craft_recipe() 2012-07-21 02:33:22 +03:00
darkrose
08e1d40d6e Add support for "textures/all" (and thus texture packs) to server 2012-07-21 02:33:19 +03:00
darkrose
80f35467d8 Make lava buckets work as fuel in minimal game 2012-07-21 02:33:11 +03:00
darkrose
1b19020bf4 Remove trenches from map generator (cyisfor) (glitches: read below)
This causes glitches in very high cliffs by not making mud "flow" down from
them. Those are quite rare currently because of the lame height differences
generated.
2012-07-21 02:32:04 +03:00
Calinou
61e58ee9b7 Message cleanups (consistency) and prevent /me when not allowed to shout 2012-07-21 02:27:58 +03:00
darkrose
f21af8da9c Handle nil placer as it might occur when using minetest.env:place_node. (Uberi) 2012-07-21 02:27:46 +03:00
Perttu Ahola
dece3a3600 Remove util/old/genmap.py, because it is uselessly old 2012-07-19 21:17:31 +03:00
Perttu Ahola
16ad10e62f Allow defining player's inventory form in Lua 2012-07-19 14:09:16 +03:00
Perttu Ahola
02fb912a95 Fix /builtin/misc.lua:47: attempt to call method 'is_player' (a nil value) 2012-06-19 00:50:07 +03:00
Perttu Ahola
48790c0751 Fix random glitches in transparent animations 2012-06-18 00:21:23 +03:00
Perttu Ahola
c57e5083e8 Add pointed_thing to lua_api.txt 2012-06-17 19:47:55 +03:00
Perttu Ahola
c9a2058361 Hopefully fix includes on mingw 2012-06-17 18:05:13 +03:00
Perttu Ahola
7039dfafd6 Increment protocol version 2012-06-17 17:49:12 +03:00
Perttu Ahola
22ae83a589 Explain node boxes in lua_api.txt 2012-06-17 17:23:58 +03:00
Kahrl
1575448b1a Custom boxy nodes (stairs, slabs) and collision changes 2012-06-17 16:34:39 +03:00
Perttu Ahola
9f031a6759 Optimize headers 2012-06-17 04:03:39 +03:00
Perttu Ahola
d0ea6f9920 Properly and efficiently use split utility headers 2012-06-17 02:40:36 +03:00
Perttu Ahola
1bc37d576c Initially split utility.h to multiple files in util/ 2012-06-17 01:29:13 +03:00
Perttu Ahola
d159591b9a Mention node drawtypes in lua_api.txt 2012-06-16 23:42:04 +03:00
Perttu Ahola
57550b2b3d Fix /setpassword and /clearpassword 2012-06-16 23:35:11 +03:00
Perttu Ahola
d15d6c4e6b Fix "Node placement prediction failed for (places __default) - Name not known" 2012-06-16 22:45:35 +03:00
Perttu Ahola
6b598f61a6 Add desynchronize_mapblock_texture_animation setting and improve minetest.conf.example a bit 2012-06-16 22:37:20 +03:00
Perttu Ahola
9e21204f8b Fix build error due to DEBUGFILE 2012-06-16 21:36:54 +03:00
Perttu Ahola
e6b86fa304 Revert back proper crack texture 2012-06-16 20:48:05 +03:00
Perttu Ahola
268e50dfbd Clean up constants.h a bit 2012-06-16 18:15:06 +03:00
Perttu Ahola
07ccc15fc2 Allow node cracking animations of any length 2012-06-16 18:02:56 +03:00
Perttu Ahola
2b500d72e5 Remove tiles and special_tiles from node definition prototype because otherwise the old names can't be used 2012-06-16 18:02:26 +03:00
Perttu Ahola
cd0014b24f Update field names to non-deprecated ones in node definition prototype 2012-06-16 17:05:21 +03:00
Perttu Ahola
b3786d84c5 Use new field names and reorder fields a bit in minimal game 2012-06-16 16:47:41 +03:00
Perttu Ahola
fd1135c7af Node texture animation 2012-06-16 16:47:28 +03:00
Perttu Ahola
f0678979b1 Add comment about ItemSAO being deprecated 2012-06-11 22:10:48 +03:00
Perttu Ahola
f4a7e11bce Add some missing object properties to doc/lua_api.txt 2012-06-10 15:04:24 +03:00
Perttu Ahola
6a0388bb4b Node placement client-side prediction 2012-06-10 12:46:48 +03:00
Perttu Ahola
7ba72f2763 Remove a random old comment and a #define from game.cpp 2012-06-09 13:40:07 +03:00
Perttu Ahola
f7147d9c0a Add experimental_tester_tool_1.png to minimal game (was accidentally left out) 2012-06-08 16:46:02 +03:00
Perttu Ahola
523a5fd2e5 Move genmap.py and pnoise.py to old/ 2012-06-08 15:50:27 +03:00
Perttu Ahola
ff85e2343c Update minetestmapper.py to support the current map format (and previous ones) 2012-06-08 15:17:03 +03:00
Perttu Ahola
e74668ef7f Update and fix doc/mapformat.txt; make current format more solid in mapblock.cpp 2012-06-08 14:57:02 +03:00
Perttu Ahola
22502f80db Don't deprecate minetest.register_on_placenode and minetest.register_on_dignode 2012-06-08 01:51:23 +03:00
Perttu Ahola
4b2cc38aba Add disallow_empty_password setting 2012-06-07 02:11:28 +03:00
171 changed files with 5774 additions and 3955 deletions

View File

@@ -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()

View File

@@ -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,
})

View File

@@ -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",

View File

@@ -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})

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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

View File

@@ -90,6 +90,6 @@ bucket.register_liquid(
minetest.register_craft({
type = "fuel",
recipe = "default:bucket_lava",
recipe = "bucket:bucket_lava",
burntime = 60,
})

View File

@@ -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

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

View File

@@ -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

View File

@@ -0,0 +1 @@
default

View 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")

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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),

View File

@@ -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

View File

@@ -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 "

View File

@@ -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;

View File

@@ -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());

View File

@@ -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

View File

@@ -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"
/*

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
{

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;}
}
}
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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");

View File

@@ -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;

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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="

View File

@@ -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"

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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.

View File

@@ -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;

View File

@@ -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

View File

@@ -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
{

View File

@@ -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"

View File

@@ -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

View File

@@ -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,

View File

@@ -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;

View File

@@ -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"

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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
View 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
View 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
View 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

View File

@@ -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

View 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

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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
*/

View File

@@ -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>

View File

@@ -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");
}
}

View File

@@ -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

View File

@@ -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"
/*

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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<<")"

View File

@@ -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"

View File

@@ -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");
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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