Grabbing updates
parent
13a918d1bb
commit
5f84f82498
|
@ -133,6 +133,11 @@ endif()
|
|||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
||||
set(COMMON_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/common")
|
||||
if(EXISTS ${COMMON_SOURCE} AND IS_DIRECTORY ${COMMON_SOURCE})
|
||||
install(FILES ${COMMON_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/common/")
|
||||
install(DIRECTORY ${COMMON_SOURCE}/mods DESTINATION "${SHAREDIR}/games/common")
|
||||
endif()
|
||||
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
||||
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
||||
install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||
|
|
|
@ -81,7 +81,7 @@ Compiling on GNU/Linux:
|
|||
-----------------------
|
||||
|
||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev
|
||||
|
||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||
$ wget https://github.com/minetest/minetest/tarball/master -O master.tar.gz
|
||||
|
@ -115,6 +115,7 @@ $ ./minetest
|
|||
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
|
||||
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
|
||||
- Debug build is slower, but gives much more useful output in a debugger
|
||||
- If you build a bare server, you don't need to have Irrlicht installed. In that case use -DIRRLICHT_SOURCE_DIR=/the/irrlicht/source
|
||||
|
||||
Compiling on Windows:
|
||||
---------------------
|
||||
|
|
218
doc/lua_api.txt
218
doc/lua_api.txt
|
@ -1,4 +1,4 @@
|
|||
Minetest Lua Modding API Reference 0.4.4
|
||||
Minetest Lua Modding API Reference 0.4.5
|
||||
==========================================
|
||||
More information at http://c55.me/minetest/
|
||||
|
||||
|
@ -203,18 +203,18 @@ from the available ones of the following files:
|
|||
Examples of sound parameter tables:
|
||||
-- Play locationless on all clients
|
||||
{
|
||||
gain = 1.0, -- default
|
||||
gain = 1.0, -- default
|
||||
}
|
||||
-- Play locationless to a player
|
||||
{
|
||||
to_player = name,
|
||||
gain = 1.0, -- default
|
||||
to_player = name,
|
||||
gain = 1.0, -- default
|
||||
}
|
||||
-- Play in a location
|
||||
{
|
||||
pos = {x=1,y=2,z=3},
|
||||
gain = 1.0, -- default
|
||||
max_hear_distance = 32, -- default
|
||||
pos = {x=1,y=2,z=3},
|
||||
gain = 1.0, -- default
|
||||
max_hear_distance = 32, -- default
|
||||
}
|
||||
-- Play connected to an object, looped
|
||||
{
|
||||
|
@ -266,11 +266,11 @@ local drawtype = get_nodedef_field(nodename, "drawtype")
|
|||
Example: minetest.get_item_group(name, group) has been implemented as:
|
||||
|
||||
function minetest.get_item_group(name, group)
|
||||
if not minetest.registered_items[name] or not
|
||||
minetest.registered_items[name].groups[group] then
|
||||
return 0
|
||||
end
|
||||
return minetest.registered_items[name].groups[group]
|
||||
if not minetest.registered_items[name] or not
|
||||
minetest.registered_items[name].groups[group] then
|
||||
return 0
|
||||
end
|
||||
return minetest.registered_items[name].groups[group]
|
||||
end
|
||||
|
||||
Nodes
|
||||
|
@ -310,6 +310,10 @@ param2 is reserved for the engine when any of these are used:
|
|||
paramtype2 == "facedir"
|
||||
^ The rotation of the node is stored in param2. Furnaces and chests are
|
||||
rotated this way. Can be made by using minetest.dir_to_facedir().
|
||||
Values range 0 - 23
|
||||
facedir modulo 4 = axisdir
|
||||
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
||||
facedir's two less significant bits are rotation around the axis
|
||||
|
||||
Nodes can also contain extra data. See "Node Metadata".
|
||||
|
||||
|
@ -368,6 +372,28 @@ A box is defined as:
|
|||
A box of a regular node would look like:
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
|
||||
Ore types
|
||||
---------------
|
||||
These tell in what manner the ore is generated.
|
||||
All default ores are of the uniformly-distributed scatter type.
|
||||
|
||||
- scatter
|
||||
Randomly chooses a location and generates a cluster of ore.
|
||||
If noise_params is specified, the ore will be placed if the 3d perlin noise at
|
||||
that point is greater than the noise_threshhold, giving the ability to create a non-equal
|
||||
distribution of ore.
|
||||
- sheet
|
||||
Creates a sheet of ore in a blob shape according to the 2d perlin noise described by noise_params.
|
||||
The relative height of the sheet can be controlled by the same perlin noise as well, by specifying
|
||||
a non-zero 'scale' parameter in noise_params. IMPORTANT: The noise is not transformed by offset or
|
||||
scale when comparing against the noise threshhold, but scale is used to determine relative height.
|
||||
The height of the blob is randomly scattered, with a maximum height of clust_size.
|
||||
clust_scarcity and clust_num_ores are ignored.
|
||||
This is essentially an improved version of the so-called "stratus" ore seen in some unofficial mods.
|
||||
- claylike - NOT YET IMPLEMENTED
|
||||
Places ore if there are no more than clust_scarcity number of specified nodes within a Von Neumann
|
||||
neighborhood of clust_size radius.
|
||||
|
||||
Representations of simple things
|
||||
--------------------------------
|
||||
Position/vector:
|
||||
|
@ -468,7 +494,7 @@ An example: Make meat soup from any meat, any water and any bowl
|
|||
}
|
||||
An another example: Make red wool from white wool and red dye
|
||||
{
|
||||
type = 'shapeless',
|
||||
type = 'shapeless',
|
||||
output = 'wool:red',
|
||||
recipe = {'wool:white', 'group:dye,basecolor_red'},
|
||||
}
|
||||
|
@ -479,7 +505,7 @@ Special groups
|
|||
- level: Can be used to give an additional sense of progression in the game.
|
||||
- A larger level will cause eg. a weapon of a lower level make much less
|
||||
damage, and get weared out much faster, or not be able to get drops
|
||||
from destroyed nodes.
|
||||
from destroyed nodes.
|
||||
- 0 is something that is directly accessible at the start of gameplay
|
||||
- There is no upper limit
|
||||
- dig_immediate: (player can always pick up node without tool wear)
|
||||
|
@ -586,11 +612,11 @@ maximum level.
|
|||
Example definition of the capabilities of a tool
|
||||
-------------------------------------------------
|
||||
tool_capabilities = {
|
||||
full_punch_interval=1.5,
|
||||
max_drop_level=1,
|
||||
groupcaps={
|
||||
crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
|
||||
}
|
||||
full_punch_interval=1.5,
|
||||
max_drop_level=1,
|
||||
groupcaps={
|
||||
crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
|
||||
}
|
||||
}
|
||||
|
||||
This makes the tool be able to dig nodes that fullfill both of these:
|
||||
|
@ -750,7 +776,7 @@ field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
|
|||
^ default is the default value of the field
|
||||
^ default may contain variable references such as '${text}' which
|
||||
will fill the value from the metadata value 'text'
|
||||
^ Note: no extra text or more than a single variable is supported ATM.
|
||||
^ Note: no extra text or more than a single variable is supported ATM.
|
||||
|
||||
field[<name>;<label>;<default>]
|
||||
^ as above but without position/size units
|
||||
|
@ -840,6 +866,7 @@ minetest.register_tool(name, item definition)
|
|||
minetest.register_craftitem(name, item definition)
|
||||
minetest.register_alias(name, convert_to)
|
||||
minetest.register_craft(recipe)
|
||||
minetest.register_ore(ore definition)
|
||||
|
||||
Global callback registration functions: (Call these only at load time)
|
||||
minetest.register_globalstep(func(dtime))
|
||||
|
@ -1024,6 +1051,37 @@ minetest.get_ban_description(ip_or_name) -> ban description (string)
|
|||
minetest.ban_player(name) -> ban a player
|
||||
minetest.unban_player_or_ip(name) -> unban player or IP address
|
||||
|
||||
Particles:
|
||||
minetest.add_particle(pos, velocity, acceleration, expirationtime,
|
||||
size, collisiondetection, texture, playername)
|
||||
^ Spawn particle at pos with velocity and acceleration
|
||||
^ Disappears after expirationtime seconds
|
||||
^ collisiondetection: if true collides with physical objects
|
||||
^ Uses texture (string)
|
||||
^ Playername is optional, if specified spawns particle only on the player's client
|
||||
|
||||
minetest.add_particlespawner(amount, time,
|
||||
minpos, maxpos,
|
||||
minvel, maxvel,
|
||||
minacc, maxacc,
|
||||
minexptime, maxexptime,
|
||||
minsize, maxsize,
|
||||
collisiondetection, texture, playername)
|
||||
^ Add a particlespawner, an object that spawns an amount of particles over time seconds
|
||||
^ The particle's properties are random values in between the boundings:
|
||||
^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
|
||||
^ minsize/maxsize, minexptime/maxexptime (expirationtime)
|
||||
^ collisiondetection: if true uses collisiondetection
|
||||
^ Uses texture (string)
|
||||
^ Playername is optional, if specified spawns particle only on the player's client
|
||||
^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
|
||||
^ Returns and id
|
||||
|
||||
minetest.delete_particlespawner(id, player)
|
||||
^ Delete ParticleSpawner with id (return value from add_particlespawner)
|
||||
^ If playername is specified, only deletes on the player's client,
|
||||
^ otherwise on all clients
|
||||
|
||||
Random:
|
||||
minetest.get_connected_players() -> list of ObjectRefs
|
||||
minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer
|
||||
|
@ -1237,9 +1295,15 @@ methods:
|
|||
- set_wielded_item(item): replaces the wielded item, returns true if successful
|
||||
- set_armor_groups({group1=rating, group2=rating, ...})
|
||||
- set_animation({x=1,y=1}, frame_speed=15, frame_blend=0)
|
||||
- set_attach(parent, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
- set_attach(parent, bone, position, rotation)
|
||||
^ bone = string
|
||||
^ position = {x=num, y=num, z=num} (relative)
|
||||
^ rotation = {x=num, y=num, z=num}
|
||||
- set_detach()
|
||||
- set_bone_position("", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
- set_bone_position(bone, position, rotation)
|
||||
^ bone = string
|
||||
^ position = {x=num, y=num, z=num} (relative)
|
||||
^ rotation = {x=num, y=num, z=num}
|
||||
- set_properties(object property table)
|
||||
LuaEntitySAO-only: (no-op for other objects)
|
||||
- setvelocity({x=num, y=num, z=num})
|
||||
|
@ -1268,10 +1332,10 @@ Player-only: (no-op for other objects)
|
|||
^ Should usually be called in on_joinplayer
|
||||
- get_inventory_formspec() -> formspec string
|
||||
- get_player_control(): returns table with player pressed keys
|
||||
{jump=bool,right=bool,left=bool,LMB=bool,RMB=bool,sneak=bool,aux1=bool,down=bool,up=bool}
|
||||
{jump=bool,right=bool,left=bool,LMB=bool,RMB=bool,sneak=bool,aux1=bool,down=bool,up=bool}
|
||||
- get_player_control_bits(): returns integer with bit packed player pressed keys
|
||||
bit nr/meaning: 0/up ,1/down ,2/left ,3/right ,4/jump ,5/aux1 ,6/sneak ,7/LMB ,8/RMB
|
||||
|
||||
bit nr/meaning: 0/up ,1/down ,2/left ,3/right ,4/jump ,5/aux1 ,6/sneak ,7/LMB ,8/RMB
|
||||
|
||||
InvRef: Reference to an inventory
|
||||
methods:
|
||||
- is_empty(listname): return true if list is empty
|
||||
|
@ -1356,8 +1420,8 @@ Registered entities
|
|||
^ puncher: ObjectRef (can be nil)
|
||||
^ time_from_last_punch: Meant for disallowing spamming of clicks (can be nil)
|
||||
^ tool_capabilities: capability table of used tool (can be nil)
|
||||
^ dir: unit vector of direction of punch. Always defined. Points from
|
||||
the puncher to the punched.
|
||||
^ dir: unit vector of direction of punch. Always defined. Points from
|
||||
the puncher to the punched.
|
||||
- on_rightclick(self, clicker)
|
||||
- get_staticdata(self)
|
||||
^ Should return a string that will be passed to on_activate when
|
||||
|
@ -1478,10 +1542,10 @@ Node definition (register_node)
|
|||
drawtype = "normal", -- See "Node drawtypes"
|
||||
visual_scale = 1.0,
|
||||
tiles = {tile definition 1, def2, def3, def4, def5, def6},
|
||||
^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
|
||||
^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
|
||||
^ List can be shortened to needed length
|
||||
special_tiles = {tile definition 1, Tile definition 2},
|
||||
^ Special textures of node; used rarely (old field name: special_materials)
|
||||
^ Special textures of node; used rarely (old field name: special_materials)
|
||||
^ List can be shortened to needed length
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0}, -- If player is inside node
|
||||
|
@ -1537,7 +1601,7 @@ Node definition (register_node)
|
|||
can_dig = function(pos,player)
|
||||
^ returns true if node can be dug, or false if not
|
||||
^ default: nil
|
||||
|
||||
|
||||
on_punch = func(pos, node, puncher),
|
||||
^ default: minetest.node_punch
|
||||
^ By default: does nothing
|
||||
|
@ -1560,32 +1624,32 @@ Node definition (register_node)
|
|||
^ Called when an UI form (eg. sign text input) returns data
|
||||
^ default: nil
|
||||
|
||||
allow_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
allow_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
on_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
on_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
allow_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
on_blast = func(pos, intensity),
|
||||
^ intensity: 1.0 = mid range of regular TNT
|
||||
^ If defined, called when an explosion touches the node, instead of
|
||||
removing the node
|
||||
allow_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
on_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
on_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
|
||||
on_blast = func(pos, intensity),
|
||||
^ intensity: 1.0 = mid range of regular TNT
|
||||
^ If defined, called when an explosion touches the node, instead of
|
||||
removing the node
|
||||
}
|
||||
|
||||
Recipe for register_craft: (shaped)
|
||||
|
@ -1634,6 +1698,28 @@ Recipe for register_craft (furnace fuel)
|
|||
burntime = 1,
|
||||
}
|
||||
|
||||
Ore definition (register_ore)
|
||||
{
|
||||
ore_type = "scatter" -- See "Ore types"
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
^ Ore has a 1 out of clust_scarcity chance of spawning in a node
|
||||
^ This value should be *MUCH* higher than your intuition might tell you!
|
||||
clust_num_ores = 8,
|
||||
^ Number of ores in a cluster
|
||||
clust_size = 3,
|
||||
^ Size of the bounding box of the cluster
|
||||
^ In this example, there is a 3x3x3 cluster where 8 out of the 27 nodes are coal ore
|
||||
height_min = -31000,
|
||||
height_max = 64,
|
||||
noise_threshhold = 0.5,
|
||||
^ If noise is above this threshhold, ore is placed. Not needed for a uniform distribution
|
||||
noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70}
|
||||
^ NoiseParams structure describing the perlin noise used for ore distribution.
|
||||
^ Needed for sheet ore_type. Omit from scatter ore_type for a uniform ore distribution
|
||||
}
|
||||
|
||||
Chatcommand definition (register_chatcommand)
|
||||
{
|
||||
params = "<name> <privilege>", -- short parameter description
|
||||
|
@ -1644,24 +1730,24 @@ Chatcommand definition (register_chatcommand)
|
|||
|
||||
Detached inventory callbacks
|
||||
{
|
||||
allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
allow_put = func(inv, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_take = func(inv, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
on_put = func(inv, listname, index, stack, player),
|
||||
on_take = func(inv, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
}
|
||||
|
||||
|
|
|
@ -27,61 +27,74 @@ minetest.register_alias("mapgen_mese", "default:mese")
|
|||
-- Ore generation
|
||||
--
|
||||
|
||||
local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max, param2)
|
||||
if maxp.y < height_min or minp.y > height_max then
|
||||
return
|
||||
end
|
||||
local y_min = math.max(minp.y, height_min)
|
||||
local y_max = math.min(maxp.y, height_max)
|
||||
local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1)
|
||||
local pr = PseudoRandom(seed)
|
||||
local num_chunks = math.floor(chunks_per_volume * volume)
|
||||
local chunk_size = 3
|
||||
if ore_per_chunk <= 4 then
|
||||
chunk_size = 2
|
||||
end
|
||||
local inverse_chance = math.floor(chunk_size*chunk_size*chunk_size / ore_per_chunk)
|
||||
--print("generate_ore num_chunks: "..dump(num_chunks))
|
||||
for i=1,num_chunks do
|
||||
local y0 = pr:next(y_min, y_max-chunk_size+1)
|
||||
if y0 >= height_min and y0 <= height_max then
|
||||
local x0 = pr:next(minp.x, maxp.x-chunk_size+1)
|
||||
local z0 = pr:next(minp.z, maxp.z-chunk_size+1)
|
||||
local p0 = {x=x0, y=y0, z=z0}
|
||||
for x1=0,chunk_size-1 do
|
||||
for y1=0,chunk_size-1 do
|
||||
for z1=0,chunk_size-1 do
|
||||
if pr:next(1,inverse_chance) == 1 then
|
||||
local x2 = x0+x1
|
||||
local y2 = y0+y1
|
||||
local z2 = z0+z1
|
||||
local p2 = {x=x2, y=y2, z=z2}
|
||||
if minetest.env:get_node(p2).name == wherein then
|
||||
minetest.env:set_node(p2, {name=name, param2=param2})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--print("generate_ore done")
|
||||
end
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -31000,
|
||||
height_max = 64,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 16*16*16,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -5,
|
||||
height_max = 7,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 12*12*12,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -16,
|
||||
height_max = -5,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 9*9*9,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -31000,
|
||||
height_max = -17,
|
||||
})
|
||||
|
||||
-- for float islands and far scaled
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = 200,
|
||||
height_max = 31000,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 9*9*9,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = 200,
|
||||
height_max = 31000,
|
||||
})
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
generate_ore("default:stone_with_coal", "default:stone", minp, maxp, seed, 1/8/8/8, 5, -31000, 64 )
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+1, 1/16/16/16, 5, -5, 7 )
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+2, 1/12/12/12, 5, -16, -5 )
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+3, 1/9/9/9, 5, -31000, -17 )
|
||||
|
||||
if minetest.setting_getbool("underground_springs") then
|
||||
generate_ore("default:water_source", "default:stone", minp, maxp, seed+4, 1/24/24/24, 12, -100, -11, 128)
|
||||
generate_ore("default:water_source", "default:stone", minp, maxp, seed+5, 1/28/28/28, 8, -10000, -101, 128)
|
||||
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+6, 1/38/38/38, 6, -500, -101, 128)
|
||||
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+7, 1/30/30/30, 16, -5000, -501, 128)
|
||||
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+8, 1/24/24/24, 20, -31000, -5001, 128)
|
||||
end
|
||||
|
||||
-- Generate clay
|
||||
if maxp.y >= 2 and minp.y <= 0 then
|
||||
-- Assume X and Z lengths are equal
|
||||
|
|
|
@ -311,7 +311,7 @@
|
|||
# Mapgen stuff
|
||||
#
|
||||
|
||||
# Name of map generator to be used. Currently v6 and indev are supported.
|
||||
# Name of map generator to be used. Currently v6, indev and singlenode are supported.
|
||||
#mg_name = v6
|
||||
# Water level of map.
|
||||
#water_level = 1
|
||||
|
@ -341,8 +341,15 @@
|
|||
#mgv7_np_heat = 25, 50, (500, 500, 500), 35293, 1, 0
|
||||
#mgv7_np_humidity = 50, 31.25, (750, 750, 750), 12094, 2, 0.6
|
||||
|
||||
# Offset, scale, spread factor, seed offset, number of octaves, persistence, farscale
|
||||
#mgindev_np_terrain_base = -4, 20, (250.0, 250, 250), 82341, 5, 0.6, 10
|
||||
#mgindev_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6, 10
|
||||
#mgindev_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 10
|
||||
#mgindev_np_mud = 4, 2, (200, 200, 200), 91013, 3, 0.55, 1
|
||||
# Offset, scale, spread factor, seed offset, number of octaves, persistence, farscale, farspread
|
||||
#mgindev_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 10, 10
|
||||
#mgindev_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6, 10, 10
|
||||
#mgindev_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2, 10
|
||||
#mgindev_np_mud = 4, 2, (200, 200, 200), 91013, 3, 0.55, 1, 1
|
||||
#mgindev_np_float_islands1 = 0, 1, (64, 64, 64 ), 3683, 5, 0.5, 1, 1.5
|
||||
#mgindev_np_float_islands2 = 0, 1, (8, 8, 8 ), 9292, 2, 0.5, 1, 1.5
|
||||
#mgindev_np_float_islands3 = 0, 1, (256, 256, 256), 6412, 2, 0.5, 1, 0.5
|
||||
#mgindev_np_biome = 0, 1, (250, 250, 250), 9130, 3, 0.50, 1, 10
|
||||
|
||||
# Float islands starts from height, 0 to disable
|
||||
#mgindev_float_islands = 500
|
||||
|
|
|
@ -219,6 +219,7 @@ set(common_SRCS
|
|||
scriptapi_object.cpp
|
||||
scriptapi_nodemeta.cpp
|
||||
scriptapi_inventory.cpp
|
||||
scriptapi_particles.cpp
|
||||
scriptapi.cpp
|
||||
script.cpp
|
||||
log.cpp
|
||||
|
@ -227,6 +228,7 @@ set(common_SRCS
|
|||
mapgen.cpp
|
||||
mapgen_v6.cpp
|
||||
mapgen_indev.cpp
|
||||
mapgen_singlenode.cpp
|
||||
treegen.cpp
|
||||
dungeongen.cpp
|
||||
content_nodemeta.cpp
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
}
|
||||
|
||||
virtual u8 getType() const = 0;
|
||||
|
||||
virtual bool getCollisionBox(aabb3f *toset) = 0;
|
||||
protected:
|
||||
u16 m_id; // 0 is invalid, "no id"
|
||||
};
|
||||
|
|
|
@ -1937,6 +1937,89 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
event.show_formspec.formname = new std::string(formname);
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_SPAWN_PARTICLE)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
v3f pos = readV3F1000(is);
|
||||
v3f vel = readV3F1000(is);
|
||||
v3f acc = readV3F1000(is);
|
||||
float expirationtime = readF1000(is);
|
||||
float size = readF1000(is);
|
||||
bool collisiondetection = readU8(is);
|
||||
std::string texture = deSerializeLongString(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_SPAWN_PARTICLE;
|
||||
event.spawn_particle.pos = new v3f (pos);
|
||||
event.spawn_particle.vel = new v3f (vel);
|
||||
event.spawn_particle.acc = new v3f (acc);
|
||||
|
||||
event.spawn_particle.expirationtime = expirationtime;
|
||||
event.spawn_particle.size = size;
|
||||
event.add_particlespawner.collisiondetection =
|
||||
collisiondetection;
|
||||
event.spawn_particle.texture = new std::string(texture);
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_ADD_PARTICLESPAWNER)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u16 amount = readU16(is);
|
||||
float spawntime = readF1000(is);
|
||||
v3f minpos = readV3F1000(is);
|
||||
v3f maxpos = readV3F1000(is);
|
||||
v3f minvel = readV3F1000(is);
|
||||
v3f maxvel = readV3F1000(is);
|
||||
v3f minacc = readV3F1000(is);
|
||||
v3f maxacc = readV3F1000(is);
|
||||
float minexptime = readF1000(is);
|
||||
float maxexptime = readF1000(is);
|
||||
float minsize = readF1000(is);
|
||||
float maxsize = readF1000(is);
|
||||
bool collisiondetection = readU8(is);
|
||||
std::string texture = deSerializeLongString(is);
|
||||
u32 id = readU32(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_ADD_PARTICLESPAWNER;
|
||||
event.add_particlespawner.amount = amount;
|
||||
event.add_particlespawner.spawntime = spawntime;
|
||||
|
||||
event.add_particlespawner.minpos = new v3f (minpos);
|
||||
event.add_particlespawner.maxpos = new v3f (maxpos);
|
||||
event.add_particlespawner.minvel = new v3f (minvel);
|
||||
event.add_particlespawner.maxvel = new v3f (maxvel);
|
||||
event.add_particlespawner.minacc = new v3f (minacc);
|
||||
event.add_particlespawner.maxacc = new v3f (maxacc);
|
||||
|
||||
event.add_particlespawner.minexptime = minexptime;
|
||||
event.add_particlespawner.maxexptime = maxexptime;
|
||||
event.add_particlespawner.minsize = minsize;
|
||||
event.add_particlespawner.maxsize = maxsize;
|
||||
event.add_particlespawner.collisiondetection = collisiondetection;
|
||||
event.add_particlespawner.texture = new std::string(texture);
|
||||
event.add_particlespawner.id = id;
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_DELETE_PARTICLESPAWNER)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u32 id = readU16(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_DELETE_PARTICLESPAWNER;
|
||||
event.delete_particlespawner.id = id;
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
|
|
34
src/client.h
34
src/client.h
|
@ -157,7 +157,10 @@ enum ClientEventType
|
|||
CE_PLAYER_FORCE_MOVE,
|
||||
CE_DEATHSCREEN,
|
||||
CE_TEXTURES_UPDATED,
|
||||
CE_SHOW_FORMSPEC
|
||||
CE_SHOW_FORMSPEC,
|
||||
CE_SPAWN_PARTICLE,
|
||||
CE_ADD_PARTICLESPAWNER,
|
||||
CE_DELETE_PARTICLESPAWNER
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
|
@ -185,6 +188,35 @@ struct ClientEvent
|
|||
} show_formspec;
|
||||
struct{
|
||||
} textures_updated;
|
||||
struct{
|
||||
v3f *pos;
|
||||
v3f *vel;
|
||||
v3f *acc;
|
||||
f32 expirationtime;
|
||||
f32 size;
|
||||
bool collisiondetection;
|
||||
std::string *texture;
|
||||
} spawn_particle;
|
||||
struct{
|
||||
u16 amount;
|
||||
f32 spawntime;
|
||||
v3f *minpos;
|
||||
v3f *maxpos;
|
||||
v3f *minvel;
|
||||
v3f *maxvel;
|
||||
v3f *minacc;
|
||||
v3f *maxacc;
|
||||
f32 minexptime;
|
||||
f32 maxexptime;
|
||||
f32 minsize;
|
||||
f32 maxsize;
|
||||
bool collisiondetection;
|
||||
std::string *texture;
|
||||
u32 id;
|
||||
} add_particlespawner;
|
||||
struct{
|
||||
u32 id;
|
||||
} delete_particlespawner;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -79,9 +79,15 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
|
|||
Serialization format changes
|
||||
PROTOCOL_VERSION 16:
|
||||
TOCLIENT_SHOW_FORMSPEC
|
||||
PROTOCOL_VERSION 17:
|
||||
Serialization format change: include backface_culling flag in TileDef
|
||||
Added rightclickable field in nodedef
|
||||
TOCLIENT_SPAWN_PARTICLE
|
||||
TOCLIENT_ADD_PARTICLESPAWNER
|
||||
TOCLIENT_DELETE_PARTICLESPAWNER
|
||||
*/
|
||||
|
||||
#define LATEST_PROTOCOL_VERSION 16
|
||||
#define LATEST_PROTOCOL_VERSION 17
|
||||
|
||||
// Server's supported network protocol range
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||
|
@ -356,6 +362,7 @@ enum ToClientCommand
|
|||
u8[len] name
|
||||
[2] serialized inventory
|
||||
*/
|
||||
|
||||
TOCLIENT_SHOW_FORMSPEC = 0x44,
|
||||
/*
|
||||
[0] u16 command
|
||||
|
@ -381,6 +388,46 @@ enum ToClientCommand
|
|||
f1000 movement_liquid_sink
|
||||
f1000 movement_gravity
|
||||
*/
|
||||
|
||||
TOCLIENT_SPAWN_PARTICLE = 0x46,
|
||||
/*
|
||||
u16 command
|
||||
v3f1000 pos
|
||||
v3f1000 velocity
|
||||
v3f1000 acceleration
|
||||
f1000 expirationtime
|
||||
f1000 size
|
||||
u8 bool collisiondetection
|
||||
u32 len
|
||||
u8[len] texture
|
||||
*/
|
||||
|
||||
TOCLIENT_ADD_PARTICLESPAWNER = 0x47,
|
||||
/*
|
||||
u16 command
|
||||
u16 amount
|
||||
f1000 spawntime
|
||||
v3f1000 minpos
|
||||
v3f1000 maxpos
|
||||
v3f1000 minvel
|
||||
v3f1000 maxvel
|
||||
v3f1000 minacc
|
||||
v3f1000 maxacc
|
||||
f1000 minexptime
|
||||
f1000 maxexptime
|
||||
f1000 minsize
|
||||
f1000 maxsize
|
||||
u8 bool collisiondetection
|
||||
u32 len
|
||||
u8[len] texture
|
||||
u32 id
|
||||
*/
|
||||
|
||||
TOCLIENT_DELETE_PARTICLESPAWNER = 0x48,
|
||||
/*
|
||||
u16 command
|
||||
u32 id
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
|
|
@ -23,7 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "log.h"
|
||||
#include "environment.h"
|
||||
#include "serverobject.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "util/timetaker.h"
|
||||
#include "main.h" // g_profiler
|
||||
#include "profiler.h"
|
||||
|
@ -186,11 +189,12 @@ bool wouldCollideWithCeiling(
|
|||
}
|
||||
|
||||
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
Map *map = &env->getMap();
|
||||
//TimeTaker tt("collisionMoveSimple");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
|
||||
|
||||
|
@ -215,6 +219,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
std::vector<bool> is_object;
|
||||
std::vector<int> bouncy_values;
|
||||
std::vector<v3s16> node_positions;
|
||||
{
|
||||
|
@ -256,6 +261,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(n_bouncy_value);
|
||||
node_positions.push_back(p);
|
||||
is_object.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
@ -267,14 +273,72 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(0);
|
||||
node_positions.push_back(p);
|
||||
is_object.push_back(false);
|
||||
}
|
||||
}
|
||||
} // tt2
|
||||
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
|
||||
//TimeTaker tt3("collisionMoveSimple collect object boxes");
|
||||
|
||||
/* add object boxes to cboxes */
|
||||
|
||||
|
||||
std::list<ActiveObject*> objects;
|
||||
#ifndef SERVER
|
||||
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
||||
if (c_env != 0)
|
||||
{
|
||||
f32 distance = speed_f.getLength();
|
||||
std::vector<DistanceSortedActiveObject> clientobjects;
|
||||
c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects);
|
||||
for (int i=0; i < clientobjects.size(); i++)
|
||||
{
|
||||
objects.push_back((ActiveObject*)clientobjects[i].obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
||||
if (s_env != 0)
|
||||
{
|
||||
f32 distance = speed_f.getLength();
|
||||
std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
|
||||
for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++)
|
||||
{
|
||||
ServerActiveObject *current = s_env->getActiveObject(*iter);
|
||||
objects.push_back((ActiveObject*)current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<ActiveObject*>::const_iterator iter = objects.begin();iter != objects.end(); ++iter)
|
||||
{
|
||||
ActiveObject *object = *iter;
|
||||
|
||||
if (object != NULL)
|
||||
{
|
||||
aabb3f object_collisionbox;
|
||||
if (object->getCollisionBox(&object_collisionbox))
|
||||
{
|
||||
cboxes.push_back(object_collisionbox);
|
||||
is_unloaded.push_back(false);
|
||||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(0);
|
||||
node_positions.push_back(v3s16(0,0,0));
|
||||
is_object.push_back(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} //tt3
|
||||
|
||||
assert(cboxes.size() == is_unloaded.size());
|
||||
assert(cboxes.size() == is_step_up.size());
|
||||
assert(cboxes.size() == bouncy_values.size());
|
||||
assert(cboxes.size() == node_positions.size());
|
||||
assert(cboxes.size() == is_object.size());
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
|
@ -386,7 +450,11 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||
is_collision = false;
|
||||
|
||||
CollisionInfo info;
|
||||
info.type = COLLISION_NODE;
|
||||
if (is_object[nearest_boxindex]) {
|
||||
info.type = COLLISION_OBJECT;
|
||||
}
|
||||
else
|
||||
info.type = COLLISION_NODE;
|
||||
info.node_p = node_positions[nearest_boxindex];
|
||||
info.bouncy = bouncy;
|
||||
info.old_speed = speed_f;
|
||||
|
|
|
@ -25,10 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
class Environment;
|
||||
|
||||
enum CollisionType
|
||||
{
|
||||
COLLISION_NODE
|
||||
COLLISION_NODE,
|
||||
COLLISION_OBJECT,
|
||||
};
|
||||
|
||||
struct CollisionInfo
|
||||
|
@ -65,7 +67,7 @@ struct collisionMoveResult
|
|||
};
|
||||
|
||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
|
|
|
@ -174,6 +174,7 @@ public:
|
|||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) { return false; }
|
||||
private:
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
|
@ -329,6 +330,7 @@ public:
|
|||
std::string infoText()
|
||||
{return m_infotext;}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) { return false; }
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
|
@ -643,6 +645,22 @@ public:
|
|||
ClientActiveObject::registerType(getType(), create);
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
if (m_prop.physical) {
|
||||
aabb3f retval;
|
||||
//update collision box
|
||||
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
||||
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
||||
|
||||
toset->MinEdge += m_position;
|
||||
toset->MaxEdge += m_position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void initialize(const std::string &data)
|
||||
{
|
||||
infostream<<"GenericCAO: Got init data"<<std::endl;
|
||||
|
@ -1127,8 +1145,7 @@ public:
|
|||
v3f p_pos = m_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&env->getMap(), gamedef,
|
||||
moveresult = collisionMoveSimple(env,env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
|
|
|
@ -42,14 +42,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
// (compatible with ContentFeatures). If you specified 0,0,1,1
|
||||
// for each face, that would be the same as passing NULL.
|
||||
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||
const TileSpec *tiles, int tilecount,
|
||||
TileSpec *tiles, int tilecount,
|
||||
video::SColor &c, const f32* txc)
|
||||
{
|
||||
assert(tilecount >= 1 && tilecount <= 6);
|
||||
|
||||
v3f min = box.MinEdge;
|
||||
v3f max = box.MaxEdge;
|
||||
|
||||
|
||||
|
||||
|
||||
if(txc == NULL)
|
||||
{
|
||||
static const f32 txc_default[24] = {
|
||||
|
@ -97,15 +99,70 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
|||
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
|
||||
};
|
||||
|
||||
for(s32 j=0; j<24; j++)
|
||||
v2f t;
|
||||
for(int i = 0; i < tilecount; i++)
|
||||
{
|
||||
switch (tiles[i].rotation)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: //R90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 2: //R180
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(180,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 3: //R270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 4: //FXR90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 5: //FXR270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
t=vertices[i*4].TCoords;
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 6: //FYR90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
case 7: //FYR270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
case 8: //FX
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 9: //FY
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(s32 j=0; j<24; j++)
|
||||
{
|
||||
int tileindex = MYMIN(j/4, tilecount-1);
|
||||
vertices[j].TCoords *= tiles[tileindex].texture.size;
|
||||
vertices[j].TCoords += tiles[tileindex].texture.pos;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
|
||||
// Add to mesh collector
|
||||
for(s32 j=0; j<24; j+=4)
|
||||
{
|
||||
|
@ -1154,14 +1211,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
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, decode_light(f.light_source));
|
||||
|
||||
|
@ -1172,17 +1223,43 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
for(int j = 0; j < 6; j++)
|
||||
{
|
||||
// Handles facedir rotation for textures
|
||||
tiles[j] = getNodeTile(n, p, tile_dirs[j], data);
|
||||
}
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
|
||||
f32 temp;
|
||||
if (box.MinEdge.X > box.MaxEdge.X)
|
||||
{
|
||||
temp=box.MinEdge.X;
|
||||
box.MinEdge.X=box.MaxEdge.X;
|
||||
box.MaxEdge.X=temp;
|
||||
}
|
||||
if (box.MinEdge.Y > box.MaxEdge.Y)
|
||||
{
|
||||
temp=box.MinEdge.Y;
|
||||
box.MinEdge.Y=box.MaxEdge.Y;
|
||||
box.MaxEdge.Y=temp;
|
||||
}
|
||||
if (box.MinEdge.Z > box.MaxEdge.Z)
|
||||
{
|
||||
temp=box.MinEdge.Z;
|
||||
box.MinEdge.Z=box.MaxEdge.Z;
|
||||
box.MaxEdge.Z=temp;
|
||||
}
|
||||
|
||||
//
|
||||
// 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 tx1 = (box.MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (box.MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (box.MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (box.MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
|
||||
f32 txc[24] = {
|
||||
// up
|
||||
tx1, 1-tz2, tx2, 1-tz1,
|
||||
|
@ -1197,7 +1274,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
// front
|
||||
tx1, 1-ty2, tx2, 1-ty1,
|
||||
};
|
||||
|
||||
makeCuboid(&collector, box, tiles, 6, c, txc);
|
||||
}
|
||||
break;}
|
||||
|
|
|
@ -64,6 +64,10 @@ public:
|
|||
infostream<<"DummyLoadSAO step"<<std::endl;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
@ -132,6 +136,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
float m_timer1;
|
||||
float m_age;
|
||||
|
@ -208,8 +216,7 @@ public:
|
|||
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,
|
||||
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
|
||||
|
@ -314,6 +321,10 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string m_itemstring;
|
||||
|
@ -490,8 +501,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||
v3f p_pos = m_base_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
|
@ -880,6 +890,22 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
|||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
|
||||
if (m_prop.physical)
|
||||
{
|
||||
//update collision box
|
||||
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
||||
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
||||
|
||||
toset->MinEdge += m_base_position;
|
||||
toset->MaxEdge += m_base_position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerSAO
|
||||
*/
|
||||
|
@ -1434,3 +1460,7 @@ std::string PlayerSAO::getPropertyPacket()
|
|||
return gob_cmd_set_properties(m_prop);
|
||||
}
|
||||
|
||||
bool PlayerSAO::getCollisionBox(aabb3f *toset) {
|
||||
//player collision handling is already done clientside no need to do it twice
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||
bool select_horiz_by_yawpitch);
|
||||
std::string getName();
|
||||
bool getCollisionBox(aabb3f *toset);
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
|
@ -235,6 +236,8 @@ public:
|
|||
m_is_singleplayer = is_singleplayer;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset);
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
|
||||
|
|
|
@ -236,11 +236,16 @@ void set_default_settings(Settings *settings)
|
|||
settings->setDefault("mgv7_np_heat", "25, 50, (500, 500, 500), 35293, 1, 0");
|
||||
settings->setDefault("mgv7_np_humidity", "50, 31.25, (750, 750, 750), 12094, 2, 0.6");
|
||||
|
||||
settings->setDefault("mgindev_np_terrain_base", "-4, 20, (250.0, 250, 250), 82341, 5, 0.6, 10");
|
||||
settings->setDefault("mgindev_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6, 10");
|
||||
settings->setDefault("mgindev_np_steepness", "0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 10");
|
||||
settings->setDefault("mgindev_np_mud", "4, 2, (200, 200, 200), 91013, 3, 0.55, 1");
|
||||
settings->setDefault("gravity_acceleration_client", "9.86");
|
||||
settings->setDefault("mgindev_np_terrain_base", "-4, 20, (250, 250, 250), 82341, 5, 0.6, 10, 10");
|
||||
settings->setDefault("mgindev_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6, 10, 10");
|
||||
settings->setDefault("mgindev_np_steepness", "0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2, 10");
|
||||
settings->setDefault("mgindev_np_mud", "4, 2, (200, 200, 200), 91013, 3, 0.55, 1, 1");
|
||||
settings->setDefault("mgindev_np_float_islands1", "0, 1, (64, 64, 64 ), 3683, 5, 0.5, 1, 1.5");
|
||||
settings->setDefault("mgindev_np_float_islands2", "0, 1, (8, 8, 8 ), 9292, 2, 0.5, 1, 1.5");
|
||||
settings->setDefault("mgindev_np_float_islands3", "0, 1, (256, 256, 256), 6412, 2, 0.5, 1, 0.5");
|
||||
settings->setDefault("mgindev_np_biome", "0, 1, (250, 250, 250), 9130, 3, 0.50, 1, 10");
|
||||
settings->setDefault("mgindev_float_islands", "500");
|
||||
|
||||
}
|
||||
|
||||
void override_default_settings(Settings *settings, Settings *from)
|
||||
|
|
|
@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "emerge.h"
|
||||
#include "mapgen_v6.h"
|
||||
#include "mapgen_indev.h"
|
||||
#include "mapgen_singlenode.h"
|
||||
|
||||
|
||||
/////////////////////////////// Emerge Manager ////////////////////////////////
|
||||
|
@ -48,6 +49,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) {
|
|||
//register built-in mapgens
|
||||
registerMapgen("v6", new MapgenFactoryV6());
|
||||
registerMapgen("indev", new MapgenFactoryIndev());
|
||||
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
||||
|
||||
this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef);
|
||||
this->params = NULL;
|
||||
|
|
|
@ -63,8 +63,9 @@ public:
|
|||
std::map<v3s16, BlockEmergeData *> blocks_enqueued;
|
||||
std::map<u16, u16> peer_queue_count;
|
||||
|
||||
//biome manager
|
||||
//Mapgen-related structures
|
||||
BiomeDefManager *biomedef;
|
||||
std::vector<Ore *> ores;
|
||||
|
||||
EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef);
|
||||
~EmergeManager();
|
||||
|
|
|
@ -2096,7 +2096,7 @@ void ClientEnvironment::step(float dtime)
|
|||
Move the lplayer.
|
||||
This also does collision detection.
|
||||
*/
|
||||
lplayer->move(dtime_part, *m_map, position_max_increment,
|
||||
lplayer->move(dtime_part, this, position_max_increment,
|
||||
&player_collisions);
|
||||
}
|
||||
}
|
||||
|
|
49
src/game.cpp
49
src/game.cpp
|
@ -2189,6 +2189,47 @@ void the_game(
|
|||
{
|
||||
update_wielded_item_trigger = true;
|
||||
}
|
||||
else if(event.type == CE_SPAWN_PARTICLE)
|
||||
{
|
||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||
AtlasPointer ap =
|
||||
gamedef->tsrc()->getTexture(*(event.spawn_particle.texture));
|
||||
|
||||
new Particle(gamedef, smgr, player, client.getEnv(),
|
||||
*event.spawn_particle.pos,
|
||||
*event.spawn_particle.vel,
|
||||
*event.spawn_particle.acc,
|
||||
event.spawn_particle.expirationtime,
|
||||
event.spawn_particle.size,
|
||||
event.spawn_particle.collisiondetection, ap);
|
||||
}
|
||||
else if(event.type == CE_ADD_PARTICLESPAWNER)
|
||||
{
|
||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||
AtlasPointer ap =
|
||||
gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture));
|
||||
|
||||
new ParticleSpawner(gamedef, smgr, player,
|
||||
event.add_particlespawner.amount,
|
||||
event.add_particlespawner.spawntime,
|
||||
*event.add_particlespawner.minpos,
|
||||
*event.add_particlespawner.maxpos,
|
||||
*event.add_particlespawner.minvel,
|
||||
*event.add_particlespawner.maxvel,
|
||||
*event.add_particlespawner.minacc,
|
||||
*event.add_particlespawner.maxacc,
|
||||
event.add_particlespawner.minexptime,
|
||||
event.add_particlespawner.maxexptime,
|
||||
event.add_particlespawner.minsize,
|
||||
event.add_particlespawner.maxsize,
|
||||
event.add_particlespawner.collisiondetection,
|
||||
ap,
|
||||
event.add_particlespawner.id);
|
||||
}
|
||||
else if(event.type == CE_DELETE_PARTICLESPAWNER)
|
||||
{
|
||||
delete_particlespawner (event.delete_particlespawner.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2418,7 +2459,8 @@ void the_game(
|
|||
const ContentFeatures &features =
|
||||
client.getNodeDefManager()->get(n);
|
||||
addPunchingParticles
|
||||
(gamedef, smgr, player, nodepos, features.tiles);
|
||||
(gamedef, smgr, player, client.getEnv(),
|
||||
nodepos, features.tiles);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2456,7 +2498,8 @@ void the_game(
|
|||
const ContentFeatures &features =
|
||||
client.getNodeDefManager()->get(wasnode);
|
||||
addDiggingParticles
|
||||
(gamedef, smgr, player, nodepos, features.tiles);
|
||||
(gamedef, smgr, player, client.getEnv(),
|
||||
nodepos, features.tiles);
|
||||
}
|
||||
|
||||
dig_time = 0;
|
||||
|
@ -2737,6 +2780,7 @@ void the_game(
|
|||
*/
|
||||
|
||||
allparticles_step(dtime, client.getEnv());
|
||||
allparticlespawners_step(dtime, client.getEnv());
|
||||
|
||||
/*
|
||||
Fog
|
||||
|
@ -3222,6 +3266,7 @@ void the_game(
|
|||
clouds->drop();
|
||||
if(gui_chat_console)
|
||||
gui_chat_console->drop();
|
||||
clear_particles ();
|
||||
|
||||
/*
|
||||
Draw a "shutting down" screen, which will be shown while the map
|
||||
|
|
|
@ -43,6 +43,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "subgame.h"
|
||||
|
||||
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define LSTRING(x) LSTRING_(x)
|
||||
#define LSTRING_(x) L##x
|
||||
|
||||
const wchar_t *contrib_core_strs[] = {
|
||||
L"Perttu Ahola (celeron55) <celeron55@gmail.com>",
|
||||
|
@ -142,6 +144,7 @@ enum
|
|||
GUI_ID_SHADERS_CB,
|
||||
GUI_ID_PRELOAD_ITEM_VISUALS_CB,
|
||||
GUI_ID_ENABLE_PARTICLES_CB,
|
||||
GUI_ID_LIQUID_FINITE_CB,
|
||||
GUI_ID_DAMAGE_CB,
|
||||
GUI_ID_CREATIVE_CB,
|
||||
GUI_ID_PUBLIC_CB,
|
||||
|
@ -432,6 +435,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
|||
e->setDrawBackground(true);
|
||||
if (m_data->serverlist_show_available == false)
|
||||
m_data->servers = ServerList::getLocal();
|
||||
#if USE_CURL
|
||||
else
|
||||
m_data->servers = ServerList::getOnline();
|
||||
#endif
|
||||
updateGuiServerList();
|
||||
e->setSelected(0);
|
||||
}
|
||||
|
@ -724,6 +731,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
|||
GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
|
||||
}
|
||||
|
||||
{
|
||||
core::rect<s32> rect(0, 0, option_w+20+20, 30);
|
||||
rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*3);
|
||||
Environment->addCheckBox(m_data->liquid_finite, rect, this,
|
||||
GUI_ID_LIQUID_FINITE_CB, wgettext("Finite liquid"));
|
||||
}
|
||||
|
||||
// Key change button
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 120, 30);
|
||||
|
@ -750,7 +764,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
|||
core::rect<s32> rect(0, 0, 130, 70);
|
||||
rect += m_topleft_client + v2s32(35, 160);
|
||||
Environment->addStaticText(
|
||||
L"Minetest " VERSION_STRING "\nhttp://minetest.net/",
|
||||
L"Minetest " LSTRING(VERSION_STRING) L"\nhttp://minetest.net/",
|
||||
rect, false, true, this, -1);
|
||||
}
|
||||
{
|
||||
|
@ -970,6 +984,12 @@ void GUIMainMenu::readInput(MainMenuData *dst)
|
|||
dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_LIQUID_FINITE_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
dst->liquid_finite = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
|
||||
|
|
|
@ -52,6 +52,7 @@ struct MainMenuData
|
|||
int enable_shaders;
|
||||
bool preload_item_visuals;
|
||||
bool enable_particles;
|
||||
bool liquid_finite;
|
||||
// Server options
|
||||
bool creative_mode;
|
||||
bool enable_damage;
|
||||
|
@ -71,7 +72,13 @@ struct MainMenuData
|
|||
|
||||
MainMenuData():
|
||||
// Generic
|
||||
selected_tab(0),
|
||||
selected_tab(
|
||||
#if USE_CURL
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
),
|
||||
// Client opts
|
||||
fancy_trees(false),
|
||||
smooth_lighting(false),
|
||||
|
@ -84,7 +91,13 @@ struct MainMenuData
|
|||
// Actions
|
||||
only_refresh(false),
|
||||
|
||||
serverlist_show_available(false)
|
||||
serverlist_show_available(
|
||||
#if USE_CURL
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -903,6 +903,10 @@ void Inventory::deSerialize(std::istream &is)
|
|||
|
||||
m_lists.push_back(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SerializationError("invalid inventory specifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "gamedef.h"
|
||||
#include "nodedef.h"
|
||||
#include "settings.h"
|
||||
#include "environment.h"
|
||||
#include "map.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
|
@ -57,9 +58,10 @@ LocalPlayer::~LocalPlayer()
|
|||
{
|
||||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
||||
std::list<CollisionInfo> *collision_info)
|
||||
{
|
||||
Map *map = &env->getMap();
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
v3f position = getPosition();
|
||||
|
@ -97,15 +99,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
if(in_liquid)
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
|
||||
in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
// If not in liquid, the threshold of going in is at lower y
|
||||
else
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
|
||||
in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
@ -118,7 +120,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
*/
|
||||
try{
|
||||
v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
|
||||
in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
@ -132,8 +134,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
try {
|
||||
v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
|
||||
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
|
||||
is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable ||
|
||||
nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move);
|
||||
is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable ||
|
||||
nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
@ -197,7 +199,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
|
||||
collisionMoveResult result = collisionMoveSimple(env, m_gamedef,
|
||||
pos_max_d, playerbox, player_stepheight, dtime,
|
||||
position, m_speed, accel_f);
|
||||
|
||||
|
@ -219,7 +221,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
*/
|
||||
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" &&
|
||||
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,
|
||||
|
@ -227,7 +229,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
m_need_to_get_new_sneak_node = false;
|
||||
m_sneak_node_exists = false;
|
||||
}
|
||||
else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air")
|
||||
else if(nodemgr->get(map->getNodeNoEx(current_node)).name != "air")
|
||||
{
|
||||
// We are on something, so make sure to recalculate the sneak
|
||||
// node.
|
||||
|
@ -267,10 +269,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
|
||||
try{
|
||||
// The node to be sneaked on has to be walkable
|
||||
if(nodemgr->get(map.getNode(p)).walkable == false)
|
||||
if(nodemgr->get(map->getNode(p)).walkable == false)
|
||||
continue;
|
||||
// And the node above it has to be nonwalkable
|
||||
if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true)
|
||||
if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
@ -331,7 +333,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
{
|
||||
camera_barely_in_ceiling = false;
|
||||
v3s16 camera_np = floatToInt(getEyePosition(), BS);
|
||||
MapNode n = map.getNodeNoEx(camera_np);
|
||||
MapNode n = map->getNodeNoEx(camera_np);
|
||||
if(n.getContent() != CONTENT_IGNORE){
|
||||
if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){
|
||||
camera_barely_in_ceiling = true;
|
||||
|
@ -343,21 +345,21 @@ 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;
|
||||
m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name;
|
||||
|
||||
/*
|
||||
Check properties of the node on which the player is standing
|
||||
*/
|
||||
const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos()));
|
||||
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
|
||||
// Determine if jumping is possible
|
||||
m_can_jump = touching_ground && !in_liquid;
|
||||
if(itemgroup_get(f.groups, "disable_jump"))
|
||||
m_can_jump = false;
|
||||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d)
|
||||
{
|
||||
move(dtime, map, pos_max_d, NULL);
|
||||
move(dtime, env, pos_max_d, NULL);
|
||||
}
|
||||
|
||||
void LocalPlayer::applyControl(float dtime)
|
||||
|
|
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "player.h"
|
||||
#include <list>
|
||||
|
||||
class ClientEnvironment;
|
||||
|
||||
class LocalPlayer : public Player
|
||||
{
|
||||
public:
|
||||
|
@ -38,9 +40,9 @@ public:
|
|||
|
||||
v3f overridePosition;
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
||||
std::list<CollisionInfo> *collision_info);
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
|
||||
|
||||
void applyControl(float dtime);
|
||||
|
||||
|
|
|
@ -1557,6 +1557,7 @@ int main(int argc, char *argv[])
|
|||
menudata.enable_shaders = g_settings->getS32("enable_shaders");
|
||||
menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals");
|
||||
menudata.enable_particles = g_settings->getBool("enable_particles");
|
||||
menudata.liquid_finite = g_settings->getBool("liquid_finite");
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
|
||||
menudata.creative_mode = g_settings->getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings->getBool("enable_damage");
|
||||
|
@ -1724,6 +1725,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
playername = wide_to_narrow(menudata.name);
|
||||
if (playername == "")
|
||||
playername = std::string("Guest") + itos(myrand_range(1000,9999));
|
||||
password = translatePassword(playername, menudata.password);
|
||||
//infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
|
||||
|
@ -1747,6 +1750,7 @@ int main(int argc, char *argv[])
|
|||
g_settings->setS32("enable_shaders", menudata.enable_shaders);
|
||||
g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals));
|
||||
g_settings->set("enable_particles", itos(menudata.enable_particles));
|
||||
g_settings->set("liquid_finite", itos(menudata.liquid_finite));
|
||||
|
||||
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
||||
|
|
|
@ -50,7 +50,7 @@ class NodeMetadata;
|
|||
class IGameDef;
|
||||
class IRollbackReportSink;
|
||||
class EmergeManager;
|
||||
class BlockMakeData;
|
||||
struct BlockMakeData;
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -455,6 +455,80 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
|||
v3f vertex_pos[4];
|
||||
v3s16 vertex_dirs[4];
|
||||
getNodeVertexDirs(dir, vertex_dirs);
|
||||
v3s16 t;
|
||||
switch (tile.rotation)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: //R90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
break;
|
||||
case 2: //R180
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[2];
|
||||
vertex_dirs[2] = t;
|
||||
t = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
break;
|
||||
case 3: //R270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
break;
|
||||
case 4: //FXR90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 5: //FXR270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 6: //FYR90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
case 7: //FYR270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
case 8: //FX
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 9: //FY
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertex_pos[i] = v3f(
|
||||
|
@ -601,60 +675,50 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
|
|||
// 5 = (0,0,-1)
|
||||
// 6 = (0,-1,0)
|
||||
// 7 = (-1,0,0)
|
||||
u8 dir_i = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7;
|
||||
u8 dir_i = ((dir.X + 2 * dir.Y + 3 * dir.Z) & 7)*2;
|
||||
|
||||
// Get rotation for things like chests
|
||||
u8 facedir = mn.getFaceDir(ndef);
|
||||
assert(facedir <= 3);
|
||||
|
||||
static const u8 dir_to_tile[4 * 8] =
|
||||
assert(facedir <= 23);
|
||||
static const u16 dir_to_tile[24 * 16] =
|
||||
{
|
||||
// 0 +X +Y +Z 0 -Z -Y -X
|
||||
0, 2, 0, 4, 0, 5, 1, 3, // facedir = 0
|
||||
0, 4, 0, 3, 0, 2, 1, 5, // facedir = 1
|
||||
0, 3, 0, 5, 0, 4, 1, 2, // facedir = 2
|
||||
0, 5, 0, 2, 0, 3, 1, 4, // facedir = 3
|
||||
// 0 +X +Y +Z -Z -Y -X -> value=tile,rotation
|
||||
0,0, 2,0 , 0,0 , 4,0 , 0,0, 5,0 , 1,0 , 3,0 , // rotate around y+ 0 - 3
|
||||
0,0, 4,0 , 0,3 , 3,0 , 0,0, 2,0 , 1,1 , 5,0 ,
|
||||
0,0, 3,0 , 0,2 , 5,0 , 0,0, 4,0 , 1,2 , 2,0 ,
|
||||
0,0, 5,0 , 0,1 , 2,0 , 0,0, 3,0 , 1,3 , 4,0 ,
|
||||
|
||||
0,0, 2,3 , 5,0 , 0,2 , 0,0, 1,0 , 4,2 , 3,1 , // rotate around z+ 4 - 7
|
||||
0,0, 4,3 , 2,0 , 0,3 , 0,0, 1,1 , 3,2 , 5,1 ,
|
||||
0,0, 3,3 , 4,0 , 0,0 , 0,0, 1,2 , 5,2 , 2,1 ,
|
||||
0,0, 5,3 , 3,0 , 0,1 , 0,0, 1,3 , 2,2 , 4,1 ,
|
||||
|
||||
0,0, 2,1 , 4,2 , 1,2 , 0,0, 0,0 , 5,0 , 3,3 , // rotate around z- 8 - 11
|
||||
0,0, 4,1 , 3,2 , 1,3 , 0,0, 0,3 , 2,0 , 5,3 ,
|
||||
0,0, 3,1 , 5,2 , 1,0 , 0,0, 0,2 , 4,0 , 2,3 ,
|
||||
0,0, 5,1 , 2,2 , 1,1 , 0,0, 0,1 , 3,0 , 4,3 ,
|
||||
|
||||
0,0, 0,3 , 3,3 , 4,1 , 0,0, 5,3 , 2,3 , 1,3 , // rotate around x+ 12 - 15
|
||||
0,0, 0,2 , 5,3 , 3,1 , 0,0, 2,3 , 4,3 , 1,0 ,
|
||||
0,0, 0,1 , 2,3 , 5,1 , 0,0, 4,3 , 3,3 , 1,1 ,
|
||||
0,0, 0,0 , 4,3 , 2,1 , 0,0, 3,3 , 5,3 , 1,2 ,
|
||||
|
||||
0,0, 1,1 , 2,1 , 4,3 , 0,0, 5,1 , 3,1 , 0,1 , // rotate around x- 16 - 19
|
||||
0,0, 1,2 , 4,1 , 3,3 , 0,0, 2,1 , 5,1 , 0,0 ,
|
||||
0,0, 1,3 , 3,1 , 5,3 , 0,0, 4,1 , 2,1 , 0,3 ,
|
||||
0,0, 1,0 , 5,1 , 2,3 , 0,0, 3,1 , 4,1 , 0,2 ,
|
||||
|
||||
0,0, 3,2 , 1,2 , 4,2 , 0,0, 5,2 , 0,2 , 2,2 , // rotate around y- 20 - 23
|
||||
0,0, 5,2 , 1,3 , 3,2 , 0,0, 2,2 , 0,1 , 4,2 ,
|
||||
0,0, 2,2 , 1,0 , 5,2 , 0,0, 4,2 , 0,0 , 3,2 ,
|
||||
0,0, 4,2 , 1,1 , 2,2 , 0,0, 3,2 , 0,3 , 5,2
|
||||
|
||||
};
|
||||
u8 tileindex = dir_to_tile[facedir*8 + dir_i];
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
u16 tile_index=facedir*16 + dir_i;
|
||||
TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data);
|
||||
spec.rotation=dir_to_tile[tile_index + 1];
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
@ -794,6 +858,7 @@ static void updateFastFaceRow(
|
|||
&& next_lights[2] == lights[2]
|
||||
&& next_lights[3] == lights[3]
|
||||
&& next_tile == tile
|
||||
&& tile.rotation == 0
|
||||
&& next_light_source == light_source)
|
||||
{
|
||||
next_is_different = false;
|
||||
|
|
135
src/mapgen.cpp
135
src/mapgen.cpp
|
@ -49,6 +49,141 @@ FlagDesc flagdesc_mapgen[] = {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Ore *createOre(OreType type) {
|
||||
switch (type) {
|
||||
case ORE_SCATTER:
|
||||
return new OreScatter;
|
||||
case ORE_SHEET:
|
||||
return new OreSheet;
|
||||
//case ORE_CLAYLIKE: //TODO: implement this!
|
||||
// return new OreClaylike;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ore::resolveNodeNames(INodeDefManager *ndef) {
|
||||
if (ore == CONTENT_IGNORE) {
|
||||
ore = ndef->getId(ore_name);
|
||||
if (ore == CONTENT_IGNORE) {
|
||||
errorstream << "Ore::resolveNodeNames: ore node '"
|
||||
<< ore_name << "' not defined";
|
||||
ore = CONTENT_AIR;
|
||||
wherein = CONTENT_AIR;
|
||||
}
|
||||
}
|
||||
|
||||
if (wherein == CONTENT_IGNORE) {
|
||||
wherein = ndef->getId(wherein_name);
|
||||
if (wherein == CONTENT_IGNORE) {
|
||||
errorstream << "Ore::resolveNodeNames: wherein node '"
|
||||
<< wherein_name << "' not defined";
|
||||
ore = CONTENT_AIR;
|
||||
wherein = CONTENT_AIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
if (nmin.Y > height_max || nmax.Y < height_min)
|
||||
return;
|
||||
|
||||
resolveNodeNames(mg->ndef);
|
||||
|
||||
MapNode n_ore(ore);
|
||||
ManualMapVoxelManipulator *vm = mg->vm;
|
||||
PseudoRandom pr(blockseed);
|
||||
|
||||
int ymin = MYMAX(nmin.Y, height_min);
|
||||
int ymax = MYMIN(nmax.Y, height_max);
|
||||
if (clust_size >= ymax - ymin + 1)
|
||||
return;
|
||||
|
||||
int volume = (nmax.X - nmin.X + 1) *
|
||||
(nmax.Y - nmin.Y + 1) *
|
||||
(nmax.Z - nmin.Z + 1);
|
||||
int csize = clust_size;
|
||||
int orechance = (csize * csize * csize) / clust_num_ores;
|
||||
int nclusters = volume / clust_scarcity;
|
||||
|
||||
for (int i = 0; i != nclusters; i++) {
|
||||
int x0 = pr.range(nmin.X, nmax.X - csize + 1);
|
||||
int y0 = pr.range(ymin, ymax - csize + 1);
|
||||
int z0 = pr.range(nmin.Z, nmax.Z - csize + 1);
|
||||
|
||||
if (np && (NoisePerlin3D(np, x0, y0, z0, mg->seed) < nthresh))
|
||||
continue;
|
||||
|
||||
for (int z1 = 0; z1 != csize; z1++)
|
||||
for (int y1 = 0; y1 != csize; y1++)
|
||||
for (int x1 = 0; x1 != csize; x1++) {
|
||||
if (pr.range(1, orechance) != 1)
|
||||
continue;
|
||||
|
||||
u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
|
||||
if (vm->m_data[i].getContent() == wherein)
|
||||
vm->m_data[i] = n_ore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OreSheet::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
if (nmin.Y > height_max || nmax.Y < height_min)
|
||||
return;
|
||||
|
||||
resolveNodeNames(mg->ndef);
|
||||
|
||||
MapNode n_ore(ore);
|
||||
ManualMapVoxelManipulator *vm = mg->vm;
|
||||
PseudoRandom pr(blockseed + 4234);
|
||||
|
||||
int ymin = MYMAX(nmin.Y, height_min);
|
||||
int ymax = MYMIN(nmax.Y, height_max);
|
||||
if (clust_size >= ymax - ymin + 1)
|
||||
return;
|
||||
|
||||
int x0 = nmin.X;
|
||||
int z0 = nmin.Z;
|
||||
|
||||
int x1 = nmax.X;
|
||||
int z1 = nmax.Z;
|
||||
|
||||
int max_height = clust_size;
|
||||
int y_start = pr.range(ymin, ymax - max_height);
|
||||
|
||||
if (!noise) {
|
||||
int sx = nmax.X - nmin.X + 1;
|
||||
int sz = nmax.Z - nmin.Z + 1;
|
||||
noise = new Noise(np, 0, sx, sz);
|
||||
}
|
||||
noise->seed = mg->seed + y_start;
|
||||
noise->perlinMap2D(x0, z0);
|
||||
|
||||
int index = 0;
|
||||
for (int z = z0; z != z1; z++)
|
||||
for (int x = x0; x != x1; x++) {
|
||||
float noiseval = noise->result[index++];
|
||||
if (noiseval < nthresh)
|
||||
continue;
|
||||
|
||||
int height = max_height * (1. / pr.range(1, 3));
|
||||
int y0 = y_start + np->scale * noiseval; //pr.range(1, 3) - 1;
|
||||
int y1 = y0 + height;
|
||||
for (int y = y0; y != y1; y++) {
|
||||
u32 i = vm->m_area.index(x, y, z);
|
||||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
|
||||
if (vm->m_data[i].getContent() == wherein)
|
||||
vm->m_data[i] = n_ore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) {
|
||||
bool isliquid, wasliquid;
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
|
|
45
src/mapgen.h
45
src/mapgen.h
|
@ -45,7 +45,7 @@ class MapBlock;
|
|||
class ManualMapVoxelManipulator;
|
||||
class VoxelManipulator;
|
||||
class INodeDefManager;
|
||||
class BlockMakeData;
|
||||
struct BlockMakeData;
|
||||
class VoxelArea;
|
||||
|
||||
struct MapgenParams {
|
||||
|
@ -97,5 +97,48 @@ struct MapgenFactory {
|
|||
virtual MapgenParams *createMapgenParams() = 0;
|
||||
};
|
||||
|
||||
enum OreType {
|
||||
ORE_SCATTER,
|
||||
ORE_SHEET,
|
||||
ORE_CLAYLIKE
|
||||
};
|
||||
|
||||
class Ore {
|
||||
public:
|
||||
std::string ore_name;
|
||||
std::string wherein_name;
|
||||
|
||||
content_t ore;
|
||||
content_t wherein; // the node to be replaced
|
||||
s16 clust_scarcity; //
|
||||
s16 clust_num_ores; // how many ore nodes are in a chunk
|
||||
s16 clust_size; // how large (in nodes) a chunk of ore is
|
||||
s16 height_min;
|
||||
s16 height_max;
|
||||
float nthresh; // threshhold for noise at which an ore is placed
|
||||
NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering)
|
||||
Noise *noise;
|
||||
|
||||
Ore() {
|
||||
ore = CONTENT_IGNORE;
|
||||
wherein = CONTENT_IGNORE;
|
||||
np = NULL;
|
||||
noise = NULL;
|
||||
}
|
||||
|
||||
void resolveNodeNames(INodeDefManager *ndef);
|
||||
virtual void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
||||
};
|
||||
|
||||
class OreScatter : public Ore {
|
||||
void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
class OreSheet : public Ore {
|
||||
void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
Ore *createOre(OreType type);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,18 +19,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "mapgen_indev.h"
|
||||
#include "constants.h"
|
||||
#include "map.h"
|
||||
#include "main.h"
|
||||
#include "log.h"
|
||||
|
||||
/////////////////// Mapgen Indev perlin noise default values
|
||||
/////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings)
|
||||
|
||||
NoiseIndevParams nparams_indev_def_terrain_base
|
||||
(-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_terrain_higher
|
||||
(20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_steepness
|
||||
(0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 1);
|
||||
NoiseIndevParams nparams_indev_def_mud
|
||||
(AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 1);
|
||||
NoiseIndevParams nparams_indev_def;
|
||||
|
||||
/*
|
||||
NoiseIndevParams nparams_indev_def_terrain_base;
|
||||
// (-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_terrain_higher;
|
||||
// (20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_steepness;
|
||||
// (0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 1);
|
||||
NoiseIndevParams nparams_indev_def_mud;
|
||||
// (AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 1);
|
||||
NoiseIndevParams nparams_indev_def_float_islands;
|
||||
// (1, 10.0, v3f(500.0, 500.0, 500.0), 32451, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_biome;
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -39,46 +48,52 @@ void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
|
|||
this->npindev = np;
|
||||
}
|
||||
|
||||
|
||||
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
|
||||
init(np, seed, sx, sy, 1);
|
||||
}
|
||||
|
||||
|
||||
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz) : Noise(np, seed, sx, sy, sz) {
|
||||
init(np, seed, sx, sy, sz);
|
||||
}
|
||||
|
||||
float farscale(float scale, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 1 - (fabs(z)) ) / (MAP_GENERATION_LIMIT * 1) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
float farscale(float scale, float x, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 2 - (fabs(x) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 2) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
float farscale(float scale, float x, float y, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 3 - (fabs(x) + fabs(y) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 3) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
void NoiseIndev::transformNoiseMapFarScale(float xx, float yy, float zz) {
|
||||
// more correct use distantion from 0,0,0 via pow, but + is faster
|
||||
//float farscale = ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 3 - (fabs(xx) + fabs(yy) + fabs(zz)) ) / (MAP_GENERATION_LIMIT * 3) ) * ((npindev)->farscale - 1) );
|
||||
// dstream << "TNM rs=" << farscale << " from=" << (npindev)->farscale << " x=" << xx << " y=" << yy <<" z=" << zz << std::endl;
|
||||
int i = 0;
|
||||
for (int z = 0; z != sz; z++) {
|
||||
for (int y = 0; y != sy; y++) {
|
||||
for (int x = 0; x != sx; x++) {
|
||||
//result[i] = result[i] * npindev->scale * farscale + npindev->offset;
|
||||
result[i] = result[i] * npindev->scale * farscale(npindev->farscale,xx,yy,zz) + npindev->offset;
|
||||
result[i] = result[i] * npindev->scale * farscale(npindev->farscale, xx, yy, zz) + npindev->offset;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params) : MapgenV6(mapgenid, params) {
|
||||
noiseindev_terrain_base = new NoiseIndev(params->npindev_terrain_base, seed, csize.X, csize.Y);
|
||||
noiseindev_terrain_higher = new NoiseIndev(params->npindev_terrain_higher, seed, csize.X, csize.Y);
|
||||
noiseindev_steepness = new NoiseIndev(params->npindev_steepness, seed, csize.X, csize.Y);
|
||||
MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge)
|
||||
: MapgenV6(mapgenid, params, emerge)
|
||||
{
|
||||
noiseindev_terrain_base = new NoiseIndev(params->npindev_terrain_base, seed, csize.X, csize.Z);
|
||||
noiseindev_terrain_higher = new NoiseIndev(params->npindev_terrain_higher, seed, csize.X, csize.Z);
|
||||
noiseindev_steepness = new NoiseIndev(params->npindev_steepness, seed, csize.X, csize.Z);
|
||||
// noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Y);
|
||||
// noise_trees = new Noise(params->np_trees, seed, csize.X, csize.Y);
|
||||
noiseindev_mud = new NoiseIndev(params->npindev_mud, seed, csize.X, csize.Y);
|
||||
noiseindev_mud = new NoiseIndev(params->npindev_mud, seed, csize.X, csize.Z);
|
||||
// noise_beach = new Noise(params->np_beach, seed, csize.X, csize.Y);
|
||||
// noise_biome = new Noise(params->np_biome, seed, csize.X, csize.Y);
|
||||
noiseindev_float_islands1 = new NoiseIndev(params->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z);
|
||||
noiseindev_float_islands2 = new NoiseIndev(params->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z);
|
||||
noiseindev_float_islands3 = new NoiseIndev(params->npindev_float_islands3, seed, csize.X, csize.Z);
|
||||
noiseindev_biome = new NoiseIndev(params->npindev_biome, seed, csize.X, csize.Z);
|
||||
}
|
||||
|
||||
MapgenIndev::~MapgenIndev() {
|
||||
|
@ -89,10 +104,12 @@ MapgenIndev::~MapgenIndev() {
|
|||
//delete noise_trees;
|
||||
delete noiseindev_mud;
|
||||
//delete noise_beach;
|
||||
//delete noise_biome;
|
||||
delete noiseindev_float_islands1;
|
||||
delete noiseindev_float_islands2;
|
||||
delete noiseindev_float_islands3;
|
||||
delete noiseindev_biome;
|
||||
}
|
||||
|
||||
|
||||
void MapgenIndev::calculateNoise() {
|
||||
int x = node_min.X;
|
||||
int y = node_min.Y;
|
||||
|
@ -100,31 +117,49 @@ void MapgenIndev::calculateNoise() {
|
|||
// Need to adjust for the original implementation's +.5 offset...
|
||||
if (!(flags & MG_FLAT)) {
|
||||
noiseindev_terrain_base->perlinMap2D(
|
||||
x + 0.5 * noiseindev_terrain_base->npindev->spread.X,
|
||||
z + 0.5 * noiseindev_terrain_base->npindev->spread.Z);
|
||||
x + 0.5 * noiseindev_terrain_base->npindev->spread.X * farscale(noiseindev_terrain_base->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_terrain_base->npindev->spread.Z * farscale(noiseindev_terrain_base->npindev->farspread, x, z));
|
||||
noiseindev_terrain_base->transformNoiseMapFarScale(x, y, z);
|
||||
//noise_terrain_base->transformNoiseMap();
|
||||
|
||||
noiseindev_terrain_higher->perlinMap2D(
|
||||
x + 0.5 * noiseindev_terrain_higher->npindev->spread.X,
|
||||
z + 0.5 * noiseindev_terrain_higher->npindev->spread.Z);
|
||||
x + 0.5 * noiseindev_terrain_higher->npindev->spread.X * farscale(noiseindev_terrain_higher->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_terrain_higher->npindev->spread.Z * farscale(noiseindev_terrain_higher->npindev->farspread, x, z));
|
||||
noiseindev_terrain_higher->transformNoiseMapFarScale(x, y, z);
|
||||
//noise_terrain_higher->transformNoiseMap();
|
||||
|
||||
noiseindev_steepness->perlinMap2D(
|
||||
x + 0.5 * noiseindev_steepness->npindev->spread.X,
|
||||
z + 0.5 * noiseindev_steepness->npindev->spread.Z);
|
||||
x + 0.5 * noiseindev_steepness->npindev->spread.X * farscale(noiseindev_steepness->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_steepness->npindev->spread.Z * farscale(noiseindev_steepness->npindev->farspread, x, z));
|
||||
noiseindev_steepness->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noise_height_select->perlinMap2D(
|
||||
x + 0.5 * noise_height_select->np->spread.X,
|
||||
z + 0.5 * noise_height_select->np->spread.Z);
|
||||
|
||||
noiseindev_float_islands1->perlinMap3D(
|
||||
x + 0.33 * noiseindev_float_islands1->npindev->spread.X * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
|
||||
y + 0.33 * noiseindev_float_islands1->npindev->spread.Y * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
|
||||
z + 0.33 * noiseindev_float_islands1->npindev->spread.Z * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z)
|
||||
);
|
||||
noiseindev_float_islands1->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_float_islands2->perlinMap3D(
|
||||
x + 0.33 * noiseindev_float_islands2->npindev->spread.X * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
|
||||
y + 0.33 * noiseindev_float_islands2->npindev->spread.Y * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
|
||||
z + 0.33 * noiseindev_float_islands2->npindev->spread.Z * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z)
|
||||
);
|
||||
noiseindev_float_islands2->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_float_islands3->perlinMap2D(
|
||||
x + 0.5 * noiseindev_float_islands3->npindev->spread.X * farscale(noiseindev_float_islands3->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z));
|
||||
noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
}
|
||||
|
||||
if (!(flags & MG_FLAT)) {
|
||||
noiseindev_mud->perlinMap2D(
|
||||
x + 0.5 * noiseindev_mud->npindev->spread.X,
|
||||
z + 0.5 * noiseindev_mud->npindev->spread.Z);
|
||||
x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z),
|
||||
z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z));
|
||||
noiseindev_mud->transformNoiseMapFarScale(x, y, z);
|
||||
}
|
||||
noise_beach->perlinMap2D(
|
||||
|
@ -132,8 +167,8 @@ void MapgenIndev::calculateNoise() {
|
|||
z + 0.7 * noise_beach->np->spread.Z);
|
||||
|
||||
noise_biome->perlinMap2D(
|
||||
x + 0.6 * noise_biome->np->spread.X,
|
||||
z + 0.2 * noise_biome->np->spread.Z);
|
||||
x + 0.6 * noiseindev_biome->npindev->spread.X * farscale(noiseindev_biome->npindev->farspread, x, z),
|
||||
z + 0.2 * noiseindev_biome->npindev->spread.Z * farscale(noiseindev_biome->npindev->farspread, x, z));
|
||||
}
|
||||
|
||||
bool MapgenIndevParams::readParams(Settings *settings) {
|
||||
|
@ -147,17 +182,20 @@ bool MapgenIndevParams::readParams(Settings *settings) {
|
|||
np_trees = settings->getNoiseParams("mgv6_np_trees");
|
||||
npindev_mud = settings->getNoiseIndevParams("mgindev_np_mud");
|
||||
np_beach = settings->getNoiseParams("mgv6_np_beach");
|
||||
np_biome = settings->getNoiseParams("mgv6_np_biome");
|
||||
npindev_biome = settings->getNoiseIndevParams("mgindev_np_biome");
|
||||
np_cave = settings->getNoiseParams("mgv6_np_cave");
|
||||
npindev_float_islands1 = settings->getNoiseIndevParams("mgindev_np_float_islands1");
|
||||
npindev_float_islands2 = settings->getNoiseIndevParams("mgindev_np_float_islands2");
|
||||
npindev_float_islands3 = settings->getNoiseIndevParams("mgindev_np_float_islands3");
|
||||
|
||||
bool success =
|
||||
npindev_terrain_base && npindev_terrain_higher && npindev_steepness &&
|
||||
np_height_select && np_trees && npindev_mud &&
|
||||
np_beach && np_biome && np_cave;
|
||||
np_beach && np_biome && np_cave &&
|
||||
npindev_float_islands1 && npindev_float_islands2 && npindev_float_islands3;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void MapgenIndevParams::writeParams(Settings *settings) {
|
||||
settings->setFloat("mgv6_freq_desert", freq_desert);
|
||||
settings->setFloat("mgv6_freq_beach", freq_beach);
|
||||
|
@ -169,8 +207,11 @@ void MapgenIndevParams::writeParams(Settings *settings) {
|
|||
settings->setNoiseParams("mgv6_np_trees", np_trees);
|
||||
settings->setNoiseIndevParams("mgindev_np_mud", npindev_mud);
|
||||
settings->setNoiseParams("mgv6_np_beach", np_beach);
|
||||
settings->setNoiseParams("mgv6_np_biome", np_biome);
|
||||
settings->setNoiseIndevParams("mgindev_np_biome", npindev_biome);
|
||||
settings->setNoiseParams("mgv6_np_cave", np_cave);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,7 +232,6 @@ float MapgenIndev::baseTerrainLevelFromNoise(v2s16 p) {
|
|||
steepness, height_select);
|
||||
}
|
||||
|
||||
|
||||
float MapgenIndev::baseTerrainLevelFromMap(int index) {
|
||||
if (flags & MG_FLAT)
|
||||
return water_level;
|
||||
|
@ -205,9 +245,7 @@ float MapgenIndev::baseTerrainLevelFromMap(int index) {
|
|||
steepness, height_select);
|
||||
}
|
||||
|
||||
|
||||
float MapgenIndev::getMudAmount(int index)
|
||||
{
|
||||
float MapgenIndev::getMudAmount(int index) {
|
||||
if (flags & MG_FLAT)
|
||||
return AVERAGE_MUD_AMOUNT;
|
||||
|
||||
|
@ -218,25 +256,19 @@ float MapgenIndev::getMudAmount(int index)
|
|||
return noiseindev_mud->result[index];
|
||||
}
|
||||
|
||||
|
||||
void MapgenIndev::defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave) {
|
||||
cave.min_tunnel_diameter = 2;
|
||||
cave.max_tunnel_diameter = ps.range(2,6);
|
||||
cave.dswitchint = ps.range(1,14);
|
||||
//cave.tunnel_routepoints = 0;
|
||||
//cave.part_max_length_rs = 0;
|
||||
cave.flooded = large_cave && ps.range(0,4);
|
||||
if(large_cave){
|
||||
cave.part_max_length_rs = ps.range(2,4);
|
||||
//dstream<<"try:"<<farscale(0.2, node_min.X,node_min.Y,node_min.Z)*30<<std::endl;
|
||||
if (node_min.Y < -500 && !ps.range(0, farscale(0.2, node_min.X,node_min.Y,node_min.Z)*30)) { //huge
|
||||
cave.flooded = ps.range(0, 1);
|
||||
//dstream<<"HUGE:"<<cave.flooded<<std::endl;
|
||||
cave.tunnel_routepoints = ps.range(5, 1522);
|
||||
if (node_min.Y < -100 && !ps.range(0, farscale(0.2, node_min.X,node_min.Y,node_min.Z)*30)) { //huge
|
||||
cave.flooded = !ps.range(0, 3);
|
||||
cave.tunnel_routepoints = ps.range(5, 20);
|
||||
cave.min_tunnel_diameter = 30;
|
||||
cave.max_tunnel_diameter = ps.range(30, ps.range(80,120));
|
||||
cave.max_tunnel_diameter = ps.range(40, ps.range(80,120));
|
||||
} else {
|
||||
//dstream<<"large:"<<cave.flooded<<std::endl;
|
||||
cave.tunnel_routepoints = ps.range(5, ps.range(15,30));
|
||||
cave.min_tunnel_diameter = 5;
|
||||
cave.max_tunnel_diameter = ps.range(7, ps.range(8,24));
|
||||
|
@ -247,3 +279,93 @@ void MapgenIndev::defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool
|
|||
}
|
||||
cave.large_cave_is_flat = (ps.range(0,1) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
// version with one perlin3d. use with good params like
|
||||
settings->setDefault("mgindev_np_float_islands1", "-9.5, 10, (20, 50, 50 ), 45123, 5, 0.6, 1.5, 5");
|
||||
void MapgenIndev::generateFloatIslands(int min_y) {
|
||||
if (node_min.Y < min_y) return;
|
||||
v3s16 p0(node_min.X, node_min.Y, node_min.Z);
|
||||
MapNode n1(c_stone), n2(c_desert_stone);
|
||||
int xl = node_max.X - node_min.X;
|
||||
int yl = node_max.Y - node_min.Y;
|
||||
int zl = node_max.Z - node_min.Z;
|
||||
u32 index = 0;
|
||||
for (int x1 = 0; x1 <= xl; x1++)
|
||||
{
|
||||
//int x = x1 + node_min.Y;
|
||||
for (int z1 = 0; z1 <= zl; z1++)
|
||||
{
|
||||
//int z = z1 + node_min.Z;
|
||||
for (int y1 = 0; y1 <= yl; y1++, index++)
|
||||
{
|
||||
//int y = y1 + node_min.Y;
|
||||
float noise = noiseindev_float_islands1->result[index];
|
||||
//dstream << " y1="<<y1<< " x1="<<x1<<" z1="<<z1<< " noise="<<noise << std::endl;
|
||||
if (noise > 0 ) {
|
||||
v3s16 p = p0 + v3s16(x1, y1, z1);
|
||||
u32 i = vm->m_area.index(p);
|
||||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
// Cancel if not air
|
||||
if (vm->m_data[i].getContent() != CONTENT_AIR)
|
||||
continue;
|
||||
vm->m_data[i] = noise > 1 ? n1 : n2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void MapgenIndev::generateFloatIslands(int min_y) {
|
||||
if (node_min.Y < min_y) return;
|
||||
PseudoRandom pr(blockseed + 985);
|
||||
// originally from http://forum.minetest.net/viewtopic.php?id=4776
|
||||
float RAR = 0.8 * farscale(0.4, node_min.Y); // 0.4; // Island rarity in chunk layer. -0.4 = thick layer with holes, 0 = 50%, 0.4 = desert rarity, 0.7 = very rare.
|
||||
float AMPY = 24; // 24; // Amplitude of island centre y variation.
|
||||
float TGRAD = 24; // 24; // Noise gradient to create top surface. Tallness of island top.
|
||||
float BGRAD = 24; // 24; // Noise gradient to create bottom surface. Tallness of island bottom.
|
||||
|
||||
v3s16 p0(node_min.X, node_min.Y, node_min.Z);
|
||||
MapNode n1(c_stone);
|
||||
|
||||
float xl = node_max.X - node_min.X;
|
||||
float yl = node_max.Y - node_min.Y;
|
||||
float zl = node_max.Z - node_min.Z;
|
||||
float midy = node_min.Y + yl * 0.5;
|
||||
u32 index = 0, index2d = 0;
|
||||
for (int x1 = 0; x1 <= xl; ++x1)
|
||||
{
|
||||
for (int z1 = 0; z1 <= zl; ++z1, ++index2d)
|
||||
{
|
||||
float noise3 = noiseindev_float_islands3->result[index2d];
|
||||
float pmidy = midy + noise3 / 1.5 * AMPY;
|
||||
for (int y1 = 0; y1 <= yl; ++y1, ++index)
|
||||
{
|
||||
int y = y1 + node_min.Y;
|
||||
float noise1 = noiseindev_float_islands1->result[index];
|
||||
float offset = y > pmidy ? (y - pmidy) / TGRAD : (pmidy - y) / BGRAD;
|
||||
float noise1off = noise1 - offset - RAR;
|
||||
if (noise1off > 0 && noise1off < 0.7) {
|
||||
float noise2 = noiseindev_float_islands2->result[index];
|
||||
if (noise2 - noise1off > -0.7){
|
||||
v3s16 p = p0 + v3s16(x1, y1, z1);
|
||||
u32 i = vm->m_area.index(p);
|
||||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
// Cancel if not air
|
||||
if (vm->m_data[i].getContent() != CONTENT_AIR)
|
||||
continue;
|
||||
vm->m_data[i] = n1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapgenIndev::generateSomething() {
|
||||
int float_islands = g_settings->getS16("mgindev_float_islands");
|
||||
if(float_islands) generateFloatIslands(float_islands);
|
||||
}
|
||||
|
|
|
@ -23,30 +23,32 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapgen.h"
|
||||
#include "mapgen_v6.h"
|
||||
|
||||
float farscale(float scale, float z);
|
||||
float farscale(float scale, float x, float z);
|
||||
float farscale(float scale, float x, float y, float z);
|
||||
|
||||
struct NoiseIndevParams : public NoiseParams {
|
||||
float farscale;
|
||||
float farspread;
|
||||
|
||||
NoiseIndevParams(){}
|
||||
NoiseIndevParams(float offset_, float scale_, v3f spread_, int seed_, int octaves_, float persist_, float farscale_)
|
||||
//:NoiseParams(offset_, scale_, spread_, seed_, octaves_, persist_)
|
||||
NoiseIndevParams(float offset_, float scale_, v3f spread_, int seed_, int octaves_, float persist_, float farscale_ = 1, float farspread_ = 1)
|
||||
{
|
||||
//NoiseParams(float offset_, float scale_, v3f spread_, int seed_, int octaves_, float persist_) {
|
||||
offset = offset_;
|
||||
scale = scale_;
|
||||
spread = spread_;
|
||||
seed = seed_;
|
||||
octaves = octaves_;
|
||||
persist = persist_;
|
||||
//}
|
||||
|
||||
farscale = farscale_;
|
||||
farspread = farspread_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#define getNoiseIndevParams(x) getStruct<NoiseIndevParams>((x), "f,f,v3,s32,s32,f,f")
|
||||
#define setNoiseIndevParams(x, y) setStruct((x), "f,f,v3,s32,s32,f,f", (y))
|
||||
#define getNoiseIndevParams(x) getStruct<NoiseIndevParams>((x), "f,f,v3,s32,s32,f,f,f")
|
||||
#define setNoiseIndevParams(x, y) setStruct((x), "f,f,v3,s32,s32,f,f,f", (y))
|
||||
|
||||
class NoiseIndev : public Noise {
|
||||
public:
|
||||
|
@ -59,6 +61,8 @@ class NoiseIndev : public Noise {
|
|||
void transformNoiseMapFarScale(float xx = 0, float yy = 0, float zz = 0);
|
||||
};
|
||||
|
||||
extern NoiseIndevParams nparams_indev_def;
|
||||
/*
|
||||
extern NoiseIndevParams nparams_indev_def_terrain_base;
|
||||
extern NoiseIndevParams nparams_indev_def_terrain_higher;
|
||||
extern NoiseIndevParams nparams_indev_def_steepness;
|
||||
|
@ -66,9 +70,10 @@ extern NoiseIndevParams nparams_indev_def_steepness;
|
|||
//extern NoiseIndevParams nparams_indev_def_trees;
|
||||
extern NoiseIndevParams nparams_indev_def_mud;
|
||||
//extern NoiseIndevParams nparams_indev_def_beach;
|
||||
//extern NoiseIndevParams nparams_indev_def_biome;
|
||||
extern NoiseIndevParams nparams_indev_def_biome;
|
||||
//extern NoiseIndevParams nparams_indev_def_cave;
|
||||
|
||||
extern NoiseIndevParams nparams_indev_def_float_islands;
|
||||
*/
|
||||
|
||||
struct MapgenIndevParams : public MapgenV6Params {
|
||||
NoiseIndevParams *npindev_terrain_base;
|
||||
|
@ -78,21 +83,28 @@ struct MapgenIndevParams : public MapgenV6Params {
|
|||
//NoiseParams *np_trees;
|
||||
NoiseIndevParams *npindev_mud;
|
||||
//NoiseParams *np_beach;
|
||||
//NoiseParams *np_biome;
|
||||
NoiseIndevParams *npindev_biome;
|
||||
//NoiseParams *np_cave;
|
||||
NoiseIndevParams *npindev_float_islands1;
|
||||
NoiseIndevParams *npindev_float_islands2;
|
||||
NoiseIndevParams *npindev_float_islands3;
|
||||
|
||||
MapgenIndevParams() {
|
||||
//freq_desert = 0.45;
|
||||
//freq_beach = 0.15;
|
||||
npindev_terrain_base = &nparams_indev_def_terrain_base;
|
||||
npindev_terrain_higher = &nparams_indev_def_terrain_higher;
|
||||
npindev_steepness = &nparams_indev_def_steepness;
|
||||
npindev_terrain_base = &nparams_indev_def; //&nparams_indev_def_terrain_base;
|
||||
npindev_terrain_higher = &nparams_indev_def; //&nparams_indev_def_terrain_higher;
|
||||
npindev_steepness = &nparams_indev_def; //&nparams_indev_def_steepness;
|
||||
//np_height_select = &nparams_v6_def_height_select;
|
||||
//np_trees = &nparams_v6_def_trees;
|
||||
npindev_mud = &nparams_indev_def_mud;
|
||||
npindev_mud = &nparams_indev_def; //&nparams_indev_def_mud;
|
||||
//np_beach = &nparams_v6_def_beach;
|
||||
//np_biome = &nparams_v6_def_biome;
|
||||
npindev_biome = &nparams_indev_def; //&nparams_indev_def_biome;
|
||||
//np_cave = &nparams_v6_def_cave;
|
||||
npindev_float_islands1 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
npindev_float_islands2 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
npindev_float_islands3 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
|
||||
}
|
||||
|
||||
bool readParams(Settings *settings);
|
||||
|
@ -108,10 +120,13 @@ class MapgenIndev : public MapgenV6 {
|
|||
//NoiseIndev *noise_trees;
|
||||
NoiseIndev *noiseindev_mud;
|
||||
//NoiseIndev *noise_beach;
|
||||
//NoiseIndev *noise_biome;
|
||||
NoiseIndev *noiseindev_biome;
|
||||
//NoiseIndevParams *np_cave;
|
||||
NoiseIndev *noiseindev_float_islands1;
|
||||
NoiseIndev *noiseindev_float_islands2;
|
||||
NoiseIndev *noiseindev_float_islands3;
|
||||
|
||||
MapgenIndev(int mapgenid, MapgenIndevParams *params);
|
||||
MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge);
|
||||
~MapgenIndev();
|
||||
void calculateNoise();
|
||||
|
||||
|
@ -119,11 +134,14 @@ class MapgenIndev : public MapgenV6 {
|
|||
float baseTerrainLevelFromMap(int index);
|
||||
float getMudAmount(int index);
|
||||
void defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave);
|
||||
void generateSomething();
|
||||
|
||||
void generateFloatIslands(int min_y);
|
||||
};
|
||||
|
||||
struct MapgenFactoryIndev : public MapgenFactoryV6 {
|
||||
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
|
||||
return new MapgenIndev(mgid, (MapgenIndevParams *)params);
|
||||
return new MapgenIndev(mgid, (MapgenIndevParams *)params, emerge);
|
||||
};
|
||||
|
||||
MapgenParams *createMapgenParams() {
|
||||
|
@ -131,5 +149,4 @@ struct MapgenFactoryIndev : public MapgenFactoryV6 {
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,9 +64,10 @@ NoiseParams nparams_v6_def_apple_trees =
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params) {
|
||||
MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) {
|
||||
this->generating = false;
|
||||
this->id = mapgenid;
|
||||
this->emerge = emerge;
|
||||
|
||||
this->seed = (int)params->seed;
|
||||
this->water_level = params->water_level;
|
||||
|
@ -422,6 +423,8 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
|
|||
// Generate general ground level to full area
|
||||
stone_surface_max_y = generateGround();
|
||||
|
||||
generateSomething();
|
||||
|
||||
const s16 max_spread_amount = MAP_BLOCKSIZE;
|
||||
// Limit dirt flow area by 1 because mud is flown into neighbors.
|
||||
s16 mudflow_minpos = -max_spread_amount + 1;
|
||||
|
@ -461,6 +464,12 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
|
|||
if (flags & MG_TREES)
|
||||
placeTreesAndJungleGrass();
|
||||
|
||||
// Generate the registered ores
|
||||
for (unsigned int i = 0; i != emerge->ores.size(); i++) {
|
||||
Ore *ore = emerge->ores[i];
|
||||
ore->generate(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
|
||||
// Calculate lighting
|
||||
calcLighting(node_min, node_max);
|
||||
|
||||
|
@ -492,14 +501,13 @@ void MapgenV6::calculateNoise() {
|
|||
noise_height_select->perlinMap2D(
|
||||
x + 0.5 * noise_height_select->np->spread.X,
|
||||
z + 0.5 * noise_height_select->np->spread.Z);
|
||||
}
|
||||
|
||||
if (!(flags & MG_FLAT)) {
|
||||
|
||||
noise_mud->perlinMap2D(
|
||||
x + 0.5 * noise_mud->np->spread.X,
|
||||
z + 0.5 * noise_mud->np->spread.Z);
|
||||
noise_mud->transformNoiseMap();
|
||||
}
|
||||
|
||||
noise_beach->perlinMap2D(
|
||||
x + 0.2 * noise_beach->np->spread.X,
|
||||
z + 0.7 * noise_beach->np->spread.Z);
|
||||
|
|
|
@ -91,6 +91,8 @@ struct MapgenV6Params : public MapgenParams {
|
|||
|
||||
class MapgenV6 : public Mapgen {
|
||||
public:
|
||||
EmergeManager *emerge;
|
||||
|
||||
int ystride;
|
||||
v3s16 csize;
|
||||
u32 flags;
|
||||
|
@ -128,7 +130,7 @@ public:
|
|||
content_t c_desert_sand;
|
||||
content_t c_desert_stone;
|
||||
|
||||
MapgenV6(int mapgenid, MapgenV6Params *params);
|
||||
MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge);
|
||||
~MapgenV6();
|
||||
|
||||
void makeChunk(BlockMakeData *data);
|
||||
|
@ -167,11 +169,12 @@ public:
|
|||
virtual void defineCave(Cave &cave, PseudoRandom ps,
|
||||
v3s16 node_min, bool large_cave);
|
||||
void generateCaves(int max_stone_y);
|
||||
virtual void generateSomething() {}; //for next mapgen
|
||||
};
|
||||
|
||||
struct MapgenFactoryV6 : public MapgenFactory {
|
||||
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
|
||||
return new MapgenV6(mgid, (MapgenV6Params *)params);
|
||||
return new MapgenV6(mgid, (MapgenV6Params *)params, emerge);
|
||||
};
|
||||
|
||||
MapgenParams *createMapgenParams() {
|
||||
|
|
136
src/mapnode.cpp
136
src/mapnode.cpp
|
@ -107,7 +107,7 @@ u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
|||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
if(f.param_type_2 == CPT2_FACEDIR)
|
||||
return getParam2() & 0x03;
|
||||
return getParam2() & 0x1F;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -140,29 +140,131 @@ static std::vector<aabb3f> transformNodeBox(const MapNode &n,
|
|||
{
|
||||
const std::vector<aabb3f> &fixed = nodebox.fixed;
|
||||
int facedir = n.getFaceDir(nodemgr);
|
||||
u8 axisdir = facedir>>2;
|
||||
facedir&=0x03;
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = fixed.begin();
|
||||
i != fixed.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
if(facedir == 1)
|
||||
switch (axisdir)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
box.repair();
|
||||
case 0:
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
}
|
||||
break;
|
||||
case 1: // z+
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(180);
|
||||
box.MaxEdge.rotateXYBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
}
|
||||
break;
|
||||
case 2: //z-
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(180);
|
||||
box.MaxEdge.rotateXYBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
}
|
||||
break;
|
||||
case 3: //x+
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(180);
|
||||
box.MaxEdge.rotateYZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
}
|
||||
break;
|
||||
case 4: //x-
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(180);
|
||||
box.MaxEdge.rotateYZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
box.MinEdge.rotateXYBy(-180);
|
||||
box.MaxEdge.rotateXYBy(-180);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
box.repair();
|
||||
boxes.push_back(box);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,26 +107,31 @@ void NodeBox::deSerialize(std::istream &is)
|
|||
TileDef
|
||||
*/
|
||||
|
||||
void TileDef::serialize(std::ostream &os) const
|
||||
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
if(protocol_version >= 17)
|
||||
writeU8(os, 1);
|
||||
else
|
||||
writeU8(os, 0);
|
||||
os<<serializeString(name);
|
||||
writeU8(os, animation.type);
|
||||
writeU16(os, animation.aspect_w);
|
||||
writeU16(os, animation.aspect_h);
|
||||
writeF1000(os, animation.length);
|
||||
if(protocol_version >= 17)
|
||||
writeU8(os, backface_culling);
|
||||
}
|
||||
|
||||
void TileDef::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
throw SerializationError("unsupported TileDef version");
|
||||
name = deSerializeString(is);
|
||||
animation.type = (TileAnimationType)readU8(is);
|
||||
animation.aspect_w = readU16(is);
|
||||
animation.aspect_h = readU16(is);
|
||||
animation.length = readF1000(is);
|
||||
if(version >= 1)
|
||||
backface_culling = readU8(is);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -235,10 +240,10 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
|
|||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].serialize(os);
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
tiledef_special[i].serialize(os);
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
|
@ -270,9 +275,9 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
|
|||
serializeSimpleSoundSpec(sound_footstep, os);
|
||||
serializeSimpleSoundSpec(sound_dig, os);
|
||||
serializeSimpleSoundSpec(sound_dug, os);
|
||||
writeU8(os, rightclickable);
|
||||
// Stuff below should be moved to correct place in a version that otherwise changes
|
||||
// the protocol version
|
||||
writeU8(os, rightclickable);
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
|
@ -331,12 +336,12 @@ void ContentFeatures::deSerialize(std::istream &is)
|
|||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||
rightclickable = readU8(is);
|
||||
// If you add anything here, insert it primarily inside the try-catch
|
||||
// block to not need to increase the version.
|
||||
try{
|
||||
// Stuff below should be moved to correct place in a version that
|
||||
// otherwise changes the protocol version
|
||||
rightclickable = readU8(is);
|
||||
}catch(SerializationError &e) {};
|
||||
}
|
||||
|
||||
|
@ -809,10 +814,10 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
|||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].serialize(os);
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
tiledef_special[i].serialize(os);
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
|
|
|
@ -119,7 +119,7 @@ struct TileDef
|
|||
animation.length = 1.0;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os) const;
|
||||
void serialize(std::ostream &os, u16 protocol_version) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
|
|
|
@ -32,19 +32,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "clientmap.h"
|
||||
#include "mapnode.h"
|
||||
|
||||
/*
|
||||
Utility
|
||||
*/
|
||||
|
||||
v3f random_v3f(v3f min, v3f max)
|
||||
{
|
||||
return v3f( rand()/(float)RAND_MAX*(max.X-min.X)+min.X,
|
||||
rand()/(float)RAND_MAX*(max.Y-min.Y)+min.Y,
|
||||
rand()/(float)RAND_MAX*(max.Z-min.Z)+min.Z);
|
||||
}
|
||||
|
||||
std::vector<Particle*> all_particles;
|
||||
std::map<u32, ParticleSpawner*> all_particlespawners;
|
||||
|
||||
Particle::Particle(
|
||||
IGameDef *gamedef,
|
||||
scene::ISceneManager* smgr,
|
||||
LocalPlayer *player,
|
||||
s32 id,
|
||||
ClientEnvironment &env,
|
||||
v3f pos,
|
||||
v3f velocity,
|
||||
v3f acceleration,
|
||||
float expirationtime,
|
||||
float size,
|
||||
bool collisiondetection,
|
||||
AtlasPointer ap
|
||||
):
|
||||
scene::ISceneNode(smgr->getRootSceneNode(), smgr, id)
|
||||
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
|
||||
{
|
||||
// Misc
|
||||
m_gamedef = gamedef;
|
||||
|
@ -57,7 +72,6 @@ Particle::Particle(
|
|||
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
m_material.setTexture(0, ap.atlas);
|
||||
m_ap = ap;
|
||||
m_light = 0;
|
||||
|
||||
|
||||
// Particle related
|
||||
|
@ -68,10 +82,20 @@ Particle::Particle(
|
|||
m_time = 0;
|
||||
m_player = player;
|
||||
m_size = size;
|
||||
m_collisiondetection = collisiondetection;
|
||||
|
||||
// Irrlicht stuff (TODO)
|
||||
m_collisionbox = core::aabbox3d<f32>(-size/2,-size/2,-size/2,size/2,size/2,size/2);
|
||||
// Irrlicht stuff
|
||||
m_collisionbox = core::aabbox3d<f32>
|
||||
(-size/2,-size/2,-size/2,size/2,size/2,size/2);
|
||||
this->setAutomaticCulling(scene::EAC_OFF);
|
||||
|
||||
// Init lighting
|
||||
updateLight(env);
|
||||
|
||||
// Init model
|
||||
updateVertices();
|
||||
|
||||
all_particles.push_back(this);
|
||||
}
|
||||
|
||||
Particle::~Particle()
|
||||
|
@ -82,8 +106,10 @@ void Particle::OnRegisterSceneNode()
|
|||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
|
||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
|
||||
SceneManager->registerNodeForRendering
|
||||
(this, scene::ESNRP_TRANSPARENT);
|
||||
SceneManager->registerNodeForRendering
|
||||
(this, scene::ESNRP_SOLID);
|
||||
}
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
|
@ -96,45 +122,45 @@ void Particle::render()
|
|||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
driver->setMaterial(m_material);
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SColor c(255, m_light, m_light, m_light);
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x0(), m_ap.y1()),
|
||||
video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y1()),
|
||||
video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y0()),
|
||||
video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, c ,m_ap.x0(), m_ap.y0()),
|
||||
};
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos.rotateYZBy(m_player->getPitch());
|
||||
vertices[i].Pos.rotateXZBy(m_player->getYaw());
|
||||
m_box.addInternalPoint(vertices[i].Pos);
|
||||
vertices[i].Pos += m_pos*BS;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2, 2,3,0};
|
||||
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||
driver->drawVertexPrimitiveList(m_vertices, 4,
|
||||
indices, 2, video::EVT_STANDARD,
|
||||
scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||
}
|
||||
|
||||
void Particle::step(float dtime, ClientEnvironment &env)
|
||||
{
|
||||
core::aabbox3d<f32> box = m_collisionbox;
|
||||
v3f p_pos = m_pos*BS;
|
||||
v3f p_velocity = m_velocity*BS;
|
||||
v3f p_acceleration = m_acceleration*BS;
|
||||
collisionMoveSimple(&env.getClientMap(), m_gamedef,
|
||||
BS*0.5, box,
|
||||
0, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
m_pos = p_pos/BS;
|
||||
m_velocity = p_velocity/BS;
|
||||
m_acceleration = p_acceleration/BS;
|
||||
m_time += dtime;
|
||||
if (m_collisiondetection)
|
||||
{
|
||||
core::aabbox3d<f32> box = m_collisionbox;
|
||||
v3f p_pos = m_pos*BS;
|
||||
v3f p_velocity = m_velocity*BS;
|
||||
v3f p_acceleration = m_acceleration*BS;
|
||||
collisionMoveSimple(&env, m_gamedef,
|
||||
BS*0.5, box,
|
||||
0, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
m_pos = p_pos/BS;
|
||||
m_velocity = p_velocity/BS;
|
||||
m_acceleration = p_acceleration/BS;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_velocity += m_acceleration * dtime;
|
||||
m_pos += m_velocity * dtime;
|
||||
}
|
||||
|
||||
// Update lighting
|
||||
updateLight(env);
|
||||
|
||||
// Update model
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
void Particle::updateLight(ClientEnvironment &env)
|
||||
{
|
||||
u8 light = 0;
|
||||
try{
|
||||
v3s16 p = v3s16(
|
||||
|
@ -151,11 +177,37 @@ void Particle::step(float dtime, ClientEnvironment &env)
|
|||
m_light = decode_light(light);
|
||||
}
|
||||
|
||||
std::vector<Particle*> all_particles;
|
||||
void Particle::updateVertices()
|
||||
{
|
||||
video::SColor c(255, m_light, m_light, m_light);
|
||||
m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
|
||||
c, m_ap.x0(), m_ap.y1());
|
||||
m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
|
||||
c, m_ap.x1(), m_ap.y1());
|
||||
m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
|
||||
c, m_ap.x1(), m_ap.y0());
|
||||
m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
|
||||
c ,m_ap.x0(), m_ap.y0());
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
|
||||
m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
|
||||
m_box.addInternalPoint(m_vertices[i].Pos);
|
||||
m_vertices[i].Pos += m_pos*BS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helpers
|
||||
*/
|
||||
|
||||
|
||||
void allparticles_step (float dtime, ClientEnvironment &env)
|
||||
{
|
||||
for(std::vector<Particle*>::iterator i = all_particles.begin(); i != all_particles.end();)
|
||||
for(std::vector<Particle*>::iterator i = all_particles.begin();
|
||||
i != all_particles.end();)
|
||||
{
|
||||
if ((*i)->get_expired())
|
||||
{
|
||||
|
@ -171,22 +223,28 @@ void allparticles_step (float dtime, ClientEnvironment &env)
|
|||
}
|
||||
}
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[])
|
||||
{
|
||||
for (u16 j = 0; j < 32; j++) // set the amount of particles here
|
||||
{
|
||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
||||
addNodeParticle(gamedef, smgr, player, env, pos, tiles);
|
||||
}
|
||||
}
|
||||
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env,
|
||||
v3s16 pos, const TileSpec tiles[])
|
||||
{
|
||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
||||
addNodeParticle(gamedef, smgr, player, env, pos, tiles);
|
||||
}
|
||||
|
||||
// add a particle of a node
|
||||
// used by digging and punching particles
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[])
|
||||
{
|
||||
// Texture
|
||||
u8 texid = myrand_range(0,5);
|
||||
|
@ -205,7 +263,10 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
|
|||
ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
|
||||
|
||||
// Physics
|
||||
v3f velocity((rand()%100/50.-1)/1.5, rand()%100/35., (rand()%100/50.-1)/1.5);
|
||||
v3f velocity( (rand()%100/50.-1)/1.5,
|
||||
rand()%100/35.,
|
||||
(rand()%100/50.-1)/1.5);
|
||||
|
||||
v3f acceleration(0,-9,0);
|
||||
v3f particlepos = v3f(
|
||||
(f32)pos.X+rand()%100/200.-0.25,
|
||||
|
@ -213,17 +274,180 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
|
|||
(f32)pos.Z+rand()%100/200.-0.25
|
||||
);
|
||||
|
||||
Particle *particle = new Particle(
|
||||
new Particle(
|
||||
gamedef,
|
||||
smgr,
|
||||
player,
|
||||
0,
|
||||
env,
|
||||
particlepos,
|
||||
velocity,
|
||||
acceleration,
|
||||
rand()%100/100., // expiration time
|
||||
visual_size,
|
||||
true,
|
||||
ap);
|
||||
|
||||
all_particles.push_back(particle);
|
||||
}
|
||||
|
||||
/*
|
||||
ParticleSpawner
|
||||
*/
|
||||
|
||||
ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, LocalPlayer *player,
|
||||
u16 amount, float time,
|
||||
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime, float minsize, float maxsize,
|
||||
bool collisiondetection, AtlasPointer ap, u32 id)
|
||||
{
|
||||
m_gamedef = gamedef;
|
||||
m_smgr = smgr;
|
||||
m_player = player;
|
||||
m_amount = amount;
|
||||
m_spawntime = time;
|
||||
m_minpos = minpos;
|
||||
m_maxpos = maxpos;
|
||||
m_minvel = minvel;
|
||||
m_maxvel = maxvel;
|
||||
m_minacc = minacc;
|
||||
m_maxacc = maxacc;
|
||||
m_minexptime = minexptime;
|
||||
m_maxexptime = maxexptime;
|
||||
m_minsize = minsize;
|
||||
m_maxsize = maxsize;
|
||||
m_collisiondetection = collisiondetection;
|
||||
m_ap = ap;
|
||||
m_time = 0;
|
||||
|
||||
for (u16 i = 0; i<=m_amount; i++)
|
||||
{
|
||||
float spawntime = (float)rand()/(float)RAND_MAX*m_spawntime;
|
||||
m_spawntimes.push_back(spawntime);
|
||||
}
|
||||
|
||||
all_particlespawners.insert(std::pair<u32, ParticleSpawner*>(id, this));
|
||||
}
|
||||
|
||||
ParticleSpawner::~ParticleSpawner() {}
|
||||
|
||||
void ParticleSpawner::step(float dtime, ClientEnvironment &env)
|
||||
{
|
||||
m_time += dtime;
|
||||
|
||||
if (m_spawntime != 0) // Spawner exists for a predefined timespan
|
||||
{
|
||||
for(std::vector<float>::iterator i = m_spawntimes.begin();
|
||||
i != m_spawntimes.end();)
|
||||
{
|
||||
if ((*i) <= m_time && m_amount > 0)
|
||||
{
|
||||
m_amount--;
|
||||
|
||||
v3f pos = random_v3f(m_minpos, m_maxpos);
|
||||
v3f vel = random_v3f(m_minvel, m_maxvel);
|
||||
v3f acc = random_v3f(m_minacc, m_maxacc);
|
||||
float exptime = rand()/(float)RAND_MAX
|
||||
*(m_maxexptime-m_minexptime)
|
||||
+m_minexptime;
|
||||
float size = rand()/(float)RAND_MAX
|
||||
*(m_maxsize-m_minsize)
|
||||
+m_minsize;
|
||||
|
||||
new Particle(
|
||||
m_gamedef,
|
||||
m_smgr,
|
||||
m_player,
|
||||
env,
|
||||
pos,
|
||||
vel,
|
||||
acc,
|
||||
exptime,
|
||||
size,
|
||||
m_collisiondetection,
|
||||
m_ap);
|
||||
m_spawntimes.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Spawner exists for an infinity timespan, spawn on a per-second base
|
||||
{
|
||||
for (int i = 0; i <= m_amount; i++)
|
||||
{
|
||||
if (rand()/(float)RAND_MAX < dtime)
|
||||
{
|
||||
v3f pos = random_v3f(m_minpos, m_maxpos);
|
||||
v3f vel = random_v3f(m_minvel, m_maxvel);
|
||||
v3f acc = random_v3f(m_minacc, m_maxacc);
|
||||
float exptime = rand()/(float)RAND_MAX
|
||||
*(m_maxexptime-m_minexptime)
|
||||
+m_minexptime;
|
||||
float size = rand()/(float)RAND_MAX
|
||||
*(m_maxsize-m_minsize)
|
||||
+m_minsize;
|
||||
|
||||
new Particle(
|
||||
m_gamedef,
|
||||
m_smgr,
|
||||
m_player,
|
||||
env,
|
||||
pos,
|
||||
vel,
|
||||
acc,
|
||||
exptime,
|
||||
size,
|
||||
m_collisiondetection,
|
||||
m_ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void allparticlespawners_step (float dtime, ClientEnvironment &env)
|
||||
{
|
||||
for(std::map<u32, ParticleSpawner*>::iterator i =
|
||||
all_particlespawners.begin();
|
||||
i != all_particlespawners.end();)
|
||||
{
|
||||
if (i->second->get_expired())
|
||||
{
|
||||
delete i->second;
|
||||
all_particlespawners.erase(i++);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->second->step(dtime, env);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete_particlespawner (u32 id)
|
||||
{
|
||||
if (all_particlespawners.find(id) != all_particlespawners.end())
|
||||
{
|
||||
delete all_particlespawners.find(id)->second;
|
||||
all_particlespawners.erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_particles ()
|
||||
{
|
||||
for(std::map<u32, ParticleSpawner*>::iterator i =
|
||||
all_particlespawners.begin();
|
||||
i != all_particlespawners.end();)
|
||||
{
|
||||
delete i->second;
|
||||
all_particlespawners.erase(i++);
|
||||
}
|
||||
|
||||
for(std::vector<Particle*>::iterator i =
|
||||
all_particles.begin();
|
||||
i != all_particles.end();)
|
||||
{
|
||||
(*i)->remove();
|
||||
delete *i;
|
||||
all_particles.erase(i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,13 @@ class Particle : public scene::ISceneNode
|
|||
IGameDef* gamedef,
|
||||
scene::ISceneManager* mgr,
|
||||
LocalPlayer *player,
|
||||
s32 id,
|
||||
ClientEnvironment &env,
|
||||
v3f pos,
|
||||
v3f velocity,
|
||||
v3f acceleration,
|
||||
float expirationtime,
|
||||
float size,
|
||||
bool collisiondetection,
|
||||
AtlasPointer texture
|
||||
);
|
||||
~Particle();
|
||||
|
@ -69,6 +70,10 @@ class Particle : public scene::ISceneNode
|
|||
{ return m_expiration < m_time; }
|
||||
|
||||
private:
|
||||
void updateLight(ClientEnvironment &env);
|
||||
void updateVertices();
|
||||
|
||||
video::S3DVertex m_vertices[4];
|
||||
float m_time;
|
||||
float m_expiration;
|
||||
|
||||
|
@ -87,12 +92,71 @@ private:
|
|||
float m_size;
|
||||
AtlasPointer m_ap;
|
||||
u8 m_light;
|
||||
bool m_collisiondetection;
|
||||
};
|
||||
|
||||
class ParticleSpawner
|
||||
{
|
||||
public:
|
||||
ParticleSpawner(IGameDef* gamedef,
|
||||
scene::ISceneManager *smgr,
|
||||
LocalPlayer *player,
|
||||
u16 amount,
|
||||
float time,
|
||||
v3f minp, v3f maxp,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection,
|
||||
AtlasPointer ap,
|
||||
u32 id);
|
||||
|
||||
~ParticleSpawner();
|
||||
|
||||
void step(float dtime, ClientEnvironment &env);
|
||||
|
||||
bool get_expired ()
|
||||
{ return (m_amount <= 0) && m_spawntime != 0; }
|
||||
|
||||
private:
|
||||
float m_time;
|
||||
IGameDef *m_gamedef;
|
||||
scene::ISceneManager *m_smgr;
|
||||
LocalPlayer *m_player;
|
||||
u16 m_amount;
|
||||
float m_spawntime;
|
||||
v3f m_minpos;
|
||||
v3f m_maxpos;
|
||||
v3f m_minvel;
|
||||
v3f m_maxvel;
|
||||
v3f m_minacc;
|
||||
v3f m_maxacc;
|
||||
float m_minexptime;
|
||||
float m_maxexptime;
|
||||
float m_minsize;
|
||||
float m_maxsize;
|
||||
AtlasPointer m_ap;
|
||||
std::vector<float> m_spawntimes;
|
||||
bool m_collisiondetection;
|
||||
};
|
||||
|
||||
void allparticles_step (float dtime, ClientEnvironment &env);
|
||||
void allparticlespawners_step (float dtime, ClientEnvironment &env);
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void delete_particlespawner (u32 id);
|
||||
void clear_particles ();
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
else{
|
||||
/* No add shall have been used */
|
||||
assert(n->second != -2);
|
||||
n->second = std::max(n->second, 0) + 1;
|
||||
n->second = (std::max)(n->second, 0) + 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
#include "settings.h" // For accessing g_settings
|
||||
#include "main.h" // For g_settings
|
||||
#include "biome.h"
|
||||
#include "emerge.h"
|
||||
#include "script.h"
|
||||
#include "rollback.h"
|
||||
|
||||
|
@ -44,6 +45,7 @@ extern "C" {
|
|||
#include "scriptapi_item.h"
|
||||
#include "scriptapi_content.h"
|
||||
#include "scriptapi_craft.h"
|
||||
#include "scriptapi_particles.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Mod related */
|
||||
|
@ -241,6 +243,14 @@ struct EnumString es_BiomeTerrainType[] =
|
|||
{0, NULL},
|
||||
};
|
||||
|
||||
struct EnumString es_OreType[] =
|
||||
{
|
||||
{ORE_SCATTER, "scatter"},
|
||||
{ORE_SHEET, "sheet"},
|
||||
{ORE_CLAYLIKE, "claylike"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Parameters */
|
||||
/*****************************************************************************/
|
||||
|
@ -611,8 +621,6 @@ static int l_register_biome_groups(lua_State *L)
|
|||
{
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int index = 1;
|
||||
if (!lua_istable(L, index))
|
||||
throw LuaError(L, "register_biome_groups: parameter is not a table");
|
||||
|
||||
BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
|
||||
if (!bmgr) {
|
||||
|
@ -685,6 +693,52 @@ static int l_register_biome(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
static int l_register_ore(lua_State *L)
|
||||
{
|
||||
int index = 1;
|
||||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
|
||||
EmergeManager *emerge = get_server(L)->getEmergeManager();
|
||||
|
||||
enum OreType oretype = (OreType)getenumfield(L, index,
|
||||
"ore_type", es_OreType, ORE_SCATTER);
|
||||
Ore *ore = createOre(oretype);
|
||||
if (!ore) {
|
||||
errorstream << "register_ore: ore_type "
|
||||
<< oretype << " not implemented";
|
||||
return 0;
|
||||
}
|
||||
|
||||
ore->ore_name = getstringfield_default(L, index, "ore", "");
|
||||
ore->wherein_name = getstringfield_default(L, index, "wherein", "");
|
||||
ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
|
||||
ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
|
||||
ore->clust_size = getintfield_default(L, index, "clust_size", 0);
|
||||
ore->height_min = getintfield_default(L, index, "height_min", 0);
|
||||
ore->height_max = getintfield_default(L, index, "height_max", 0);
|
||||
ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.);
|
||||
|
||||
lua_getfield(L, index, "noise_params");
|
||||
ore->np = read_noiseparams(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
ore->noise = NULL;
|
||||
|
||||
if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
|
||||
errorstream << "register_ore: clust_scarcity and clust_num_ores"
|
||||
"must be greater than 0";
|
||||
delete ore;
|
||||
return 0;
|
||||
}
|
||||
|
||||
emerge->ores.push_back(ore);
|
||||
|
||||
verbosestream << "register_ore: ore '" << ore->ore_name
|
||||
<< "' registered" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setting_set(name, value)
|
||||
static int l_setting_set(lua_State *L)
|
||||
|
@ -1059,6 +1113,7 @@ static const struct luaL_Reg minetest_f [] = {
|
|||
{"register_craft", l_register_craft},
|
||||
{"register_biome", l_register_biome},
|
||||
{"register_biome_groups", l_register_biome_groups},
|
||||
{"register_ore", l_register_ore},
|
||||
{"setting_set", l_setting_set},
|
||||
{"setting_get", l_setting_get},
|
||||
{"setting_getbool", l_setting_getbool},
|
||||
|
@ -1089,6 +1144,9 @@ static const struct luaL_Reg minetest_f [] = {
|
|||
{"get_all_craft_recipes", l_get_all_craft_recipes},
|
||||
{"rollback_get_last_node_actor", l_rollback_get_last_node_actor},
|
||||
{"rollback_revert_actions_by", l_rollback_revert_actions_by},
|
||||
{"add_particle", l_add_particle},
|
||||
{"add_particlespawner", l_add_particlespawner},
|
||||
{"delete_particlespawner", l_delete_particlespawner},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -269,6 +269,7 @@ NoiseParams *read_noiseparams(lua_State *L, int index)
|
|||
np->scale = getfloatfield_default(L, index, "scale", 0.0);
|
||||
lua_getfield(L, index, "spread");
|
||||
np->spread = read_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
np->seed = getintfield_default(L, index, "seed", 0);
|
||||
np->octaves = getintfield_default(L, index, "octaves", 0);
|
||||
np->persist = getfloatfield_default(L, index, "persist", 0.0);
|
||||
|
@ -276,6 +277,7 @@ NoiseParams *read_noiseparams(lua_State *L, int index)
|
|||
return np;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
LuaPseudoRandom
|
||||
*/
|
||||
|
|
241
src/server.cpp
241
src/server.cpp
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "server.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include "clientserver.h"
|
||||
#include "map.h"
|
||||
#include "jmutexautolock.h"
|
||||
|
@ -652,7 +653,6 @@ Server::Server(
|
|||
m_craftdef(createCraftDefManager()),
|
||||
m_event(new EventManager()),
|
||||
m_thread(this),
|
||||
//m_emergethread(this),
|
||||
m_time_of_day_send_timer(0),
|
||||
m_uptime(0),
|
||||
m_shutdown_requested(false),
|
||||
|
@ -697,7 +697,10 @@ Server::Server(
|
|||
|
||||
// Create biome definition manager
|
||||
m_biomedef = new BiomeDefManager(this);
|
||||
|
||||
|
||||
// Create emerge manager
|
||||
m_emerge = new EmergeManager(this, m_biomedef);
|
||||
|
||||
// Create rollback manager
|
||||
std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
|
||||
m_rollback = createRollbackManager(rollback_path, this);
|
||||
|
@ -813,9 +816,6 @@ Server::Server(
|
|||
// Add default biomes after nodedef had its aliases added
|
||||
m_biomedef->addDefaultBiomes();
|
||||
|
||||
// Create emerge manager
|
||||
m_emerge = new EmergeManager(this, m_biomedef);
|
||||
|
||||
// Initialize Environment
|
||||
ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
|
||||
m_env = new ServerEnvironment(servermap, m_lua, this, this);
|
||||
|
@ -3474,6 +3474,132 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, co
|
|||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
// Spawns a particle on peer with peer_id
|
||||
void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
writeU16(os, TOCLIENT_SPAWN_PARTICLE);
|
||||
writeV3F1000(os, pos);
|
||||
writeV3F1000(os, velocity);
|
||||
writeV3F1000(os, acceleration);
|
||||
writeF1000(os, expirationtime);
|
||||
writeF1000(os, size);
|
||||
writeU8(os, collisiondetection);
|
||||
os<<serializeLongString(texture);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
// Spawns a particle on all peers
|
||||
void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
|
||||
{
|
||||
for(std::map<u16, RemoteClient*>::iterator
|
||||
i = m_clients.begin();
|
||||
i != m_clients.end(); i++)
|
||||
{
|
||||
// Get client and check that it is valid
|
||||
RemoteClient *client = i->second;
|
||||
assert(client->peer_id == i->first);
|
||||
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||
continue;
|
||||
|
||||
SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
|
||||
expirationtime, size, collisiondetection, texture);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a ParticleSpawner on peer with peer_id
|
||||
void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
|
||||
float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
|
||||
|
||||
writeU16(os, amount);
|
||||
writeF1000(os, spawntime);
|
||||
writeV3F1000(os, minpos);
|
||||
writeV3F1000(os, maxpos);
|
||||
writeV3F1000(os, minvel);
|
||||
writeV3F1000(os, maxvel);
|
||||
writeV3F1000(os, minacc);
|
||||
writeV3F1000(os, maxacc);
|
||||
writeF1000(os, minexptime);
|
||||
writeF1000(os, maxexptime);
|
||||
writeF1000(os, minsize);
|
||||
writeF1000(os, maxsize);
|
||||
writeU8(os, collisiondetection);
|
||||
os<<serializeLongString(texture);
|
||||
writeU32(os, id);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
// Adds a ParticleSpawner on all peers
|
||||
void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
|
||||
float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
|
||||
{
|
||||
for(std::map<u16, RemoteClient*>::iterator
|
||||
i = m_clients.begin();
|
||||
i != m_clients.end(); i++)
|
||||
{
|
||||
// Get client and check that it is valid
|
||||
RemoteClient *client = i->second;
|
||||
assert(client->peer_id == i->first);
|
||||
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||
continue;
|
||||
|
||||
SendAddParticleSpawner(client->peer_id, amount, spawntime,
|
||||
minpos, maxpos, minvel, maxvel, minacc, maxacc,
|
||||
minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
|
||||
|
||||
writeU16(os, id);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendDeleteParticleSpawnerAll(u32 id)
|
||||
{
|
||||
for(std::map<u16, RemoteClient*>::iterator
|
||||
i = m_clients.begin();
|
||||
i != m_clients.end(); i++)
|
||||
{
|
||||
// Get client and check that it is valid
|
||||
RemoteClient *client = i->second;
|
||||
assert(client->peer_id == i->first);
|
||||
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||
continue;
|
||||
|
||||
SendDeleteParticleSpawner(client->peer_id, id);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::BroadcastChatMessage(const std::wstring &message)
|
||||
{
|
||||
for(std::map<u16, RemoteClient*>::iterator
|
||||
|
@ -4432,6 +4558,111 @@ void Server::notifyPlayers(const std::wstring msg)
|
|||
BroadcastChatMessage(msg);
|
||||
}
|
||||
|
||||
void Server::spawnParticle(const char *playername, v3f pos,
|
||||
v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size, bool
|
||||
collisiondetection, std::string texture)
|
||||
{
|
||||
Player *player = m_env->getPlayer(playername);
|
||||
if(!player)
|
||||
return;
|
||||
SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
|
||||
expirationtime, size, collisiondetection, texture);
|
||||
}
|
||||
|
||||
void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size,
|
||||
bool collisiondetection, std::string texture)
|
||||
{
|
||||
SendSpawnParticleAll(pos, velocity, acceleration,
|
||||
expirationtime, size, collisiondetection, texture);
|
||||
}
|
||||
|
||||
u32 Server::addParticleSpawner(const char *playername,
|
||||
u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture)
|
||||
{
|
||||
Player *player = m_env->getPlayer(playername);
|
||||
if(!player)
|
||||
return -1;
|
||||
|
||||
u32 id = 0;
|
||||
for(;;) // look for unused particlespawner id
|
||||
{
|
||||
id++;
|
||||
if (std::find(m_particlespawner_ids.begin(),
|
||||
m_particlespawner_ids.end(), id)
|
||||
== m_particlespawner_ids.end())
|
||||
{
|
||||
m_particlespawner_ids.push_back(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SendAddParticleSpawner(player->peer_id, amount, spawntime,
|
||||
minpos, maxpos, minvel, maxvel, minacc, maxacc,
|
||||
minexptime, maxexptime, minsize, maxsize,
|
||||
collisiondetection, texture, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture)
|
||||
{
|
||||
u32 id = 0;
|
||||
for(;;) // look for unused particlespawner id
|
||||
{
|
||||
id++;
|
||||
if (std::find(m_particlespawner_ids.begin(),
|
||||
m_particlespawner_ids.end(), id)
|
||||
== m_particlespawner_ids.end())
|
||||
{
|
||||
m_particlespawner_ids.push_back(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SendAddParticleSpawnerAll(amount, spawntime,
|
||||
minpos, maxpos, minvel, maxvel, minacc, maxacc,
|
||||
minexptime, maxexptime, minsize, maxsize,
|
||||
collisiondetection, texture, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void Server::deleteParticleSpawner(const char *playername, u32 id)
|
||||
{
|
||||
Player *player = m_env->getPlayer(playername);
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
m_particlespawner_ids.erase(
|
||||
std::remove(m_particlespawner_ids.begin(),
|
||||
m_particlespawner_ids.end(), id),
|
||||
m_particlespawner_ids.end());
|
||||
SendDeleteParticleSpawner(player->peer_id, id);
|
||||
}
|
||||
|
||||
void Server::deleteParticleSpawnerAll(u32 id)
|
||||
{
|
||||
m_particlespawner_ids.erase(
|
||||
std::remove(m_particlespawner_ids.begin(),
|
||||
m_particlespawner_ids.end(), id),
|
||||
m_particlespawner_ids.end());
|
||||
SendDeleteParticleSpawnerAll(id);
|
||||
}
|
||||
|
||||
void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
|
||||
{
|
||||
m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, blockpos, allow_generate);
|
||||
|
|
69
src/server.h
69
src/server.h
|
@ -456,6 +456,35 @@ public:
|
|||
// Envlock and conlock should be locked when calling this
|
||||
void notifyPlayer(const char *name, const std::wstring msg);
|
||||
void notifyPlayers(const std::wstring msg);
|
||||
void spawnParticle(const char *playername,
|
||||
v3f pos, v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
void spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
u32 addParticleSpawner(const char *playername,
|
||||
u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
u32 addParticleSpawnerAll(u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
void deleteParticleSpawner(const char *playername, u32 id);
|
||||
void deleteParticleSpawnerAll(u32 id);
|
||||
|
||||
|
||||
void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
|
||||
|
||||
|
@ -574,6 +603,41 @@ private:
|
|||
void sendDetachedInventoryToAll(const std::string &name);
|
||||
void sendDetachedInventories(u16 peer_id);
|
||||
|
||||
// Adds a ParticleSpawner on peer with peer_id
|
||||
void SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture, u32 id);
|
||||
|
||||
// Adds a ParticleSpawner on all peers
|
||||
void SendAddParticleSpawnerAll(u16 amount, float spawntime,
|
||||
v3f minpos, v3f maxpos,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection, std::string texture, u32 id);
|
||||
|
||||
// Deletes ParticleSpawner on a single client
|
||||
void SendDeleteParticleSpawner(u16 peer_id, u32 id);
|
||||
|
||||
// Deletes ParticleSpawner on all clients
|
||||
void SendDeleteParticleSpawnerAll(u32 id);
|
||||
|
||||
// Spawns particle on single client
|
||||
void SendSpawnParticle(u16 peer_id,
|
||||
v3f pos, v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
// Spawns particle on all clients
|
||||
void SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
|
||||
float expirationtime, float size,
|
||||
bool collisiondetection, std::string texture);
|
||||
|
||||
/*
|
||||
Something random
|
||||
*/
|
||||
|
@ -790,6 +854,11 @@ private:
|
|||
*/
|
||||
// key = name
|
||||
std::map<std::string, Inventory*> m_detached_inventories;
|
||||
|
||||
/*
|
||||
Particles
|
||||
*/
|
||||
std::vector<u32> m_particlespawner_ids;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -205,7 +205,8 @@ struct TileSpec
|
|||
texture == other.texture &&
|
||||
alpha == other.alpha &&
|
||||
material_type == other.material_type &&
|
||||
material_flags == other.material_flags
|
||||
material_flags == other.material_flags &&
|
||||
rotation == other.rotation
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -264,6 +265,7 @@ struct TileSpec
|
|||
// Animation parameters
|
||||
u8 animation_frame_count;
|
||||
u16 animation_frame_length_ms;
|
||||
u8 rotation;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue