mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Merge branch 'upstream/master'
Conflicts: data/oerkki1.png src/client.cpp
This commit is contained in:
commit
3560f0de08
@ -9,7 +9,12 @@ src/jthread/CMakeFiles/*
|
|||||||
src/jthread/Makefile
|
src/jthread/Makefile
|
||||||
src/jthread/cmake_config.h
|
src/jthread/cmake_config.h
|
||||||
src/jthread/cmake_install.cmake
|
src/jthread/cmake_install.cmake
|
||||||
|
src/.*.swp
|
||||||
|
src/sqlite/libsqlite3.a
|
||||||
|
src/session.vim
|
||||||
|
util/uloste.png
|
||||||
minetest.conf
|
minetest.conf
|
||||||
|
debug.txt
|
||||||
bin/
|
bin/
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CPackConfig.cmake
|
CPackConfig.cmake
|
||||||
|
@ -9,7 +9,7 @@ project(minetest)
|
|||||||
|
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 2)
|
set(VERSION_MINOR 2)
|
||||||
set(VERSION_PATCH 20110618_0_dev)
|
set(VERSION_PATCH 20110704_0)
|
||||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
|
|
||||||
# Configuration options
|
# Configuration options
|
||||||
|
BIN
data/oerkki1_damaged.png
Normal file
BIN
data/oerkki1_damaged.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 341 B |
BIN
data/unknown_block.png
Normal file
BIN
data/unknown_block.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 582 B |
@ -3,6 +3,11 @@ Minetest-c55 changelog
|
|||||||
This should contain all the major changes.
|
This should contain all the major changes.
|
||||||
For minor stuff, refer to the commit log of the repository.
|
For minor stuff, refer to the commit log of the repository.
|
||||||
|
|
||||||
|
2011-07-04:
|
||||||
|
- Many small fixes
|
||||||
|
- Code reorganizing to aid further development
|
||||||
|
- Renewed map generator
|
||||||
|
|
||||||
2011-06-02:
|
2011-06-02:
|
||||||
- Password crash on windows fixed
|
- Password crash on windows fixed
|
||||||
- Optimized server CPU usage a lot
|
- Optimized server CPU usage a lot
|
||||||
|
@ -9,25 +9,28 @@
|
|||||||
#
|
#
|
||||||
# Further documentation:
|
# Further documentation:
|
||||||
# http://celeron.55.lt/~celeron55/minetest/wiki/doku.php
|
# http://celeron.55.lt/~celeron55/minetest/wiki/doku.php
|
||||||
|
#
|
||||||
|
# NOTE: This file might not be up-to-date, refer to the
|
||||||
|
# defaultsettings.cpp file for an up-to-date list:
|
||||||
|
# https://bitbucket.org/celeron55/minetest/src/tip/src/defaultsettings.cpp
|
||||||
|
#
|
||||||
|
# A vim command to convert most of defaultsettings.cpp to conf file format:
|
||||||
|
# :'<,'>s/\tg_settings\.setDefault("\([^"]*\)", "\([^"]*\)");.*/#\1 = \2/g
|
||||||
|
|
||||||
#
|
#
|
||||||
# Client side stuff
|
# Client and server
|
||||||
#
|
#
|
||||||
|
|
||||||
# Initial window size
|
# Network port (UDP)
|
||||||
#screenW = 800
|
#port =
|
||||||
#screenH = 600
|
# Name of player; on a server this is the main admin
|
||||||
|
|
||||||
# Port to connect to and to bind a server at
|
|
||||||
#port = 30000
|
|
||||||
|
|
||||||
# Address to connect to (blank = start local server)
|
|
||||||
#address =
|
|
||||||
|
|
||||||
# Name of player. On server, this is the default admin.
|
|
||||||
#name =
|
#name =
|
||||||
|
|
||||||
# Key configuration.
|
#
|
||||||
|
# Client stuff
|
||||||
|
#
|
||||||
|
|
||||||
|
# Key mappings
|
||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||||
#keymap_forward = KEY_KEY_W
|
#keymap_forward = KEY_KEY_W
|
||||||
#keymap_backward = KEY_KEY_S
|
#keymap_backward = KEY_KEY_S
|
||||||
@ -38,108 +41,99 @@
|
|||||||
#keymap_inventory = KEY_KEY_I
|
#keymap_inventory = KEY_KEY_I
|
||||||
#keymap_chat = KEY_KEY_T
|
#keymap_chat = KEY_KEY_T
|
||||||
#keymap_rangeselect = KEY_KEY_R
|
#keymap_rangeselect = KEY_KEY_R
|
||||||
# Some (temporary) keys for debugging features
|
#keymap_freemove = KEY_KEY_K
|
||||||
|
#keymap_fastmove = KEY_KEY_J
|
||||||
|
#keymap_frametime_graph = KEY_F1
|
||||||
|
#keymap_screenshot = KEY_F12
|
||||||
|
# Some (temporary) keys for debugging
|
||||||
#keymap_special1 = KEY_KEY_E
|
#keymap_special1 = KEY_KEY_E
|
||||||
#keymap_print_debug_stacks = KEY_KEY_P
|
#keymap_print_debug_stacks = KEY_KEY_P
|
||||||
|
|
||||||
#invert_mouse = false
|
|
||||||
|
|
||||||
# The desired FPS
|
# The desired FPS
|
||||||
#wanted_fps = 30
|
#wanted_fps = 30
|
||||||
|
|
||||||
# If FPS would go higher than this, limit it by sleeping
|
# If FPS would go higher than this, limit it by sleeping
|
||||||
# (to not waste CPU power for no benefit)
|
# (to not waste CPU power for no benefit)
|
||||||
#fps_max = 60
|
#fps_max = 60
|
||||||
|
|
||||||
# The allowed adjustment range for the automatic rendering range adjustment
|
# The allowed adjustment range for the automatic rendering range adjustment
|
||||||
#viewing_range_nodes_max = 300
|
#viewing_range_nodes_max = 300
|
||||||
#viewing_range_nodes_min = 35
|
#viewing_range_nodes_min = 25
|
||||||
|
# Initial window size
|
||||||
|
screenW# = 800
|
||||||
|
screenH# = 600
|
||||||
|
# Address to connect to (#blank = start local server)
|
||||||
|
#address =
|
||||||
|
# Enable random user input, for testing
|
||||||
|
#random_input = false
|
||||||
|
# Timeout for client to remove unused map data from memory
|
||||||
|
#client_unload_unused_data_timeout = 600
|
||||||
# Whether to fog out the end of the visible area
|
# Whether to fog out the end of the visible area
|
||||||
#enable_fog = true
|
#enable_fog = true
|
||||||
|
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
||||||
# Enable/disable clouds
|
#new_style_water = false
|
||||||
#enable_clouds = true
|
|
||||||
|
|
||||||
# Experimental
|
|
||||||
#enable_farmesh = false
|
|
||||||
|
|
||||||
# Enable a bit lower water surface; disable for speed
|
|
||||||
#new_style_water = true
|
|
||||||
|
|
||||||
# Enable nice leaves; disable for speed
|
# Enable nice leaves; disable for speed
|
||||||
#new_style_leaves = true
|
#new_style_leaves = true
|
||||||
|
|
||||||
# Enable smooth lighting with simple ambient occlusion;
|
# Enable smooth lighting with simple ambient occlusion;
|
||||||
# disable for speed or for different looks.
|
# disable for speed or for different looks.
|
||||||
#smooth_lighting = true
|
#smooth_lighting = true
|
||||||
|
|
||||||
# Whether to draw a frametime graph (for debugging frametime)
|
# Whether to draw a frametime graph (for debugging frametime)
|
||||||
#frametime_graph = false
|
#frametime_graph = false
|
||||||
|
|
||||||
# Enable combining mainly used textures to a bigger one for improved speed
|
# Enable combining mainly used textures to a bigger one for improved speed
|
||||||
# disable if it causes graphics glitches.
|
# disable if it causes graphics glitches.
|
||||||
#enable_texture_atlas = true
|
#enable_texture_atlas = true
|
||||||
|
|
||||||
# Path to texture directory. All textures are first searched from here.
|
# Path to texture directory. All textures are first searched from here.
|
||||||
#texture_path =
|
#texture_path =
|
||||||
|
|
||||||
# Video back-end.
|
# Video back-end.
|
||||||
# Possible values: null, software, burningsvideo, direct3d8, direct3d9, opengl
|
# Possible values: null, software, burningsvideo, direct3d8, direct3d9, opengl
|
||||||
#video_driver = opengl
|
#video_driver = opengl
|
||||||
|
# Unobstructed movement without physics, downwards key is keymap_special1
|
||||||
# Enable random user input, for testing
|
#free_move = false
|
||||||
#random_input = false
|
# Continuous forward movement (for testing)
|
||||||
|
#continuous_forward = false
|
||||||
# Timeout for client to remove unused map data from memory
|
# Fast movement (keymap_special1)
|
||||||
#client_delete_unused_sectors_timeout = 1200
|
#fast_move = false
|
||||||
|
# Invert mouse
|
||||||
|
#invert_mouse = false
|
||||||
|
# FarMesh thingy
|
||||||
|
#enable_farmesh = false
|
||||||
|
# Enable/disable clouds
|
||||||
|
#enable_clouds = true
|
||||||
|
# Don't draw stone (for testing)
|
||||||
|
#invisible_stone = false
|
||||||
|
# Path for screenshots
|
||||||
|
#screenshot_path = .
|
||||||
|
|
||||||
#
|
#
|
||||||
# Server side stuff
|
# Server stuff
|
||||||
#
|
#
|
||||||
|
|
||||||
# Map directory (everything in the world is stored here)
|
# Map directory (everything in the world is stored here)
|
||||||
#map-dir = /home/palle/custom_map
|
#map-#dir = /custom/map
|
||||||
|
# Set to true to enable experimental features or stuff that is tested
|
||||||
|
# (varies from version to version, usually not useful at all)
|
||||||
|
#enable_experimental = false
|
||||||
# Set to true to enable creative mode (unlimited inventory)
|
# Set to true to enable creative mode (unlimited inventory)
|
||||||
#creative_mode = false
|
#creative_mode = false
|
||||||
|
|
||||||
#enable_damage = false
|
#enable_damage = false
|
||||||
|
|
||||||
#default_password =
|
|
||||||
|
|
||||||
# Available privileges: build, teleport, settime, privs, shout
|
|
||||||
#default_privs = build, shout
|
|
||||||
|
|
||||||
# Gives some stuff to players at the beginning
|
# Gives some stuff to players at the beginning
|
||||||
#give_initial_stuff = false
|
#give_initial_stuff = false
|
||||||
|
#default_password =
|
||||||
# Set to true to enable experimental features
|
# Available privileges: build, teleport, settime, privs, shout
|
||||||
# (varies from version to version, see wiki)
|
#default_privs = build, shout
|
||||||
#enable_experimental = false
|
# Profiler data print interval. #0 = disable.
|
||||||
|
#profiler_print_interval = 0
|
||||||
# Profiler data print interval. 0 = disable.
|
#enable_mapgen_debug_info = false
|
||||||
#profiler_print_interval = 10
|
|
||||||
|
|
||||||
# Player and object positions are sent at intervals specified by this
|
# Player and object positions are sent at intervals specified by this
|
||||||
#objectdata_inverval = 0.2
|
#objectdata_interval = 0.2
|
||||||
|
|
||||||
#active_object_range = 2
|
#active_object_range = 2
|
||||||
|
#max_simultaneous_block_sends_per_client = 2
|
||||||
#max_simultaneous_block_sends_per_client = 1
|
#max_simultaneous_block_sends_server_total = 8
|
||||||
#max_simultaneous_block_sends_server_total = 4
|
#max_block_send_distance = 8
|
||||||
|
#max_block_generate_distance = 8
|
||||||
#max_block_send_distance = 5
|
#time_send_interval = 20
|
||||||
#max_block_generate_distance = 4
|
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||||
|
|
||||||
# 20 min/day
|
|
||||||
#time_speed = 72
|
#time_speed = 72
|
||||||
# 4 min/day
|
#server_unload_unused_data_timeout = 60
|
||||||
#time_speed = 360
|
|
||||||
# 1 min/day
|
|
||||||
#time_speed = 1440
|
|
||||||
|
|
||||||
#time_send_interval = 5
|
|
||||||
#server_unload_unused_sectors_timeout = 60
|
|
||||||
#server_map_save_interval = 60
|
#server_map_save_interval = 60
|
||||||
|
#full_block_send_enable_min_time_from_building = 2.0
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
content_sao.cpp
|
||||||
mapgen.cpp
|
mapgen.cpp
|
||||||
content_inventory.cpp
|
content_inventory.cpp
|
||||||
content_nodemeta.cpp
|
content_nodemeta.cpp
|
||||||
@ -102,6 +103,7 @@ set(common_SRCS
|
|||||||
# Client sources
|
# Client sources
|
||||||
set(minetest_SRCS
|
set(minetest_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
|
content_cao.cpp
|
||||||
mapblock_mesh.cpp
|
mapblock_mesh.cpp
|
||||||
farmesh.cpp
|
farmesh.cpp
|
||||||
keycode.cpp
|
keycode.cpp
|
||||||
|
@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#define ACTIVEOBJECT_TYPE_INVALID 0
|
||||||
|
// Other types are defined in content_object.h
|
||||||
|
|
||||||
struct ActiveObjectMessage
|
struct ActiveObjectMessage
|
||||||
{
|
{
|
||||||
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
|
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
|
||||||
@ -36,12 +39,6 @@ struct ActiveObjectMessage
|
|||||||
std::string datastring;
|
std::string datastring;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ACTIVEOBJECT_TYPE_INVALID 0
|
|
||||||
#define ACTIVEOBJECT_TYPE_TEST 1
|
|
||||||
#define ACTIVEOBJECT_TYPE_ITEM 2
|
|
||||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
|
||||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parent class for ServerActiveObject and ClientActiveObject
|
Parent class for ServerActiveObject and ClientActiveObject
|
||||||
*/
|
*/
|
||||||
|
305
src/client.cpp
305
src/client.cpp
@ -25,6 +25,105 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
#include "mapsector.h"
|
||||||
|
#include "mapblock_mesh.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
QueuedMeshUpdate
|
||||||
|
*/
|
||||||
|
|
||||||
|
QueuedMeshUpdate::QueuedMeshUpdate():
|
||||||
|
p(-1337,-1337,-1337),
|
||||||
|
data(NULL),
|
||||||
|
ack_block_to_server(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QueuedMeshUpdate::~QueuedMeshUpdate()
|
||||||
|
{
|
||||||
|
if(data)
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
MeshUpdateQueue
|
||||||
|
*/
|
||||||
|
|
||||||
|
MeshUpdateQueue::MeshUpdateQueue()
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshUpdateQueue::~MeshUpdateQueue()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::list<QueuedMeshUpdate*>::Iterator i;
|
||||||
|
for(i=m_queue.begin(); i!=m_queue.end(); i++)
|
||||||
|
{
|
||||||
|
QueuedMeshUpdate *q = *i;
|
||||||
|
delete q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
peer_id=0 adds with nobody to send to
|
||||||
|
*/
|
||||||
|
void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find if block is already in queue.
|
||||||
|
If it is, update the data and quit.
|
||||||
|
*/
|
||||||
|
core::list<QueuedMeshUpdate*>::Iterator i;
|
||||||
|
for(i=m_queue.begin(); i!=m_queue.end(); i++)
|
||||||
|
{
|
||||||
|
QueuedMeshUpdate *q = *i;
|
||||||
|
if(q->p == p)
|
||||||
|
{
|
||||||
|
if(q->data)
|
||||||
|
delete q->data;
|
||||||
|
q->data = data;
|
||||||
|
if(ack_block_to_server)
|
||||||
|
q->ack_block_to_server = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the block
|
||||||
|
*/
|
||||||
|
QueuedMeshUpdate *q = new QueuedMeshUpdate;
|
||||||
|
q->p = p;
|
||||||
|
q->data = data;
|
||||||
|
q->ack_block_to_server = ack_block_to_server;
|
||||||
|
m_queue.push_back(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returned pointer must be deleted
|
||||||
|
// Returns NULL if queue is empty
|
||||||
|
QueuedMeshUpdate * MeshUpdateQueue::pop()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::list<QueuedMeshUpdate*>::Iterator i = m_queue.begin();
|
||||||
|
if(i == m_queue.end())
|
||||||
|
return NULL;
|
||||||
|
QueuedMeshUpdate *q = *i;
|
||||||
|
m_queue.erase(i);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
MeshUpdateThread
|
||||||
|
*/
|
||||||
|
|
||||||
void * MeshUpdateThread::Thread()
|
void * MeshUpdateThread::Thread()
|
||||||
{
|
{
|
||||||
@ -36,6 +135,15 @@ void * MeshUpdateThread::Thread()
|
|||||||
|
|
||||||
while(getRun())
|
while(getRun())
|
||||||
{
|
{
|
||||||
|
/*// Wait for output queue to flush.
|
||||||
|
// Allow 2 in queue, this makes less frametime jitter.
|
||||||
|
// Umm actually, there is no much difference
|
||||||
|
if(m_queue_out.size() >= 2)
|
||||||
|
{
|
||||||
|
sleep_ms(3);
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
|
|
||||||
QueuedMeshUpdate *q = m_queue_in.pop();
|
QueuedMeshUpdate *q = m_queue_in.pop();
|
||||||
if(q == NULL)
|
if(q == NULL)
|
||||||
{
|
{
|
||||||
@ -91,7 +199,7 @@ Client::Client(
|
|||||||
m_access_denied(false)
|
m_access_denied(false)
|
||||||
{
|
{
|
||||||
m_packetcounter_timer = 0.0;
|
m_packetcounter_timer = 0.0;
|
||||||
m_delete_unused_sectors_timer = 0.0;
|
//m_delete_unused_sectors_timer = 0.0;
|
||||||
m_connection_reinit_timer = 0.0;
|
m_connection_reinit_timer = 0.0;
|
||||||
m_avg_rtt_timer = 0.0;
|
m_avg_rtt_timer = 0.0;
|
||||||
m_playerpos_send_timer = 0.0;
|
m_playerpos_send_timer = 0.0;
|
||||||
@ -196,6 +304,10 @@ void Client::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get connection status
|
||||||
|
bool connected = connectedAndInitialized();
|
||||||
|
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Delete unused sectors
|
Delete unused sectors
|
||||||
@ -225,16 +337,16 @@ void Client::step(float dtime)
|
|||||||
true, &deleted_blocks);*/
|
true, &deleted_blocks);*/
|
||||||
|
|
||||||
// Delete whole sectors
|
// Delete whole sectors
|
||||||
u32 num = m_env.getMap().unloadUnusedData
|
m_env.getMap().unloadUnusedData
|
||||||
(delete_unused_sectors_timeout,
|
(delete_unused_sectors_timeout,
|
||||||
false, &deleted_blocks);
|
&deleted_blocks);
|
||||||
|
|
||||||
if(num > 0)
|
if(deleted_blocks.size() > 0)
|
||||||
{
|
{
|
||||||
/*dstream<<DTIME<<"Client: Deleted blocks of "<<num
|
/*dstream<<DTIME<<"Client: Deleted blocks of "<<num
|
||||||
<<" unused sectors"<<std::endl;*/
|
<<" unused sectors"<<std::endl;*/
|
||||||
dstream<<DTIME<<"Client: Deleted "<<num
|
/*dstream<<DTIME<<"Client: Deleted "<<num
|
||||||
<<" unused sectors"<<std::endl;
|
<<" unused sectors"<<std::endl;*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send info to server
|
Send info to server
|
||||||
@ -284,8 +396,7 @@ void Client::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
bool connected = connectedAndInitialized();
|
|
||||||
|
|
||||||
if(connected == false)
|
if(connected == false)
|
||||||
{
|
{
|
||||||
@ -330,6 +441,67 @@ void Client::step(float dtime)
|
|||||||
Do stuff if connected
|
Do stuff if connected
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Run Map's timers and unload unused data
|
||||||
|
*/
|
||||||
|
const float map_timer_and_unload_dtime = 5.25;
|
||||||
|
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||||
|
{
|
||||||
|
ScopeProfiler sp(&g_profiler, "Client: map timer and unload");
|
||||||
|
core::list<v3s16> deleted_blocks;
|
||||||
|
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||||
|
g_settings.getFloat("client_unload_unused_data_timeout"),
|
||||||
|
&deleted_blocks);
|
||||||
|
|
||||||
|
/*if(deleted_blocks.size() > 0)
|
||||||
|
dstream<<"Client: Unloaded "<<deleted_blocks.size()
|
||||||
|
<<" unused blocks"<<std::endl;*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send info to server
|
||||||
|
NOTE: This loop is intentionally iterated the way it is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::list<v3s16>::Iterator i = deleted_blocks.begin();
|
||||||
|
core::list<v3s16> sendlist;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(sendlist.size() == 255 || i == deleted_blocks.end())
|
||||||
|
{
|
||||||
|
if(sendlist.size() == 0)
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
[0] u16 command
|
||||||
|
[2] u8 count
|
||||||
|
[3] v3s16 pos_0
|
||||||
|
[3+6] v3s16 pos_1
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
u32 replysize = 2+1+6*sendlist.size();
|
||||||
|
SharedBuffer<u8> reply(replysize);
|
||||||
|
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
|
||||||
|
reply[2] = sendlist.size();
|
||||||
|
u32 k = 0;
|
||||||
|
for(core::list<v3s16>::Iterator
|
||||||
|
j = sendlist.begin();
|
||||||
|
j != sendlist.end(); j++)
|
||||||
|
{
|
||||||
|
writeV3S16(&reply[2+1+6*k], *j);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
||||||
|
|
||||||
|
if(i == deleted_blocks.end())
|
||||||
|
break;
|
||||||
|
|
||||||
|
sendlist.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendlist.push_back(*i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handle environment
|
Handle environment
|
||||||
*/
|
*/
|
||||||
@ -346,23 +518,23 @@ void Client::step(float dtime)
|
|||||||
// Step environment
|
// Step environment
|
||||||
m_env.step(dtime);
|
m_env.step(dtime);
|
||||||
|
|
||||||
// Step active blocks
|
/*
|
||||||
|
Handle active blocks
|
||||||
|
NOTE: These old objects are DEPRECATED. TODO: Remove
|
||||||
|
*/
|
||||||
for(core::map<v3s16, bool>::Iterator
|
for(core::map<v3s16, bool>::Iterator
|
||||||
i = m_active_blocks.getIterator();
|
i = m_active_blocks.getIterator();
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
v3s16 p = i.getNode()->getKey();
|
v3s16 p = i.getNode()->getKey();
|
||||||
|
|
||||||
MapBlock *block = NULL;
|
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
||||||
try
|
if(block == NULL)
|
||||||
{
|
continue;
|
||||||
block = m_env.getMap().getBlockNoCreate(p);
|
|
||||||
|
// Step MapBlockObjects
|
||||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
||||||
}
|
}
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get events
|
Get events
|
||||||
@ -695,36 +867,24 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
MapSector *sector;
|
MapSector *sector;
|
||||||
MapBlock *block;
|
MapBlock *block;
|
||||||
|
|
||||||
{ //envlock
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
|
|
||||||
v2s16 p2d(p.X, p.Z);
|
v2s16 p2d(p.X, p.Z);
|
||||||
sector = m_env.getMap().emergeSector(p2d);
|
sector = m_env.getMap().emergeSector(p2d);
|
||||||
|
|
||||||
v2s16 sp = sector->getPos();
|
assert(sector->getPos() == p2d);
|
||||||
if(sp != p2d)
|
|
||||||
{
|
|
||||||
dstream<<"ERROR: Got sector with getPos()="
|
|
||||||
<<"("<<sp.X<<","<<sp.Y<<"), tried to get"
|
|
||||||
<<"("<<p2d.X<<","<<p2d.Y<<")"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(sp == p2d);
|
|
||||||
//assert(sector->getPos() == p2d);
|
|
||||||
|
|
||||||
//TimeTaker timer("MapBlock deSerialize");
|
//TimeTaker timer("MapBlock deSerialize");
|
||||||
// 0ms
|
// 0ms
|
||||||
|
|
||||||
try{
|
block = sector->getBlockNoCreateNoEx(p.Y);
|
||||||
block = sector->getBlockNoCreate(p.Y);
|
if(block)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
Update an existing block
|
Update an existing block
|
||||||
*/
|
*/
|
||||||
//dstream<<"Updating"<<std::endl;
|
//dstream<<"Updating"<<std::endl;
|
||||||
block->deSerialize(istr, ser_version);
|
block->deSerialize(istr, ser_version);
|
||||||
//block->setChangedFlag();
|
|
||||||
}
|
}
|
||||||
catch(InvalidPositionException &e)
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Create a new block
|
Create a new block
|
||||||
@ -733,7 +893,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
block = new MapBlock(&m_env.getMap(), p);
|
block = new MapBlock(&m_env.getMap(), p);
|
||||||
block->deSerialize(istr, ser_version);
|
block->deSerialize(istr, ser_version);
|
||||||
sector->insertBlock(block);
|
sector->insertBlock(block);
|
||||||
//block->setChangedFlag();
|
|
||||||
|
|
||||||
//DEBUG
|
//DEBUG
|
||||||
/*NodeMod mod;
|
/*NodeMod mod;
|
||||||
@ -744,29 +903,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
block->setTempMod(v3s16(8,8,8), mod);
|
block->setTempMod(v3s16(8,8,8), mod);
|
||||||
block->setTempMod(v3s16(8,7,8), mod);
|
block->setTempMod(v3s16(8,7,8), mod);
|
||||||
block->setTempMod(v3s16(8,6,8), mod);*/
|
block->setTempMod(v3s16(8,6,8), mod);*/
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Add some coulds
|
|
||||||
Well, this is a dumb way to do it, they should just
|
|
||||||
be drawn as separate objects. But the looks of them
|
|
||||||
can be tested this way.
|
|
||||||
*/
|
|
||||||
if(p.Y == 3)
|
|
||||||
{
|
|
||||||
NodeMod mod;
|
|
||||||
mod.type = NODEMOD_CHANGECONTENT;
|
|
||||||
mod.param = CONTENT_CLOUD;
|
|
||||||
v3s16 p2;
|
|
||||||
p2.Y = 8;
|
|
||||||
for(p2.X=3; p2.X<=13; p2.X++)
|
|
||||||
for(p2.Z=3; p2.Z<=13; p2.Z++)
|
|
||||||
{
|
|
||||||
block->setTempMod(p2, mod);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} //envlock
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
@ -798,6 +935,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
/*
|
/*
|
||||||
Add it to mesh update queue and set it to be acknowledged after update.
|
Add it to mesh update queue and set it to be acknowledged after update.
|
||||||
*/
|
*/
|
||||||
|
//std::cerr<<"Adding mesh update task for received block"<<std::endl;
|
||||||
addUpdateMeshTaskWithEdge(p, true);
|
addUpdateMeshTaskWithEdge(p, true);
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_PLAYERPOS)
|
else if(command == TOCLIENT_PLAYERPOS)
|
||||||
@ -974,6 +1112,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
}
|
}
|
||||||
else if(command == TOCLIENT_SECTORMETA)
|
else if(command == TOCLIENT_SECTORMETA)
|
||||||
{
|
{
|
||||||
|
dstream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl;
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
[0] u16 command
|
[0] u16 command
|
||||||
[2] u8 sector count
|
[2] u8 sector count
|
||||||
@ -1009,6 +1149,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
((ClientMap&)m_env.getMap()).deSerializeSector(pos, is);
|
((ClientMap&)m_env.getMap()).deSerializeSector(pos, is);
|
||||||
}
|
}
|
||||||
} //envlock
|
} //envlock
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_INVENTORY)
|
else if(command == TOCLIENT_INVENTORY)
|
||||||
{
|
{
|
||||||
@ -1105,6 +1246,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Read block objects
|
Read block objects
|
||||||
|
NOTE: Deprecated stuff here, TODO: Remove
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Read active block count
|
// Read active block count
|
||||||
@ -1753,7 +1895,7 @@ void Client::addNode(v3s16 p, MapNode n)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
||||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
|
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
|
||||||
}
|
}
|
||||||
catch(InvalidPositionException &e)
|
catch(InvalidPositionException &e)
|
||||||
@ -1981,12 +2123,6 @@ void Client::printDebugInfo(std::ostream &os)
|
|||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*s32 Client::getDayNightIndex()
|
|
||||||
{
|
|
||||||
assert(m_daynight_i >= 0 && m_daynight_i < DAYNIGHT_CACHE_COUNT);
|
|
||||||
return m_daynight_i;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
u32 Client::getDayNightRatio()
|
u32 Client::getDayNightRatio()
|
||||||
{
|
{
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||||
@ -2000,6 +2136,40 @@ u16 Client::getHP()
|
|||||||
return player->hp;
|
return player->hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::setTempMod(v3s16 p, NodeMod mod)
|
||||||
|
{
|
||||||
|
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||||
|
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> affected_blocks;
|
||||||
|
((ClientMap&)m_env.getMap()).setTempMod(p, mod,
|
||||||
|
&affected_blocks);
|
||||||
|
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = affected_blocks.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::clearTempMod(v3s16 p)
|
||||||
|
{
|
||||||
|
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||||
|
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> affected_blocks;
|
||||||
|
((ClientMap&)m_env.getMap()).clearTempMod(p,
|
||||||
|
&affected_blocks);
|
||||||
|
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = affected_blocks.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
||||||
{
|
{
|
||||||
/*dstream<<"Client::addUpdateMeshTask(): "
|
/*dstream<<"Client::addUpdateMeshTask(): "
|
||||||
@ -2018,7 +2188,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
|||||||
|
|
||||||
{
|
{
|
||||||
//TimeTaker timer("data fill");
|
//TimeTaker timer("data fill");
|
||||||
// 0ms
|
// Release: ~0ms
|
||||||
|
// Debug: 1-6ms, avg=2ms
|
||||||
data->fill(getDayNightRatio(), b);
|
data->fill(getDayNightRatio(), b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2044,6 +2215,10 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mark mesh as non-expired at this point so that it can already
|
||||||
|
be marked as expired again if the data changes
|
||||||
|
*/
|
||||||
b->setMeshExpired(false);
|
b->setMeshExpired(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
src/client.h
130
src/client.h
@ -28,6 +28,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "jmutex.h"
|
#include "jmutex.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
|
#include "utility.h" // For IntervalLimiter
|
||||||
|
|
||||||
|
struct MeshMakeData;
|
||||||
|
|
||||||
class ClientNotReadyException : public BaseException
|
class ClientNotReadyException : public BaseException
|
||||||
{
|
{
|
||||||
@ -43,18 +46,8 @@ struct QueuedMeshUpdate
|
|||||||
MeshMakeData *data;
|
MeshMakeData *data;
|
||||||
bool ack_block_to_server;
|
bool ack_block_to_server;
|
||||||
|
|
||||||
QueuedMeshUpdate():
|
QueuedMeshUpdate();
|
||||||
p(-1337,-1337,-1337),
|
~QueuedMeshUpdate();
|
||||||
data(NULL),
|
|
||||||
ack_block_to_server(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~QueuedMeshUpdate()
|
|
||||||
{
|
|
||||||
if(data)
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -63,76 +56,18 @@ struct QueuedMeshUpdate
|
|||||||
class MeshUpdateQueue
|
class MeshUpdateQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MeshUpdateQueue()
|
MeshUpdateQueue();
|
||||||
{
|
|
||||||
m_mutex.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
~MeshUpdateQueue()
|
~MeshUpdateQueue();
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::list<QueuedMeshUpdate*>::Iterator i;
|
|
||||||
for(i=m_queue.begin(); i!=m_queue.end(); i++)
|
|
||||||
{
|
|
||||||
QueuedMeshUpdate *q = *i;
|
|
||||||
delete q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
peer_id=0 adds with nobody to send to
|
peer_id=0 adds with nobody to send to
|
||||||
*/
|
*/
|
||||||
void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server)
|
void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server);
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Find if block is already in queue.
|
|
||||||
If it is, update the data and quit.
|
|
||||||
*/
|
|
||||||
core::list<QueuedMeshUpdate*>::Iterator i;
|
|
||||||
for(i=m_queue.begin(); i!=m_queue.end(); i++)
|
|
||||||
{
|
|
||||||
QueuedMeshUpdate *q = *i;
|
|
||||||
if(q->p == p)
|
|
||||||
{
|
|
||||||
if(q->data)
|
|
||||||
delete q->data;
|
|
||||||
q->data = data;
|
|
||||||
if(ack_block_to_server)
|
|
||||||
q->ack_block_to_server = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the block
|
|
||||||
*/
|
|
||||||
QueuedMeshUpdate *q = new QueuedMeshUpdate;
|
|
||||||
q->p = p;
|
|
||||||
q->data = data;
|
|
||||||
q->ack_block_to_server = ack_block_to_server;
|
|
||||||
m_queue.push_back(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returned pointer must be deleted
|
// Returned pointer must be deleted
|
||||||
// Returns NULL if queue is empty
|
// Returns NULL if queue is empty
|
||||||
QueuedMeshUpdate * pop()
|
QueuedMeshUpdate * pop();
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::list<QueuedMeshUpdate*>::Iterator i = m_queue.begin();
|
|
||||||
if(i == m_queue.end())
|
|
||||||
return NULL;
|
|
||||||
QueuedMeshUpdate *q = *i;
|
|
||||||
m_queue.erase(i);
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size()
|
u32 size()
|
||||||
{
|
{
|
||||||
@ -309,40 +244,8 @@ public:
|
|||||||
|
|
||||||
u16 getHP();
|
u16 getHP();
|
||||||
|
|
||||||
//void updateSomeExpiredMeshes();
|
void setTempMod(v3s16 p, NodeMod mod);
|
||||||
|
void clearTempMod(v3s16 p);
|
||||||
void setTempMod(v3s16 p, NodeMod mod)
|
|
||||||
{
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> affected_blocks;
|
|
||||||
((ClientMap&)m_env.getMap()).setTempMod(p, mod,
|
|
||||||
&affected_blocks);
|
|
||||||
|
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
|
||||||
i = affected_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void clearTempMod(v3s16 p)
|
|
||||||
{
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> affected_blocks;
|
|
||||||
((ClientMap&)m_env.getMap()).clearTempMod(p,
|
|
||||||
&affected_blocks);
|
|
||||||
|
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
|
||||||
i = affected_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float getAvgRtt()
|
float getAvgRtt()
|
||||||
{
|
{
|
||||||
@ -390,6 +293,15 @@ public:
|
|||||||
return m_access_denied_reason;
|
return m_access_denied_reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This should only be used for calling the special drawing stuff in
|
||||||
|
ClientEnvironment
|
||||||
|
*/
|
||||||
|
ClientEnvironment * getEnv()
|
||||||
|
{
|
||||||
|
return &m_env;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Virtual methods from con::PeerHandler
|
// Virtual methods from con::PeerHandler
|
||||||
@ -404,11 +316,11 @@ private:
|
|||||||
void sendPlayerInfo();
|
void sendPlayerInfo();
|
||||||
|
|
||||||
float m_packetcounter_timer;
|
float m_packetcounter_timer;
|
||||||
float m_delete_unused_sectors_timer;
|
|
||||||
float m_connection_reinit_timer;
|
float m_connection_reinit_timer;
|
||||||
float m_avg_rtt_timer;
|
float m_avg_rtt_timer;
|
||||||
float m_playerpos_send_timer;
|
float m_playerpos_send_timer;
|
||||||
float m_ignore_damage_timer; // Used after server moves player
|
float m_ignore_damage_timer; // Used after server moves player
|
||||||
|
IntervalLimiter m_map_timer_and_unload_interval;
|
||||||
|
|
||||||
MeshUpdateThread m_mesh_update_thread;
|
MeshUpdateThread m_mesh_update_thread;
|
||||||
|
|
||||||
|
@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utility.h"
|
|
||||||
#include "environment.h"
|
|
||||||
#include "tile.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ClientActiveObject
|
ClientActiveObject
|
||||||
@ -68,674 +65,4 @@ void ClientActiveObject::registerType(u16 type, Factory f)
|
|||||||
m_types.insert(type, f);
|
m_types.insert(type, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
TestCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
TestCAO proto_TestCAO;
|
|
||||||
|
|
||||||
TestCAO::TestCAO():
|
|
||||||
ClientActiveObject(0),
|
|
||||||
m_node(NULL),
|
|
||||||
m_position(v3f(0,10*BS,0))
|
|
||||||
{
|
|
||||||
ClientActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
TestCAO::~TestCAO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientActiveObject* TestCAO::create()
|
|
||||||
{
|
|
||||||
return new TestCAO();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
buf->getMaterial().setTexture
|
|
||||||
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::removeFromScene()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->remove();
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::updateLight(u8 light_at_pos)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 TestCAO::getLightPosition()
|
|
||||||
{
|
|
||||||
return floatToInt(m_position, BS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::updateNodePos()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->setPosition(m_position);
|
|
||||||
//m_node->setRotation(v3f(0, 45, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::step(float dtime, ClientEnvironment *env)
|
|
||||||
{
|
|
||||||
if(m_node)
|
|
||||||
{
|
|
||||||
v3f rot = m_node->getRotation();
|
|
||||||
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
|
||||||
rot.Y += dtime * 180;
|
|
||||||
m_node->setRotation(rot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCAO::processMessage(const std::string &data)
|
|
||||||
{
|
|
||||||
dstream<<"TestCAO: Got data: "<<data<<std::endl;
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
u16 cmd;
|
|
||||||
is>>cmd;
|
|
||||||
if(cmd == 0)
|
|
||||||
{
|
|
||||||
v3f newpos;
|
|
||||||
is>>newpos.X;
|
|
||||||
is>>newpos.Y;
|
|
||||||
is>>newpos.Z;
|
|
||||||
m_position = newpos;
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
ItemCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "inventory.h"
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
ItemCAO proto_ItemCAO;
|
|
||||||
|
|
||||||
ItemCAO::ItemCAO():
|
|
||||||
ClientActiveObject(0),
|
|
||||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
|
|
||||||
m_node(NULL),
|
|
||||||
m_position(v3f(0,10*BS,0))
|
|
||||||
{
|
|
||||||
ClientActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemCAO::~ItemCAO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientActiveObject* ItemCAO::create()
|
|
||||||
{
|
|
||||||
return new ItemCAO();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
//buf->getMaterial().setTexture(0, NULL);
|
|
||||||
// Initialize with the stick texture
|
|
||||||
buf->getMaterial().setTexture
|
|
||||||
(0, driver->getTexture(getTexturePath("stick.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
// Set it to use the materials of the meshbuffers directly.
|
|
||||||
// This is needed for changing the texture in the future
|
|
||||||
m_node->setReadOnlyMaterials(true);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::removeFromScene()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->remove();
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::updateLight(u8 light_at_pos)
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u8 li = decode_light(light_at_pos);
|
|
||||||
video::SColor color(255,li,li,li);
|
|
||||||
|
|
||||||
scene::IMesh *mesh = m_node->getMesh();
|
|
||||||
if(mesh == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u16 mc = mesh->getMeshBufferCount();
|
|
||||||
for(u16 j=0; j<mc; j++)
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
|
||||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
|
||||||
u16 vc = buf->getVertexCount();
|
|
||||||
for(u16 i=0; i<vc; i++)
|
|
||||||
{
|
|
||||||
vertices[i].Color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 ItemCAO::getLightPosition()
|
|
||||||
{
|
|
||||||
return floatToInt(m_position, BS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::updateNodePos()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->setPosition(m_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::step(float dtime, ClientEnvironment *env)
|
|
||||||
{
|
|
||||||
if(m_node)
|
|
||||||
{
|
|
||||||
/*v3f rot = m_node->getRotation();
|
|
||||||
rot.Y += dtime * 120;
|
|
||||||
m_node->setRotation(rot);*/
|
|
||||||
LocalPlayer *player = env->getLocalPlayer();
|
|
||||||
assert(player);
|
|
||||||
v3f rot = m_node->getRotation();
|
|
||||||
rot.Y = 180.0 - (player->getYaw());
|
|
||||||
m_node->setRotation(rot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::processMessage(const std::string &data)
|
|
||||||
{
|
|
||||||
dstream<<"ItemCAO: Got message"<<std::endl;
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// command
|
|
||||||
u8 cmd = readU8(is);
|
|
||||||
if(cmd == 0)
|
|
||||||
{
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemCAO::initialize(const std::string &data)
|
|
||||||
{
|
|
||||||
dstream<<"ItemCAO: Got init data"<<std::endl;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// version
|
|
||||||
u8 version = readU8(is);
|
|
||||||
// check version
|
|
||||||
if(version != 0)
|
|
||||||
return;
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
// inventorystring
|
|
||||||
m_inventorystring = deSerializeString(is);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodePos();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update image of node
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scene::IMesh *mesh = m_node->getMesh();
|
|
||||||
|
|
||||||
if(mesh == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
|
|
||||||
|
|
||||||
if(buf == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Create an inventory item to see what is its image
|
|
||||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
|
||||||
video::ITexture *texture = NULL;
|
|
||||||
try{
|
|
||||||
InventoryItem *item = NULL;
|
|
||||||
item = InventoryItem::deSerialize(is);
|
|
||||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
|
||||||
<<m_inventorystring<<"\" -> item="<<item
|
|
||||||
<<std::endl;
|
|
||||||
if(item)
|
|
||||||
{
|
|
||||||
texture = item->getImage();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(SerializationError &e)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: "<<__FUNCTION_NAME
|
|
||||||
<<": error deSerializing inventorystring \""
|
|
||||||
<<m_inventorystring<<"\""<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set meshbuffer texture
|
|
||||||
buf->getMaterial().setTexture(0, texture);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
RatCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "inventory.h"
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
RatCAO proto_RatCAO;
|
|
||||||
|
|
||||||
RatCAO::RatCAO():
|
|
||||||
ClientActiveObject(0),
|
|
||||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
|
||||||
m_node(NULL),
|
|
||||||
m_position(v3f(0,10*BS,0)),
|
|
||||||
m_yaw(0)
|
|
||||||
{
|
|
||||||
ClientActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
RatCAO::~RatCAO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientActiveObject* RatCAO::create()
|
|
||||||
{
|
|
||||||
return new RatCAO();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
//buf->getMaterial().setTexture(0, NULL);
|
|
||||||
buf->getMaterial().setTexture
|
|
||||||
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
// Set it to use the materials of the meshbuffers directly.
|
|
||||||
// This is needed for changing the texture in the future
|
|
||||||
m_node->setReadOnlyMaterials(true);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::removeFromScene()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->remove();
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::updateLight(u8 light_at_pos)
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u8 li = decode_light(light_at_pos);
|
|
||||||
video::SColor color(255,li,li,li);
|
|
||||||
|
|
||||||
scene::IMesh *mesh = m_node->getMesh();
|
|
||||||
if(mesh == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u16 mc = mesh->getMeshBufferCount();
|
|
||||||
for(u16 j=0; j<mc; j++)
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
|
||||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
|
||||||
u16 vc = buf->getVertexCount();
|
|
||||||
for(u16 i=0; i<vc; i++)
|
|
||||||
{
|
|
||||||
vertices[i].Color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 RatCAO::getLightPosition()
|
|
||||||
{
|
|
||||||
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::updateNodePos()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//m_node->setPosition(m_position);
|
|
||||||
m_node->setPosition(pos_translator.vect_show);
|
|
||||||
|
|
||||||
v3f rot = m_node->getRotation();
|
|
||||||
rot.Y = 180.0 - m_yaw;
|
|
||||||
m_node->setRotation(rot);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::step(float dtime, ClientEnvironment *env)
|
|
||||||
{
|
|
||||||
pos_translator.translate(dtime);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::processMessage(const std::string &data)
|
|
||||||
{
|
|
||||||
//dstream<<"RatCAO: Got message"<<std::endl;
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// command
|
|
||||||
u8 cmd = readU8(is);
|
|
||||||
if(cmd == 0)
|
|
||||||
{
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
pos_translator.update(m_position);
|
|
||||||
// yaw
|
|
||||||
m_yaw = readF1000(is);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatCAO::initialize(const std::string &data)
|
|
||||||
{
|
|
||||||
//dstream<<"RatCAO: Got init data"<<std::endl;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// version
|
|
||||||
u8 version = readU8(is);
|
|
||||||
// check version
|
|
||||||
if(version != 0)
|
|
||||||
return;
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
pos_translator.init(m_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Oerkki1CAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "inventory.h"
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
Oerkki1CAO proto_Oerkki1CAO;
|
|
||||||
|
|
||||||
Oerkki1CAO::Oerkki1CAO():
|
|
||||||
ClientActiveObject(0),
|
|
||||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
|
|
||||||
m_node(NULL),
|
|
||||||
m_position(v3f(0,10*BS,0)),
|
|
||||||
m_yaw(0)
|
|
||||||
{
|
|
||||||
ClientActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
Oerkki1CAO::~Oerkki1CAO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientActiveObject* Oerkki1CAO::create()
|
|
||||||
{
|
|
||||||
return new Oerkki1CAO();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
//buf->getMaterial().setTexture(0, NULL);
|
|
||||||
buf->getMaterial().setTexture
|
|
||||||
(0, driver->getTexture(getTexturePath("oerkki1.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
// Set it to use the materials of the meshbuffers directly.
|
|
||||||
// This is needed for changing the texture in the future
|
|
||||||
m_node->setReadOnlyMaterials(true);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::removeFromScene()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_node->remove();
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::updateLight(u8 light_at_pos)
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(light_at_pos <= 2)
|
|
||||||
{
|
|
||||||
m_node->setVisible(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_node->setVisible(true);
|
|
||||||
|
|
||||||
u8 li = decode_light(light_at_pos);
|
|
||||||
video::SColor color(255,li,li,li);
|
|
||||||
|
|
||||||
scene::IMesh *mesh = m_node->getMesh();
|
|
||||||
if(mesh == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u16 mc = mesh->getMeshBufferCount();
|
|
||||||
for(u16 j=0; j<mc; j++)
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
|
||||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
|
||||||
u16 vc = buf->getVertexCount();
|
|
||||||
for(u16 i=0; i<vc; i++)
|
|
||||||
{
|
|
||||||
vertices[i].Color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 Oerkki1CAO::getLightPosition()
|
|
||||||
{
|
|
||||||
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::updateNodePos()
|
|
||||||
{
|
|
||||||
if(m_node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//m_node->setPosition(m_position);
|
|
||||||
m_node->setPosition(pos_translator.vect_show);
|
|
||||||
|
|
||||||
v3f rot = m_node->getRotation();
|
|
||||||
rot.Y = 180.0 - m_yaw + 90.0;
|
|
||||||
m_node->setRotation(rot);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
|
||||||
{
|
|
||||||
pos_translator.translate(dtime);
|
|
||||||
updateNodePos();
|
|
||||||
|
|
||||||
LocalPlayer *player = env->getLocalPlayer();
|
|
||||||
assert(player);
|
|
||||||
|
|
||||||
v3f playerpos = player->getPosition();
|
|
||||||
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
|
||||||
v2f objectpos_2d(m_position.X,m_position.Z);
|
|
||||||
|
|
||||||
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
|
|
||||||
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.0*BS)
|
|
||||||
{
|
|
||||||
if(m_attack_interval.step(dtime, 0.5))
|
|
||||||
{
|
|
||||||
env->damageLocalPlayer(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::processMessage(const std::string &data)
|
|
||||||
{
|
|
||||||
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// command
|
|
||||||
u8 cmd = readU8(is);
|
|
||||||
if(cmd == 0)
|
|
||||||
{
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
pos_translator.update(m_position);
|
|
||||||
// yaw
|
|
||||||
m_yaw = readF1000(is);
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1CAO::initialize(const std::string &data)
|
|
||||||
{
|
|
||||||
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// version
|
|
||||||
u8 version = readU8(is);
|
|
||||||
// check version
|
|
||||||
if(version != 0)
|
|
||||||
return;
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
pos_translator.init(m_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "activeobject.h"
|
#include "activeobject.h"
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -36,63 +35,6 @@ Some planning
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
SmoothTranslator
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct SmoothTranslator
|
|
||||||
{
|
|
||||||
v3f vect_old;
|
|
||||||
f32 anim_counter;
|
|
||||||
f32 anim_time;
|
|
||||||
f32 anim_time_counter;
|
|
||||||
v3f vect_show;
|
|
||||||
v3f vect_aim;
|
|
||||||
|
|
||||||
SmoothTranslator():
|
|
||||||
vect_old(0,0,0),
|
|
||||||
anim_counter(0),
|
|
||||||
anim_time(0),
|
|
||||||
anim_time_counter(0),
|
|
||||||
vect_show(0,0,0),
|
|
||||||
vect_aim(0,0,0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void init(v3f vect)
|
|
||||||
{
|
|
||||||
vect_old = vect;
|
|
||||||
vect_show = vect;
|
|
||||||
vect_aim = vect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(v3f vect_new)
|
|
||||||
{
|
|
||||||
vect_old = vect_show;
|
|
||||||
vect_aim = vect_new;
|
|
||||||
if(anim_time < 0.001 || anim_time > 1.0)
|
|
||||||
anim_time = anim_time_counter;
|
|
||||||
else
|
|
||||||
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
|
||||||
anim_time_counter = 0;
|
|
||||||
anim_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void translate(f32 dtime)
|
|
||||||
{
|
|
||||||
anim_time_counter = anim_time_counter + dtime;
|
|
||||||
anim_counter = anim_counter + dtime;
|
|
||||||
v3f vect_move = vect_aim - vect_old;
|
|
||||||
f32 moveratio = 1.0;
|
|
||||||
if(anim_time > 0.001)
|
|
||||||
moveratio = anim_time_counter / anim_time;
|
|
||||||
// Move a bit less than should, to avoid oscillation
|
|
||||||
moveratio = moveratio * 0.8;
|
|
||||||
if(moveratio > 1.5)
|
|
||||||
moveratio = 1.5;
|
|
||||||
vect_show = vect_old + vect_move * moveratio;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClientEnvironment;
|
class ClientEnvironment;
|
||||||
|
|
||||||
class ClientActiveObject : public ActiveObject
|
class ClientActiveObject : public ActiveObject
|
||||||
@ -153,164 +95,5 @@ struct DistanceSortedActiveObject
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
TestCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TestCAO : public ClientActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestCAO();
|
|
||||||
virtual ~TestCAO();
|
|
||||||
|
|
||||||
u8 getType() const
|
|
||||||
{
|
|
||||||
return ACTIVEOBJECT_TYPE_TEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClientActiveObject* create();
|
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr);
|
|
||||||
void removeFromScene();
|
|
||||||
void updateLight(u8 light_at_pos);
|
|
||||||
v3s16 getLightPosition();
|
|
||||||
void updateNodePos();
|
|
||||||
|
|
||||||
void step(float dtime, ClientEnvironment *env);
|
|
||||||
|
|
||||||
void processMessage(const std::string &data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
scene::IMeshSceneNode *m_node;
|
|
||||||
v3f m_position;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
ItemCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ItemCAO : public ClientActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ItemCAO();
|
|
||||||
virtual ~ItemCAO();
|
|
||||||
|
|
||||||
u8 getType() const
|
|
||||||
{
|
|
||||||
return ACTIVEOBJECT_TYPE_ITEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClientActiveObject* create();
|
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr);
|
|
||||||
void removeFromScene();
|
|
||||||
void updateLight(u8 light_at_pos);
|
|
||||||
v3s16 getLightPosition();
|
|
||||||
void updateNodePos();
|
|
||||||
|
|
||||||
void step(float dtime, ClientEnvironment *env);
|
|
||||||
|
|
||||||
void processMessage(const std::string &data);
|
|
||||||
|
|
||||||
void initialize(const std::string &data);
|
|
||||||
|
|
||||||
core::aabbox3d<f32>* getSelectionBox()
|
|
||||||
{return &m_selection_box;}
|
|
||||||
v3f getPosition()
|
|
||||||
{return m_position;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
core::aabbox3d<f32> m_selection_box;
|
|
||||||
scene::IMeshSceneNode *m_node;
|
|
||||||
v3f m_position;
|
|
||||||
std::string m_inventorystring;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
RatCAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class RatCAO : public ClientActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RatCAO();
|
|
||||||
virtual ~RatCAO();
|
|
||||||
|
|
||||||
u8 getType() const
|
|
||||||
{
|
|
||||||
return ACTIVEOBJECT_TYPE_RAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClientActiveObject* create();
|
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr);
|
|
||||||
void removeFromScene();
|
|
||||||
void updateLight(u8 light_at_pos);
|
|
||||||
v3s16 getLightPosition();
|
|
||||||
void updateNodePos();
|
|
||||||
|
|
||||||
void step(float dtime, ClientEnvironment *env);
|
|
||||||
|
|
||||||
void processMessage(const std::string &data);
|
|
||||||
|
|
||||||
void initialize(const std::string &data);
|
|
||||||
|
|
||||||
core::aabbox3d<f32>* getSelectionBox()
|
|
||||||
{return &m_selection_box;}
|
|
||||||
v3f getPosition()
|
|
||||||
{return m_position;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
core::aabbox3d<f32> m_selection_box;
|
|
||||||
scene::IMeshSceneNode *m_node;
|
|
||||||
v3f m_position;
|
|
||||||
float m_yaw;
|
|
||||||
SmoothTranslator pos_translator;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Oerkki1CAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Oerkki1CAO : public ClientActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Oerkki1CAO();
|
|
||||||
virtual ~Oerkki1CAO();
|
|
||||||
|
|
||||||
u8 getType() const
|
|
||||||
{
|
|
||||||
return ACTIVEOBJECT_TYPE_OERKKI1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClientActiveObject* create();
|
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr);
|
|
||||||
void removeFromScene();
|
|
||||||
void updateLight(u8 light_at_pos);
|
|
||||||
v3s16 getLightPosition();
|
|
||||||
void updateNodePos();
|
|
||||||
|
|
||||||
void step(float dtime, ClientEnvironment *env);
|
|
||||||
|
|
||||||
void processMessage(const std::string &data);
|
|
||||||
|
|
||||||
void initialize(const std::string &data);
|
|
||||||
|
|
||||||
core::aabbox3d<f32>* getSelectionBox()
|
|
||||||
{return &m_selection_box;}
|
|
||||||
v3f getPosition()
|
|
||||||
{return pos_translator.vect_show;}
|
|
||||||
//{return m_position;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
IntervalLimiter m_attack_interval;
|
|
||||||
core::aabbox3d<f32> m_selection_box;
|
|
||||||
scene::IMeshSceneNode *m_node;
|
|
||||||
v3f m_position;
|
|
||||||
float m_yaw;
|
|
||||||
SmoothTranslator pos_translator;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ enum ToClientCommand
|
|||||||
[0] u16 TOSERVER_INIT
|
[0] u16 TOSERVER_INIT
|
||||||
[2] u8 deployed version
|
[2] u8 deployed version
|
||||||
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
||||||
([4] u64 map seed (new as of 2011-02-27))
|
[12] u64 map seed (new as of 2011-02-27)
|
||||||
|
|
||||||
NOTE: The position in here is deprecated; position is
|
NOTE: The position in here is deprecated; position is
|
||||||
explicitly sent afterwards
|
explicitly sent afterwards
|
||||||
|
@ -182,4 +182,58 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d,
|
||||||
|
const core::aabbox3d<f32> &box_0,
|
||||||
|
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||||
|
{
|
||||||
|
collisionMoveResult final_result;
|
||||||
|
|
||||||
|
// Maximum time increment (for collision detection etc)
|
||||||
|
// time = distance / speed
|
||||||
|
f32 dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||||
|
|
||||||
|
// Maximum time increment is 10ms or lower
|
||||||
|
if(dtime_max_increment > 0.01)
|
||||||
|
dtime_max_increment = 0.01;
|
||||||
|
|
||||||
|
// Don't allow overly huge dtime
|
||||||
|
if(dtime > 2.0)
|
||||||
|
dtime = 2.0;
|
||||||
|
|
||||||
|
f32 dtime_downcount = dtime;
|
||||||
|
|
||||||
|
u32 loopcount = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
loopcount++;
|
||||||
|
|
||||||
|
f32 dtime_part;
|
||||||
|
if(dtime_downcount > dtime_max_increment)
|
||||||
|
{
|
||||||
|
dtime_part = dtime_max_increment;
|
||||||
|
dtime_downcount -= dtime_part;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dtime_part = dtime_downcount;
|
||||||
|
/*
|
||||||
|
Setting this to 0 (no -=dtime_part) disables an infinite loop
|
||||||
|
when dtime_part is so small that dtime_downcount -= dtime_part
|
||||||
|
does nothing
|
||||||
|
*/
|
||||||
|
dtime_downcount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
collisionMoveResult result = collisionMoveSimple(map, pos_max_d,
|
||||||
|
box_0, dtime_part, pos_f, speed_f);
|
||||||
|
|
||||||
|
if(result.touching_ground)
|
||||||
|
final_result.touching_ground = true;
|
||||||
|
}
|
||||||
|
while(dtime_downcount > 0.001);
|
||||||
|
|
||||||
|
|
||||||
|
return final_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,10 +33,15 @@ struct collisionMoveResult
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||||
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
||||||
const core::aabbox3d<f32> &box_0,
|
const core::aabbox3d<f32> &box_0,
|
||||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||||
//{return collisionMoveResult();}
|
|
||||||
|
// Moves using as many iterations as needed
|
||||||
|
collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d,
|
||||||
|
const core::aabbox3d<f32> &box_0,
|
||||||
|
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||||
|
|
||||||
enum CollisionType
|
enum CollisionType
|
||||||
{
|
{
|
||||||
|
753
src/content_cao.cpp
Normal file
753
src/content_cao.cpp
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_cao.h"
|
||||||
|
#include "tile.h"
|
||||||
|
#include "environment.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
TestCAO proto_TestCAO;
|
||||||
|
|
||||||
|
TestCAO::TestCAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCAO::~TestCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* TestCAO::create()
|
||||||
|
{
|
||||||
|
return new TestCAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 TestCAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(m_position);
|
||||||
|
//m_node->setRotation(v3f(0, 45, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||||
|
rot.Y += dtime * 180;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
dstream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
u16 cmd;
|
||||||
|
is>>cmd;
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
v3f newpos;
|
||||||
|
is>>newpos.X;
|
||||||
|
is>>newpos.Y;
|
||||||
|
is>>newpos.Z;
|
||||||
|
m_position = newpos;
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ItemCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
ItemCAO proto_ItemCAO;
|
||||||
|
|
||||||
|
ItemCAO::ItemCAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemCAO::~ItemCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* ItemCAO::create()
|
||||||
|
{
|
||||||
|
return new ItemCAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
// Initialize with the stick texture
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(getTexturePath("stick.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||||
|
u16 vc = buf->getVertexCount();
|
||||||
|
for(u16 i=0; i<vc; i++)
|
||||||
|
{
|
||||||
|
vertices[i].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 ItemCAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
/*v3f rot = m_node->getRotation();
|
||||||
|
rot.Y += dtime * 120;
|
||||||
|
m_node->setRotation(rot);*/
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - (player->getYaw());
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
dstream<<"ItemCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemCAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
dstream<<"ItemCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// inventorystring
|
||||||
|
m_inventorystring = deSerializeString(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update image of node
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
|
||||||
|
|
||||||
|
if(buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Create an inventory item to see what is its image
|
||||||
|
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||||
|
video::ITexture *texture = NULL;
|
||||||
|
try{
|
||||||
|
InventoryItem *item = NULL;
|
||||||
|
item = InventoryItem::deSerialize(is);
|
||||||
|
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||||
|
<<m_inventorystring<<"\" -> item="<<item
|
||||||
|
<<std::endl;
|
||||||
|
if(item)
|
||||||
|
{
|
||||||
|
texture = item->getImage();
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: "<<__FUNCTION_NAME
|
||||||
|
<<": error deSerializing inventorystring \""
|
||||||
|
<<m_inventorystring<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set meshbuffer texture
|
||||||
|
buf->getMaterial().setTexture(0, texture);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatCAO proto_RatCAO;
|
||||||
|
|
||||||
|
RatCAO::RatCAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
RatCAO::~RatCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* RatCAO::create()
|
||||||
|
{
|
||||||
|
return new RatCAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||||
|
u16 vc = buf->getVertexCount();
|
||||||
|
for(u16 i=0; i<vc; i++)
|
||||||
|
{
|
||||||
|
vertices[i].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 RatCAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"RatCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"RatCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1CAO proto_Oerkki1CAO;
|
||||||
|
|
||||||
|
Oerkki1CAO::Oerkki1CAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_damage_visual_timer(0),
|
||||||
|
m_damage_texture_enabled(false)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
Oerkki1CAO::~Oerkki1CAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* Oerkki1CAO::create()
|
||||||
|
{
|
||||||
|
return new Oerkki1CAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(getTexturePath("oerkki1.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(light_at_pos <= 2)
|
||||||
|
{
|
||||||
|
m_node->setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->setVisible(true);
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||||
|
u16 vc = buf->getVertexCount();
|
||||||
|
for(u16 i=0; i<vc; i++)
|
||||||
|
{
|
||||||
|
vertices[i].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 Oerkki1CAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw + 90.0;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||||
|
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||||
|
|
||||||
|
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
|
||||||
|
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
|
||||||
|
{
|
||||||
|
if(m_attack_interval.step(dtime, 0.5))
|
||||||
|
{
|
||||||
|
env->damageLocalPlayer(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_damage_visual_timer > 0)
|
||||||
|
{
|
||||||
|
if(!m_damage_texture_enabled)
|
||||||
|
{
|
||||||
|
// Enable damage texture
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
video::IVideoDriver* driver =
|
||||||
|
m_node->getSceneManager()->getVideoDriver();
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
buf->getMaterial().setTexture(0, driver->getTexture(
|
||||||
|
getTexturePath("oerkki1_damaged.png").c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_damage_texture_enabled = true;
|
||||||
|
}
|
||||||
|
m_damage_visual_timer -= dtime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_damage_texture_enabled)
|
||||||
|
{
|
||||||
|
// Disable damage texture
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
video::IVideoDriver* driver =
|
||||||
|
m_node->getSceneManager()->getVideoDriver();
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
buf->getMaterial().setTexture(0, driver->getTexture(
|
||||||
|
getTexturePath("oerkki1.png").c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_damage_texture_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
else if(cmd == 1)
|
||||||
|
{
|
||||||
|
u16 damage = readU8(is);
|
||||||
|
m_damage_visual_timer = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
248
src/content_cao.h
Normal file
248
src/content_cao.h
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_CAO_HEADER
|
||||||
|
#define CONTENT_CAO_HEADER
|
||||||
|
|
||||||
|
#include "clientobject.h"
|
||||||
|
#include "content_object.h"
|
||||||
|
#include "utility.h" // For IntervalLimiter
|
||||||
|
|
||||||
|
/*
|
||||||
|
SmoothTranslator
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SmoothTranslator
|
||||||
|
{
|
||||||
|
v3f vect_old;
|
||||||
|
f32 anim_counter;
|
||||||
|
f32 anim_time;
|
||||||
|
f32 anim_time_counter;
|
||||||
|
v3f vect_show;
|
||||||
|
v3f vect_aim;
|
||||||
|
|
||||||
|
SmoothTranslator():
|
||||||
|
vect_old(0,0,0),
|
||||||
|
anim_counter(0),
|
||||||
|
anim_time(0),
|
||||||
|
anim_time_counter(0),
|
||||||
|
vect_show(0,0,0),
|
||||||
|
vect_aim(0,0,0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void init(v3f vect)
|
||||||
|
{
|
||||||
|
vect_old = vect;
|
||||||
|
vect_show = vect;
|
||||||
|
vect_aim = vect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(v3f vect_new)
|
||||||
|
{
|
||||||
|
vect_old = vect_show;
|
||||||
|
vect_aim = vect_new;
|
||||||
|
if(anim_time < 0.001 || anim_time > 1.0)
|
||||||
|
anim_time = anim_time_counter;
|
||||||
|
else
|
||||||
|
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
||||||
|
anim_time_counter = 0;
|
||||||
|
anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translate(f32 dtime)
|
||||||
|
{
|
||||||
|
anim_time_counter = anim_time_counter + dtime;
|
||||||
|
anim_counter = anim_counter + dtime;
|
||||||
|
v3f vect_move = vect_aim - vect_old;
|
||||||
|
f32 moveratio = 1.0;
|
||||||
|
if(anim_time > 0.001)
|
||||||
|
moveratio = anim_time_counter / anim_time;
|
||||||
|
// Move a bit less than should, to avoid oscillation
|
||||||
|
moveratio = moveratio * 0.8;
|
||||||
|
if(moveratio > 1.5)
|
||||||
|
moveratio = 1.5;
|
||||||
|
vect_show = vect_old + vect_move * moveratio;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TestCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestCAO();
|
||||||
|
virtual ~TestCAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ItemCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ItemCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemCAO();
|
||||||
|
virtual ~ItemCAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
std::string m_inventorystring;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RatCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatCAO();
|
||||||
|
virtual ~RatCAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_RAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Oerkki1CAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1CAO();
|
||||||
|
virtual ~Oerkki1CAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_OERKKI1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
//{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntervalLimiter m_attack_interval;
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
float m_damage_visual_timer;
|
||||||
|
bool m_damage_texture_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -19,8 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "content_inventory.h"
|
#include "content_inventory.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "serverobject.h"
|
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
|
//#include "serverobject.h"
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
bool item_material_is_cookable(u8 content)
|
bool item_material_is_cookable(u8 content)
|
||||||
{
|
{
|
||||||
|
@ -272,7 +272,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
/*
|
/*
|
||||||
Signs on walls
|
Signs on walls
|
||||||
*/
|
*/
|
||||||
if(n.d == CONTENT_SIGN_WALL)
|
else if(n.d == CONTENT_SIGN_WALL)
|
||||||
{
|
{
|
||||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||||
video::SColor c(255,l,l,l);
|
video::SColor c(255,l,l,l);
|
||||||
|
@ -224,7 +224,6 @@ void content_mapnode_init()
|
|||||||
// Deprecated
|
// Deprecated
|
||||||
i = CONTENT_COALSTONE;
|
i = CONTENT_COALSTONE;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
|
||||||
f->setAllTextures("stone.png^mineral_coal.png");
|
f->setAllTextures("stone.png^mineral_coal.png");
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
setStoneLikeDiggingProperties(f->digging_properties, 1.5);
|
setStoneLikeDiggingProperties(f->digging_properties, 1.5);
|
||||||
|
29
src/content_object.h
Normal file
29
src/content_object.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_OBJECT_HEADER
|
||||||
|
#define CONTENT_OBJECT_HEADER
|
||||||
|
|
||||||
|
#define ACTIVEOBJECT_TYPE_TEST 1
|
||||||
|
#define ACTIVEOBJECT_TYPE_ITEM 2
|
||||||
|
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||||
|
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
694
src/content_sao.cpp
Normal file
694
src/content_sao.cpp
Normal file
@ -0,0 +1,694 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
#include "collision.h"
|
||||||
|
#include "environment.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_timer1(0),
|
||||||
|
m_age(0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
return new TestSAO(env, id, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 10)
|
||||||
|
{
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_base_position.Y += dtime * BS * 2;
|
||||||
|
if(m_base_position.Y > 8*BS)
|
||||||
|
m_base_position.Y = 2*BS;
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_timer1 -= dtime;
|
||||||
|
if(m_timer1 < 0.0)
|
||||||
|
{
|
||||||
|
m_timer1 += 0.125;
|
||||||
|
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
data += itos(0); // 0 = position
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.X);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Y);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Z);
|
||||||
|
|
||||||
|
ActiveObjectMessage aom(getId(), false, data);
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ItemSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
|
||||||
|
|
||||||
|
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string inventorystring):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_inventorystring(inventorystring),
|
||||||
|
m_speed_f(0,0,0),
|
||||||
|
m_last_sent_position(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
std::string inventorystring = deSerializeString(is);
|
||||||
|
dstream<<"ItemSAO::create(): Creating item \""
|
||||||
|
<<inventorystring<<"\""<<std::endl;
|
||||||
|
return new ItemSAO(env, id, pos, inventorystring);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
const float interval = 0.2;
|
||||||
|
if(m_move_interval.step(dtime, interval)==false)
|
||||||
|
return;
|
||||||
|
dtime = interval;
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||||
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[6];
|
||||||
|
// command (0 = update position)
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// pos
|
||||||
|
writeS32((u8*)buf, m_base_position.X*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[6];
|
||||||
|
// version
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// pos
|
||||||
|
writeS32((u8*)buf, m_base_position.X*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
// inventorystring
|
||||||
|
os<<serializeString(m_inventorystring);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemSAO::getStaticData()
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// version
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// inventorystring
|
||||||
|
os<<serializeString(m_inventorystring);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem * ItemSAO::createInventoryItem()
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||||
|
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||||
|
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||||
|
<<m_inventorystring<<"\" -> item="<<item
|
||||||
|
<<std::endl;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<": serialization error: "
|
||||||
|
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
return new RatSAO(env, id, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*m_age += dtime;
|
||||||
|
if(m_age > 60)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
if(player_is_close == false)
|
||||||
|
{
|
||||||
|
m_speed_f.X = 0;
|
||||||
|
m_speed_f.Z = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
m_speed_f.X = speed * dir.X;
|
||||||
|
m_speed_f.Z = speed * dir.Z;
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 1.0;
|
||||||
|
m_speed_f.Y = 5.0*BS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||||
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getStaticData()
|
||||||
|
{
|
||||||
|
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem* RatSAO::createPickedUpItem()
|
||||||
|
{
|
||||||
|
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
|
||||||
|
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1SAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Y is copied, X and Z change is limited
|
||||||
|
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||||
|
{
|
||||||
|
v3f d_wanted = target_speed - speed;
|
||||||
|
d_wanted.Y = 0;
|
||||||
|
f32 dl_wanted = d_wanted.getLength();
|
||||||
|
f32 dl = dl_wanted;
|
||||||
|
if(dl > max_increase)
|
||||||
|
dl = max_increase;
|
||||||
|
|
||||||
|
v3f d = d_wanted.normalize() * dl;
|
||||||
|
|
||||||
|
speed.X += d.X;
|
||||||
|
speed.Z += d.Z;
|
||||||
|
speed.Y = target_speed.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
m_hp = 20;
|
||||||
|
m_after_jump_timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// read version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// read hp
|
||||||
|
u8 hp = readU8(is);
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
|
||||||
|
o->m_hp = hp;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 120)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_after_jump_timer -= dtime;
|
||||||
|
|
||||||
|
v3f old_speed = m_speed_f;
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
bool player_is_too_close = false;
|
||||||
|
v3f near_player_pos;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||||
|
if(dist < BS*1.45)
|
||||||
|
{
|
||||||
|
player_is_too_close = true;
|
||||||
|
near_player_pos = playerpos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(dist < BS*15.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
near_player_pos = playerpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
v3f target_speed = m_speed_f;
|
||||||
|
|
||||||
|
if(!player_is_close)
|
||||||
|
{
|
||||||
|
target_speed = v3f(0,0,0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
|
||||||
|
v3f ndir = near_player_pos - m_base_position;
|
||||||
|
ndir.Y = 0;
|
||||||
|
ndir.normalize();
|
||||||
|
|
||||||
|
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
|
||||||
|
if(nyaw < m_yaw - 180)
|
||||||
|
nyaw += 360;
|
||||||
|
else if(nyaw > m_yaw + 180)
|
||||||
|
nyaw -= 360;
|
||||||
|
m_yaw = 0.95*m_yaw + 0.05*nyaw;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
|
||||||
|
if((m_touching_ground || m_after_jump_timer > 0.0)
|
||||||
|
&& !player_is_too_close)
|
||||||
|
{
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
target_speed.X = speed * dir.X;
|
||||||
|
target_speed.Z = speed * dir.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 0.2;
|
||||||
|
// Jump
|
||||||
|
target_speed.Y = 5.0*BS;
|
||||||
|
m_after_jump_timer = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
//m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*90;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close)
|
||||||
|
accelerate_xz(m_speed_f, target_speed, dtime*BS*8);
|
||||||
|
else
|
||||||
|
accelerate_xz(m_speed_f, target_speed, dtime*BS*4);
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
/*// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
moveresult = collisionMovePrecise(&m_env->getMap(), pos_max_d,
|
||||||
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
// Do collision damage
|
||||||
|
float tolerance = BS*12;
|
||||||
|
float factor = BS*0.5;
|
||||||
|
v3f speed_diff = old_speed - m_speed_f;
|
||||||
|
// Increase effect in X and Z
|
||||||
|
speed_diff.X *= 2;
|
||||||
|
speed_diff.Z *= 2;
|
||||||
|
float vel = speed_diff.getLength();
|
||||||
|
if(vel > tolerance)
|
||||||
|
{
|
||||||
|
f32 damage_f = (vel - tolerance)/BS*factor;
|
||||||
|
u16 damage = (u16)(damage_f+0.5);
|
||||||
|
doDamage(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false && m_speed_f.getLength() < 3.0*BS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getStaticData()
|
||||||
|
{
|
||||||
|
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// hp
|
||||||
|
writeU8(os, m_hp);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir)
|
||||||
|
{
|
||||||
|
m_speed_f += dir*12*BS;
|
||||||
|
|
||||||
|
u16 amount = 5;
|
||||||
|
doDamage(amount);
|
||||||
|
return 65536/100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::doDamage(u16 d)
|
||||||
|
{
|
||||||
|
dstream<<"oerkki damage: "<<d<<std::endl;
|
||||||
|
|
||||||
|
if(d < m_hp)
|
||||||
|
{
|
||||||
|
m_hp -= d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_hp = 0;
|
||||||
|
m_removed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (1 = damage)
|
||||||
|
writeU8(os, 1);
|
||||||
|
// amount
|
||||||
|
writeU8(os, d);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
118
src/content_sao.h
Normal file
118
src/content_sao.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_SAO_HEADER
|
||||||
|
#define CONTENT_SAO_HEADER
|
||||||
|
|
||||||
|
#include "serverobject.h"
|
||||||
|
#include "content_object.h"
|
||||||
|
|
||||||
|
class TestSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_TEST;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
private:
|
||||||
|
float m_timer1;
|
||||||
|
float m_age;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ItemSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string inventorystring);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_ITEM;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createInventoryItem();
|
||||||
|
InventoryItem* createPickedUpItem(){return createInventoryItem();}
|
||||||
|
private:
|
||||||
|
std::string m_inventorystring;
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
IntervalLimiter m_move_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RatSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_RAT;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createPickedUpItem();
|
||||||
|
private:
|
||||||
|
bool m_is_active;
|
||||||
|
IntervalLimiter m_inactive_interval;
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_oldpos;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
float m_yaw;
|
||||||
|
float m_counter1;
|
||||||
|
float m_counter2;
|
||||||
|
float m_age;
|
||||||
|
bool m_touching_ground;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Oerkki1SAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_OERKKI1;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
|
u16 punch(const std::string &toolname, v3f dir);
|
||||||
|
private:
|
||||||
|
void doDamage(u16 d);
|
||||||
|
|
||||||
|
bool m_is_active;
|
||||||
|
IntervalLimiter m_inactive_interval;
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_oldpos;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
float m_yaw;
|
||||||
|
float m_counter1;
|
||||||
|
float m_counter2;
|
||||||
|
float m_age;
|
||||||
|
bool m_touching_ground;
|
||||||
|
u8 m_hp;
|
||||||
|
float m_after_jump_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -42,6 +42,8 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("keymap_rangeselect", "KEY_KEY_R");
|
g_settings.setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||||
g_settings.setDefault("keymap_freemove", "KEY_KEY_K");
|
g_settings.setDefault("keymap_freemove", "KEY_KEY_K");
|
||||||
g_settings.setDefault("keymap_fastmove", "KEY_KEY_J");
|
g_settings.setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||||
|
g_settings.setDefault("keymap_frametime_graph", "KEY_F1");
|
||||||
|
g_settings.setDefault("keymap_screenshot", "KEY_F12");
|
||||||
// Some (temporary) keys for debugging
|
// Some (temporary) keys for debugging
|
||||||
g_settings.setDefault("keymap_special1", "KEY_KEY_E");
|
g_settings.setDefault("keymap_special1", "KEY_KEY_E");
|
||||||
g_settings.setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
g_settings.setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||||
@ -54,7 +56,7 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("screenH", "600");
|
g_settings.setDefault("screenH", "600");
|
||||||
g_settings.setDefault("address", "");
|
g_settings.setDefault("address", "");
|
||||||
g_settings.setDefault("random_input", "false");
|
g_settings.setDefault("random_input", "false");
|
||||||
g_settings.setDefault("client_delete_unused_sectors_timeout", "1200");
|
g_settings.setDefault("client_unload_unused_data_timeout", "600");
|
||||||
g_settings.setDefault("enable_fog", "true");
|
g_settings.setDefault("enable_fog", "true");
|
||||||
g_settings.setDefault("new_style_water", "false");
|
g_settings.setDefault("new_style_water", "false");
|
||||||
g_settings.setDefault("new_style_leaves", "true");
|
g_settings.setDefault("new_style_leaves", "true");
|
||||||
@ -72,6 +74,7 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("farmesh_distance", "40");
|
g_settings.setDefault("farmesh_distance", "40");
|
||||||
g_settings.setDefault("enable_clouds", "true");
|
g_settings.setDefault("enable_clouds", "true");
|
||||||
g_settings.setDefault("invisible_stone", "false");
|
g_settings.setDefault("invisible_stone", "false");
|
||||||
|
g_settings.setDefault("screenshot_path", ".");
|
||||||
|
|
||||||
// Server stuff
|
// Server stuff
|
||||||
g_settings.setDefault("enable_experimental", "false");
|
g_settings.setDefault("enable_experimental", "false");
|
||||||
@ -81,17 +84,19 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("default_password", "");
|
g_settings.setDefault("default_password", "");
|
||||||
g_settings.setDefault("default_privs", "build, shout");
|
g_settings.setDefault("default_privs", "build, shout");
|
||||||
g_settings.setDefault("profiler_print_interval", "0");
|
g_settings.setDefault("profiler_print_interval", "0");
|
||||||
|
g_settings.setDefault("enable_mapgen_debug_info", "false");
|
||||||
|
|
||||||
g_settings.setDefault("objectdata_interval", "0.2");
|
g_settings.setDefault("objectdata_interval", "0.2");
|
||||||
g_settings.setDefault("active_object_range", "2");
|
g_settings.setDefault("active_object_range", "2");
|
||||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||||
|
// This causes frametime jitter on client side, or does it?
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||||
g_settings.setDefault("max_block_send_distance", "8");
|
g_settings.setDefault("max_block_send_distance", "8");
|
||||||
g_settings.setDefault("max_block_generate_distance", "8");
|
g_settings.setDefault("max_block_generate_distance", "8");
|
||||||
g_settings.setDefault("time_send_interval", "20");
|
g_settings.setDefault("time_send_interval", "20");
|
||||||
g_settings.setDefault("time_speed", "96");
|
g_settings.setDefault("time_speed", "96");
|
||||||
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
g_settings.setDefault("server_unload_unused_data_timeout", "60");
|
||||||
g_settings.setDefault("server_map_save_interval", "60");
|
g_settings.setDefault("server_map_save_interval", "60");
|
||||||
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||||
//g_settings.setDefault("dungeon_rarity", "0.025");
|
//g_settings.setDefault("dungeon_rarity", "0.025");
|
||||||
|
@ -22,7 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
#include "serverobject.h"
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
Environment::Environment():
|
Environment::Environment():
|
||||||
m_time_of_day(9000)
|
m_time_of_day(9000)
|
||||||
@ -658,14 +660,6 @@ void ServerEnvironment::step(float dtime)
|
|||||||
m_game_time_fraction_counter -= (float)inc_i;
|
m_game_time_fraction_counter -= (float)inc_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Let map update it's timers
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
//TimeTaker timer("Server m_map->timerUpdate()");
|
|
||||||
m_map->timerUpdate(dtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handle players
|
Handle players
|
||||||
*/
|
*/
|
||||||
@ -868,6 +862,9 @@ void ServerEnvironment::step(float dtime)
|
|||||||
if(block==NULL)
|
if(block==NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Reset block usage timer
|
||||||
|
block->resetUsageTimer();
|
||||||
|
|
||||||
// Set current time as timestamp
|
// Set current time as timestamp
|
||||||
block->setTimestampNoChangedFlag(m_game_time);
|
block->setTimestampNoChangedFlag(m_game_time);
|
||||||
|
|
||||||
@ -986,8 +983,14 @@ void ServerEnvironment::step(float dtime)
|
|||||||
// Don't step if is to be removed or stored statically
|
// Don't step if is to be removed or stored statically
|
||||||
if(obj->m_removed || obj->m_pending_deactivation)
|
if(obj->m_removed || obj->m_pending_deactivation)
|
||||||
continue;
|
continue;
|
||||||
// Step object, putting messages directly to the queue
|
// Step object
|
||||||
obj->step(dtime, m_active_object_messages, send_recommended);
|
obj->step(dtime, send_recommended);
|
||||||
|
// Read messages from object
|
||||||
|
while(obj->m_messages_out.size() > 0)
|
||||||
|
{
|
||||||
|
m_active_object_messages.push_back(
|
||||||
|
obj->m_messages_out.pop_front());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1242,7 +1245,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
|||||||
block->setChangedFlag();
|
block->setChangedFlag();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
dstream<<"WARNING: Server: Could not find a block for "
|
dstream<<"WARNING: ServerEnv: Could not find a block for "
|
||||||
<<"storing newly added static active object"<<std::endl;
|
<<"storing newly added static active object"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1414,7 +1417,20 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||||||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
||||||
// Add to the block where the object is located in
|
// Add to the block where the object is located in
|
||||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
// Get or generate the block
|
||||||
|
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||||
|
|
||||||
|
/*MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block == NULL)
|
||||||
|
{
|
||||||
|
// Block not found. Is the old block still ok?
|
||||||
|
if(oldblock)
|
||||||
|
block = oldblock;
|
||||||
|
// Load from disk or generate
|
||||||
|
else
|
||||||
|
block = m_map->emergeBlock(blockpos);
|
||||||
|
}*/
|
||||||
|
|
||||||
if(block)
|
if(block)
|
||||||
{
|
{
|
||||||
block->m_static_objects.insert(0, s_obj);
|
block->m_static_objects.insert(0, s_obj);
|
||||||
@ -1422,17 +1438,9 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||||||
obj->m_static_exists = true;
|
obj->m_static_exists = true;
|
||||||
obj->m_static_block = block->getPos();
|
obj->m_static_block = block->getPos();
|
||||||
}
|
}
|
||||||
// If not possible, add back to previous block
|
|
||||||
else if(oldblock)
|
|
||||||
{
|
|
||||||
oldblock->m_static_objects.insert(0, s_obj);
|
|
||||||
oldblock->setChangedFlag();
|
|
||||||
obj->m_static_exists = true;
|
|
||||||
obj->m_static_block = oldblock->getPos();
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
dstream<<"WARNING: Server: Could not find a block for "
|
dstream<<"WARNING: ServerEnv: Could not find or generate "
|
||||||
<<"storing static object"<<std::endl;
|
<<"a block for storing static object"<<std::endl;
|
||||||
obj->m_static_exists = false;
|
obj->m_static_exists = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1526,11 +1534,6 @@ void ClientEnvironment::step(float dtime)
|
|||||||
bool free_move = g_settings.getBool("free_move");
|
bool free_move = g_settings.getBool("free_move");
|
||||||
bool footprints = g_settings.getBool("footprints");
|
bool footprints = g_settings.getBool("footprints");
|
||||||
|
|
||||||
{
|
|
||||||
//TimeTaker timer("Client m_map->timerUpdate()");
|
|
||||||
m_map->timerUpdate(dtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get local player
|
// Get local player
|
||||||
LocalPlayer *lplayer = getLocalPlayer();
|
LocalPlayer *lplayer = getLocalPlayer();
|
||||||
assert(lplayer);
|
assert(lplayer);
|
||||||
@ -1728,6 +1731,9 @@ void ClientEnvironment::step(float dtime)
|
|||||||
ClientActiveObject* obj = i.getNode()->getValue();
|
ClientActiveObject* obj = i.getNode()->getValue();
|
||||||
// Step object
|
// Step object
|
||||||
obj->step(dtime, this);
|
obj->step(dtime, this);
|
||||||
|
|
||||||
|
if(m_active_object_light_update_interval.step(dtime, 0.21))
|
||||||
|
{
|
||||||
// Update lighting
|
// Update lighting
|
||||||
//u8 light = LIGHT_MAX;
|
//u8 light = LIGHT_MAX;
|
||||||
u8 light = 0;
|
u8 light = 0;
|
||||||
@ -1741,6 +1747,7 @@ void ClientEnvironment::step(float dtime)
|
|||||||
obj->updateLight(light);
|
obj->updateLight(light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClientEnvironment::updateMeshes(v3s16 blockpos)
|
void ClientEnvironment::updateMeshes(v3s16 blockpos)
|
||||||
{
|
{
|
||||||
@ -1926,6 +1933,22 @@ ClientEnvEvent ClientEnvironment::getClientEvent()
|
|||||||
return m_client_event_queue.pop_front();
|
return m_client_event_queue.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos)
|
||||||
|
{
|
||||||
|
/*LocalPlayer *player = getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
v3f pos_f = player->getPosition() + v3f(0,BS*1.625,0);*/
|
||||||
|
v3f pos_f = camera_pos;
|
||||||
|
v3s16 p_nodes = floatToInt(pos_f, BS);
|
||||||
|
MapNode n = m_map->getNodeNoEx(p_nodes);
|
||||||
|
if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE)
|
||||||
|
{
|
||||||
|
v2u32 ss = driver->getScreenSize();
|
||||||
|
core::rect<s32> rect(0,0, ss.X, ss.Y);
|
||||||
|
driver->draw2DRectangle(video::SColor(64, 100, 100, 200), rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // #ifndef SERVER
|
#endif // #ifndef SERVER
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "activeobject.h"
|
||||||
|
|
||||||
|
class Server;
|
||||||
|
class ActiveBlockModifier;
|
||||||
|
class ServerActiveObject;
|
||||||
|
|
||||||
class Environment
|
class Environment
|
||||||
{
|
{
|
||||||
@ -118,11 +123,6 @@ private:
|
|||||||
This is not thread-safe. Server uses an environment mutex.
|
This is not thread-safe. Server uses an environment mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "serverobject.h"
|
|
||||||
|
|
||||||
class Server;
|
|
||||||
class ActiveBlockModifier;
|
|
||||||
|
|
||||||
class ServerEnvironment : public Environment
|
class ServerEnvironment : public Environment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -407,11 +407,15 @@ public:
|
|||||||
// Get event from queue. CEE_NONE is returned if queue is empty.
|
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||||
ClientEnvEvent getClientEvent();
|
ClientEnvEvent getClientEvent();
|
||||||
|
|
||||||
|
// Post effects
|
||||||
|
void drawPostFx(video::IVideoDriver* driver, v3f camera_pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClientMap *m_map;
|
ClientMap *m_map;
|
||||||
scene::ISceneManager *m_smgr;
|
scene::ISceneManager *m_smgr;
|
||||||
core::map<u16, ClientActiveObject*> m_active_objects;
|
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||||
Queue<ClientEnvEvent> m_client_event_queue;
|
Queue<ClientEnvEvent> m_client_event_queue;
|
||||||
|
IntervalLimiter m_active_object_light_update_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,7 +280,8 @@ void FarMesh::render()
|
|||||||
if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS)
|
if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS)
|
||||||
{
|
{
|
||||||
//c = video::SColor(255,59,86,146);
|
//c = video::SColor(255,59,86,146);
|
||||||
c = video::SColor(255,82,120,204);
|
//c = video::SColor(255,82,120,204);
|
||||||
|
c = video::SColor(255,74,105,170);
|
||||||
|
|
||||||
/*// Set to water level
|
/*// Set to water level
|
||||||
for(u32 i=0; i<4; i++)
|
for(u32 i=0; i<4; i++)
|
||||||
|
138
src/game.cpp
138
src/game.cpp
@ -30,8 +30,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include "farmesh.h"
|
#include "farmesh.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
|
||||||
// TODO: Move content-aware stuff to separate file
|
/*
|
||||||
|
TODO: Move content-aware stuff to separate file by adding properties
|
||||||
|
and virtual interfaces
|
||||||
|
*/
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
#include "content_nodemeta.h"
|
#include "content_nodemeta.h"
|
||||||
|
|
||||||
@ -672,6 +676,34 @@ void update_skybox(video::IVideoDriver* driver,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draws a screen with a single text on it.
|
||||||
|
Text will be removed when the screen is drawn the next time.
|
||||||
|
*/
|
||||||
|
/*gui::IGUIStaticText **/
|
||||||
|
void draw_load_screen(const std::wstring &text,
|
||||||
|
video::IVideoDriver* driver, gui::IGUIFont* font)
|
||||||
|
{
|
||||||
|
v2u32 screensize = driver->getScreenSize();
|
||||||
|
const wchar_t *loadingtext = text.c_str();
|
||||||
|
core::vector2d<u32> textsize_u = font->getDimension(loadingtext);
|
||||||
|
core::vector2d<s32> textsize(textsize_u.X,textsize_u.Y);
|
||||||
|
core::vector2d<s32> center(screensize.X/2, screensize.Y/2);
|
||||||
|
core::rect<s32> textrect(center - textsize/2, center + textsize/2);
|
||||||
|
|
||||||
|
gui::IGUIStaticText *guitext = guienv->addStaticText(
|
||||||
|
loadingtext, textrect, false, false);
|
||||||
|
guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
|
||||||
|
|
||||||
|
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||||
|
guienv->drawAll();
|
||||||
|
driver->endScene();
|
||||||
|
|
||||||
|
guitext->remove();
|
||||||
|
|
||||||
|
//return guitext;
|
||||||
|
}
|
||||||
|
|
||||||
void the_game(
|
void the_game(
|
||||||
bool &kill,
|
bool &kill,
|
||||||
bool random_input,
|
bool random_input,
|
||||||
@ -689,12 +721,17 @@ void the_game(
|
|||||||
video::IVideoDriver* driver = device->getVideoDriver();
|
video::IVideoDriver* driver = device->getVideoDriver();
|
||||||
scene::ISceneManager* smgr = device->getSceneManager();
|
scene::ISceneManager* smgr = device->getSceneManager();
|
||||||
|
|
||||||
|
// Calculate text height using the font
|
||||||
|
u32 text_height = font->getDimension(L"Random test string").Height;
|
||||||
|
|
||||||
v2u32 screensize(0,0);
|
v2u32 screensize(0,0);
|
||||||
v2u32 last_screensize(0,0);
|
v2u32 last_screensize(0,0);
|
||||||
screensize = driver->getScreenSize();
|
screensize = driver->getScreenSize();
|
||||||
|
|
||||||
const s32 hotbar_itemcount = 8;
|
const s32 hotbar_itemcount = 8;
|
||||||
const s32 hotbar_imagesize = 36;
|
//const s32 hotbar_imagesize = 36;
|
||||||
|
//const s32 hotbar_imagesize = 64;
|
||||||
|
s32 hotbar_imagesize = 48;
|
||||||
|
|
||||||
// The color of the sky
|
// The color of the sky
|
||||||
|
|
||||||
@ -705,20 +742,10 @@ void the_game(
|
|||||||
/*
|
/*
|
||||||
Draw "Loading" screen
|
Draw "Loading" screen
|
||||||
*/
|
*/
|
||||||
const wchar_t *loadingtext = L"Loading and connecting...";
|
/*gui::IGUIStaticText *gui_loadingtext = */
|
||||||
u32 text_height = font->getDimension(loadingtext).Height;
|
//draw_load_screen(L"Loading and connecting...", driver, font);
|
||||||
core::vector2d<s32> center(screensize.X/2, screensize.Y/2);
|
|
||||||
core::vector2d<s32> textsize(300, text_height);
|
|
||||||
core::rect<s32> textrect(center - textsize/2, center + textsize/2);
|
|
||||||
|
|
||||||
gui::IGUIStaticText *gui_loadingtext = guienv->addStaticText(
|
|
||||||
loadingtext, textrect, false, false);
|
|
||||||
gui_loadingtext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
|
|
||||||
|
|
||||||
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
|
||||||
guienv->drawAll();
|
|
||||||
driver->endScene();
|
|
||||||
|
|
||||||
|
draw_load_screen(L"Loading...", driver, font);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create server.
|
Create server.
|
||||||
@ -726,6 +753,7 @@ void the_game(
|
|||||||
*/
|
*/
|
||||||
SharedPtr<Server> server;
|
SharedPtr<Server> server;
|
||||||
if(address == ""){
|
if(address == ""){
|
||||||
|
draw_load_screen(L"Creating server...", driver, font);
|
||||||
std::cout<<DTIME<<"Creating server"<<std::endl;
|
std::cout<<DTIME<<"Creating server"<<std::endl;
|
||||||
server = new Server(map_dir);
|
server = new Server(map_dir);
|
||||||
server->start(port);
|
server->start(port);
|
||||||
@ -735,9 +763,11 @@ void the_game(
|
|||||||
Create client
|
Create client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
draw_load_screen(L"Creating client...", driver, font);
|
||||||
std::cout<<DTIME<<"Creating client"<<std::endl;
|
std::cout<<DTIME<<"Creating client"<<std::endl;
|
||||||
Client client(device, playername.c_str(), password, draw_control);
|
Client client(device, playername.c_str(), password, draw_control);
|
||||||
|
|
||||||
|
draw_load_screen(L"Resolving address...", driver, font);
|
||||||
Address connect_address(0,0,0,0, port);
|
Address connect_address(0,0,0,0, port);
|
||||||
try{
|
try{
|
||||||
if(address == "")
|
if(address == "")
|
||||||
@ -751,7 +781,7 @@ void the_game(
|
|||||||
std::cout<<DTIME<<"Couldn't resolve address"<<std::endl;
|
std::cout<<DTIME<<"Couldn't resolve address"<<std::endl;
|
||||||
//return 0;
|
//return 0;
|
||||||
error_message = L"Couldn't resolve address";
|
error_message = L"Couldn't resolve address";
|
||||||
gui_loadingtext->remove();
|
//gui_loadingtext->remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,10 +815,16 @@ void the_game(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update screen
|
std::wostringstream ss;
|
||||||
|
ss<<L"Connecting to server... (timeout in ";
|
||||||
|
ss<<(int)(10.0 - time_counter + 1.0);
|
||||||
|
ss<<L" seconds)";
|
||||||
|
draw_load_screen(ss.str(), driver, font);
|
||||||
|
|
||||||
|
/*// Update screen
|
||||||
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||||
guienv->drawAll();
|
guienv->drawAll();
|
||||||
driver->endScene();
|
driver->endScene();*/
|
||||||
|
|
||||||
// Update client and server
|
// Update client and server
|
||||||
|
|
||||||
@ -818,7 +854,7 @@ void the_game(
|
|||||||
error_message = L"Connection timed out.";
|
error_message = L"Connection timed out.";
|
||||||
std::cout<<DTIME<<"Timed out."<<std::endl;
|
std::cout<<DTIME<<"Timed out."<<std::endl;
|
||||||
}
|
}
|
||||||
gui_loadingtext->remove();
|
//gui_loadingtext->remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +916,7 @@ void the_game(
|
|||||||
Move into game
|
Move into game
|
||||||
*/
|
*/
|
||||||
|
|
||||||
gui_loadingtext->remove();
|
//gui_loadingtext->remove();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add some gui stuff
|
Add some gui stuff
|
||||||
@ -973,6 +1009,8 @@ void the_game(
|
|||||||
|
|
||||||
while(device->run() && kill == false)
|
while(device->run() && kill == false)
|
||||||
{
|
{
|
||||||
|
//std::cerr<<"frame"<<std::endl;
|
||||||
|
|
||||||
if(g_gamecallback->disconnect_requested)
|
if(g_gamecallback->disconnect_requested)
|
||||||
{
|
{
|
||||||
g_gamecallback->disconnect_requested = false;
|
g_gamecallback->disconnect_requested = false;
|
||||||
@ -999,6 +1037,14 @@ void the_game(
|
|||||||
v2s32 displaycenter(screensize.X/2,screensize.Y/2);
|
v2s32 displaycenter(screensize.X/2,screensize.Y/2);
|
||||||
//bool screensize_changed = screensize != last_screensize;
|
//bool screensize_changed = screensize != last_screensize;
|
||||||
|
|
||||||
|
// Resize hotbar
|
||||||
|
if(screensize.Y <= 600)
|
||||||
|
hotbar_imagesize = 32;
|
||||||
|
else if(screensize.Y <= 1024)
|
||||||
|
hotbar_imagesize = 48;
|
||||||
|
else
|
||||||
|
hotbar_imagesize = 64;
|
||||||
|
|
||||||
// Hilight boxes collected during the loop and displayed
|
// Hilight boxes collected during the loop and displayed
|
||||||
core::list< core::aabbox3d<f32> > hilightboxes;
|
core::list< core::aabbox3d<f32> > hilightboxes;
|
||||||
|
|
||||||
@ -1090,7 +1136,7 @@ void the_game(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static f32 dtime_avg1 = 0.0;
|
static f32 dtime_avg1 = 0.0;
|
||||||
dtime_avg1 = dtime_avg1 * 0.98 + dtime * 0.02;
|
dtime_avg1 = dtime_avg1 * 0.96 + dtime * 0.04;
|
||||||
f32 dtime_jitter1 = dtime - dtime_avg1;
|
f32 dtime_jitter1 = dtime - dtime_avg1;
|
||||||
|
|
||||||
static f32 dtime_jitter1_max_sample = 0.0;
|
static f32 dtime_jitter1_max_sample = 0.0;
|
||||||
@ -1254,6 +1300,38 @@ void the_game(
|
|||||||
chat_lines.push_back(ChatLine(L"fast_move enabled"));
|
chat_lines.push_back(ChatLine(L"fast_move enabled"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(input->wasKeyDown(getKeySetting("keymap_frametime_graph")))
|
||||||
|
{
|
||||||
|
if(g_settings.getBool("frametime_graph"))
|
||||||
|
{
|
||||||
|
g_settings.set("frametime_graph","false");
|
||||||
|
chat_lines.push_back(ChatLine(L"frametime_graph disabled"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_settings.set("frametime_graph","true");
|
||||||
|
chat_lines.push_back(ChatLine(L"frametime_graph enabled"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(input->wasKeyDown(getKeySetting("keymap_screenshot")))
|
||||||
|
{
|
||||||
|
irr::video::IImage* const image = driver->createScreenShot();
|
||||||
|
if (image) {
|
||||||
|
irr::c8 filename[256];
|
||||||
|
snprintf(filename, 256, "%s/screenshot_%u.png",
|
||||||
|
g_settings.get("screenshot_path").c_str(),
|
||||||
|
device->getTimer()->getRealTime());
|
||||||
|
if (driver->writeImageToFile(image, filename)) {
|
||||||
|
std::wstringstream sstr;
|
||||||
|
sstr<<"Saved screenshot to '"<<filename<<"'";
|
||||||
|
dstream<<"Saved screenshot to '"<<filename<<"'"<<std::endl;
|
||||||
|
chat_lines.push_back(ChatLine(sstr.str()));
|
||||||
|
} else{
|
||||||
|
dstream<<"Failed to save screenshot '"<<filename<<"'"<<std::endl;
|
||||||
|
}
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Item selection with mouse wheel
|
// Item selection with mouse wheel
|
||||||
{
|
{
|
||||||
@ -2195,6 +2273,13 @@ void the_game(
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Environment post fx
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
client.getEnv()->drawPostFx(driver, camera_position);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
End scene
|
End scene
|
||||||
*/
|
*/
|
||||||
@ -2237,15 +2322,12 @@ void the_game(
|
|||||||
generator and other stuff quits
|
generator and other stuff quits
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
const wchar_t *shuttingdowntext = L"Shutting down stuff...";
|
/*gui::IGUIStaticText *gui_shuttingdowntext = */
|
||||||
gui::IGUIStaticText *gui_shuttingdowntext = guienv->addStaticText(
|
draw_load_screen(L"Shutting down stuff...", driver, font);
|
||||||
shuttingdowntext, textrect, false, false);
|
/*driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||||
gui_shuttingdowntext->setTextAlignment(gui::EGUIA_CENTER,
|
|
||||||
gui::EGUIA_UPPERLEFT);
|
|
||||||
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
|
||||||
guienv->drawAll();
|
guienv->drawAll();
|
||||||
driver->endScene();
|
driver->endScene();
|
||||||
gui_shuttingdowntext->remove();
|
gui_shuttingdowntext->remove();*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
#include "content_inventory.h"
|
#include "content_inventory.h"
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InventoryItem
|
InventoryItem
|
||||||
|
153
src/main.cpp
153
src/main.cpp
@ -27,6 +27,33 @@ NOTE: Global locale is now set at initialization
|
|||||||
NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the
|
NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the
|
||||||
hardware buffer (it is not freed automatically)
|
hardware buffer (it is not freed automatically)
|
||||||
|
|
||||||
|
NOTE: A random to-do list saved here as documentation:
|
||||||
|
A list of "active blocks" in which stuff happens. (+=done)
|
||||||
|
+ Add a never-resetted game timer to the server
|
||||||
|
+ Add a timestamp value to blocks
|
||||||
|
+ The simple rule: All blocks near some player are "active"
|
||||||
|
- Do stuff in real time in active blocks
|
||||||
|
+ Handle objects
|
||||||
|
- Grow grass, delete leaves without a tree
|
||||||
|
- Spawn some mobs based on some rules
|
||||||
|
- Transform cobble to mossy cobble near water
|
||||||
|
- Run a custom script
|
||||||
|
- ...And all kinds of other dynamic stuff
|
||||||
|
+ Keep track of when a block becomes active and becomes inactive
|
||||||
|
+ When a block goes inactive:
|
||||||
|
+ Store objects statically to block
|
||||||
|
+ Store timer value as the timestamp
|
||||||
|
+ When a block goes active:
|
||||||
|
+ Create active objects out of static objects
|
||||||
|
- Simulate the results of what would have happened if it would have
|
||||||
|
been active for all the time
|
||||||
|
- Grow a lot of grass and so on
|
||||||
|
+ Initially it is fine to send information about every active object
|
||||||
|
to every player. Eventually it should be modified to only send info
|
||||||
|
about the nearest ones.
|
||||||
|
+ This was left to be done by the old system and it sends only the
|
||||||
|
nearest ones.
|
||||||
|
|
||||||
Old, wild and random suggestions that probably won't be done:
|
Old, wild and random suggestions that probably won't be done:
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|
||||||
@ -73,9 +100,6 @@ SUGG: Make the amount of blocks sending to client and the total
|
|||||||
SUGG: Meshes of blocks could be split into 6 meshes facing into
|
SUGG: Meshes of blocks could be split into 6 meshes facing into
|
||||||
different directions and then only those drawn that need to be
|
different directions and then only those drawn that need to be
|
||||||
|
|
||||||
SUGG: Calculate lighting per vertex to get a lighting effect like in
|
|
||||||
bartwe's game
|
|
||||||
|
|
||||||
SUGG: Background music based on cellular automata?
|
SUGG: Background music based on cellular automata?
|
||||||
http://www.earslap.com/projectslab/otomata
|
http://www.earslap.com/projectslab/otomata
|
||||||
|
|
||||||
@ -90,6 +114,8 @@ SUGG: Make a system for pregenerating quick information for mapblocks, so
|
|||||||
or even generated.
|
or even generated.
|
||||||
|
|
||||||
SUGG: Erosion simulation at map generation time
|
SUGG: Erosion simulation at map generation time
|
||||||
|
- This might be plausible if larger areas of map were pregenerated
|
||||||
|
without lighting (which is slow)
|
||||||
- Simulate water flows, which would carve out dirt fast and
|
- Simulate water flows, which would carve out dirt fast and
|
||||||
then turn stone into gravel and sand and relocate it.
|
then turn stone into gravel and sand and relocate it.
|
||||||
- How about relocating minerals, too? Coal and gold in
|
- How about relocating minerals, too? Coal and gold in
|
||||||
@ -100,6 +126,16 @@ SUGG: Erosion simulation at map generation time
|
|||||||
- Simulate rock falling from cliffs when water has removed
|
- Simulate rock falling from cliffs when water has removed
|
||||||
enough solid rock from the bottom
|
enough solid rock from the bottom
|
||||||
|
|
||||||
|
SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface
|
||||||
|
stuff as simple flags/values
|
||||||
|
- Light?
|
||||||
|
- A building?
|
||||||
|
And at some point make the server send this data to the client too,
|
||||||
|
instead of referring to the noise functions
|
||||||
|
- Ground height
|
||||||
|
- Surface ground type
|
||||||
|
- Trees?
|
||||||
|
|
||||||
Gaming ideas:
|
Gaming ideas:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -173,12 +209,13 @@ SUGG: Make fetching sector's blocks more efficient when rendering
|
|||||||
sectors that have very large amounts of blocks (on client)
|
sectors that have very large amounts of blocks (on client)
|
||||||
- Is this necessary at all?
|
- Is this necessary at all?
|
||||||
|
|
||||||
TODO: Flowing water animation
|
|
||||||
|
|
||||||
SUGG: Draw cubes in inventory directly with 3D drawing commands, so that
|
SUGG: Draw cubes in inventory directly with 3D drawing commands, so that
|
||||||
animating them is easier.
|
animating them is easier.
|
||||||
|
|
||||||
SUGG: Option for enabling proper alpha channel for textures
|
SUGG: Option for enabling proper alpha channel for textures
|
||||||
|
|
||||||
|
TODO: Flowing water animation
|
||||||
|
|
||||||
TODO: A setting for enabling bilinear filtering for textures
|
TODO: A setting for enabling bilinear filtering for textures
|
||||||
|
|
||||||
TODO: Better control of draw_control.wanted_max_blocks
|
TODO: Better control of draw_control.wanted_max_blocks
|
||||||
@ -193,6 +230,12 @@ TODO: Artificial (night) light could be more yellow colored than sunlight.
|
|||||||
|
|
||||||
SUGG: Somehow make the night less colorful
|
SUGG: Somehow make the night less colorful
|
||||||
|
|
||||||
|
TODO: Occlusion culling
|
||||||
|
- At the same time, move some of the renderMap() block choosing code
|
||||||
|
to the same place as where the new culling happens.
|
||||||
|
- Shoot some rays per frame and when ready, make a new list of
|
||||||
|
blocks for usage of renderMap and give it a new pointer to it.
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -231,6 +274,7 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
|
|||||||
* Fix the problem with the server constantly saving one or a few
|
* Fix the problem with the server constantly saving one or a few
|
||||||
blocks? List the first saved block, maybe it explains.
|
blocks? List the first saved block, maybe it explains.
|
||||||
- It is probably caused by oscillating water
|
- It is probably caused by oscillating water
|
||||||
|
- TODO: Investigate if this still happens (this is a very old one)
|
||||||
* Make a small history check to transformLiquids to detect and log
|
* Make a small history check to transformLiquids to detect and log
|
||||||
continuous oscillations, in such detail that they can be fixed.
|
continuous oscillations, in such detail that they can be fixed.
|
||||||
|
|
||||||
@ -238,44 +282,12 @@ FIXME: The new optimized map sending doesn't sometimes send enough blocks
|
|||||||
from big caves and such
|
from big caves and such
|
||||||
FIXME: Block send distance configuration does not take effect for some reason
|
FIXME: Block send distance configuration does not take effect for some reason
|
||||||
|
|
||||||
TODO: Map saving should be done by EmergeThread
|
|
||||||
|
|
||||||
SUGG: Map unloading based on sector reference is not very good, it keeps
|
|
||||||
unnecessary stuff in memory. I guess. Investigate this.
|
|
||||||
|
|
||||||
TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set
|
|
||||||
the direction accordingly.
|
|
||||||
|
|
||||||
Environment:
|
Environment:
|
||||||
------------
|
------------
|
||||||
|
|
||||||
TODO: A list of "active blocks" in which stuff happens. (+=done)
|
TODO: Add proper hooks to when adding and removing active blocks
|
||||||
+ Add a never-resetted game timer to the server
|
|
||||||
+ Add a timestamp value to blocks
|
TODO: Finish the ActiveBlockModifier stuff and use it for something
|
||||||
+ The simple rule: All blocks near some player are "active"
|
|
||||||
- Do stuff in real time in active blocks
|
|
||||||
+ Handle objects
|
|
||||||
TODO: Make proper hooks in here
|
|
||||||
- Grow grass, delete leaves without a tree
|
|
||||||
- Spawn some mobs based on some rules
|
|
||||||
- Transform cobble to mossy cobble near water
|
|
||||||
- Run a custom script
|
|
||||||
- ...And all kinds of other dynamic stuff
|
|
||||||
+ Keep track of when a block becomes active and becomes inactive
|
|
||||||
+ When a block goes inactive:
|
|
||||||
+ Store objects statically to block
|
|
||||||
+ Store timer value as the timestamp
|
|
||||||
+ When a block goes active:
|
|
||||||
+ Create active objects out of static objects
|
|
||||||
TODO: Make proper hooks in here
|
|
||||||
- Simulate the results of what would have happened if it would have
|
|
||||||
been active for all the time
|
|
||||||
- Grow a lot of grass and so on
|
|
||||||
+ Initially it is fine to send information about every active object
|
|
||||||
to every player. Eventually it should be modified to only send info
|
|
||||||
about the nearest ones.
|
|
||||||
+ This was left to be done by the old system and it sends only the
|
|
||||||
nearest ones.
|
|
||||||
|
|
||||||
Objects:
|
Objects:
|
||||||
--------
|
--------
|
||||||
@ -287,6 +299,7 @@ TODO: Get rid of MapBlockObjects and use only ActiveObjects
|
|||||||
|
|
||||||
SUGG: MovingObject::move and Player::move are basically the same.
|
SUGG: MovingObject::move and Player::move are basically the same.
|
||||||
combine them.
|
combine them.
|
||||||
|
- NOTE: This is a bit tricky because player has the sneaking ability
|
||||||
- NOTE: Player::move is more up-to-date.
|
- NOTE: Player::move is more up-to-date.
|
||||||
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
||||||
- NOTE: MovingObject will be deleted (MapBlockObject)
|
- NOTE: MovingObject will be deleted (MapBlockObject)
|
||||||
@ -305,59 +318,25 @@ TODO: Mineral and ground material properties
|
|||||||
TODO: Flowing water to actually contain flow direction information
|
TODO: Flowing water to actually contain flow direction information
|
||||||
- There is a space for this - it just has to be implemented.
|
- There is a space for this - it just has to be implemented.
|
||||||
|
|
||||||
SUGG: Try out the notch way of generating maps, that is, make bunches
|
TODO: Consider smoothening cave floors after generating them
|
||||||
of low-res 3d noise and interpolate linearly.
|
|
||||||
|
|
||||||
Mapgen v2 (the current one):
|
|
||||||
* Possibly add some kind of erosion and other stuff
|
|
||||||
* Better water generation (spread it to underwater caverns but don't
|
|
||||||
fill dungeons that don't touch big water masses)
|
|
||||||
* When generating a chunk and the neighboring chunk doesn't have mud
|
|
||||||
and stuff yet and the ground is fairly flat, the mud will flow to
|
|
||||||
the other chunk making nasty straight walls when the other chunk
|
|
||||||
is generated. Fix it. Maybe just a special case if the ground is
|
|
||||||
flat?
|
|
||||||
* Consider not updating this one and make a good mainly block-based
|
|
||||||
generator
|
|
||||||
|
|
||||||
SUGG: Make two "modified states", one that forces the block to be saved at
|
|
||||||
the next save event, and one that makes the block to be saved at exit
|
|
||||||
time.
|
|
||||||
|
|
||||||
TODO: Add a not_fully_generated flag to MapBlock, which would be set for
|
|
||||||
blocks that contain eg. trees from neighboring generations but haven't
|
|
||||||
been generated itself. This is required for the future generator.
|
|
||||||
|
|
||||||
Misc. stuff:
|
Misc. stuff:
|
||||||
------------
|
------------
|
||||||
- Make sure server handles removing grass when a block is placed (etc)
|
TODO: Make sure server handles removing grass when a block is placed (etc)
|
||||||
- The client should not do it by itself
|
- The client should not do it by itself
|
||||||
- Block cube placement around player's head
|
- NOTE: I think nobody does it currently...
|
||||||
- Protocol version field
|
TODO: Block cube placement around player's head
|
||||||
- Consider getting some textures from cisoun's texture pack
|
TODO: Protocol version field
|
||||||
- Ask from Cisoun
|
TODO: Think about using same bits for material for fences and doors, for
|
||||||
- Make sure the fence implementation and data format is good
|
|
||||||
- Think about using same bits for material for fences and doors, for
|
|
||||||
example
|
example
|
||||||
- Finish the ActiveBlockModifier stuff and use it for something
|
TODO: Move mineral to param2, increment map serialization version, add
|
||||||
- Move mineral to param2, increment map serialization version, add conversion
|
conversion
|
||||||
|
|
||||||
TODO: Add a per-sector database to store surface stuff as simple flags/values
|
|
||||||
- Light?
|
|
||||||
- A building?
|
|
||||||
And at some point make the server send this data to the client too,
|
|
||||||
instead of referring to the noise functions
|
|
||||||
- Ground height
|
|
||||||
- Surface ground type
|
|
||||||
- Trees?
|
|
||||||
|
|
||||||
TODO: Restart irrlicht completely when coming back to main menu from game.
|
TODO: Restart irrlicht completely when coming back to main menu from game.
|
||||||
- This gets rid of everything that is stored in irrlicht's caches.
|
- This gets rid of everything that is stored in irrlicht's caches.
|
||||||
|
|
||||||
TODO: Merge bahamada's audio stuff (clean patch available)
|
TODO: Merge bahamada's audio stuff (clean patch available)
|
||||||
|
|
||||||
TODO: Merge spongie's chest/furnace direction (by hand)
|
|
||||||
|
|
||||||
TODO: Merge key configuration menu (no clean patch available)
|
TODO: Merge key configuration menu (no clean patch available)
|
||||||
|
|
||||||
Making it more portable:
|
Making it more portable:
|
||||||
@ -375,9 +354,6 @@ Stuff to do after release:
|
|||||||
Doing currently:
|
Doing currently:
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
|
||||||
(on client and server)
|
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -406,16 +382,12 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
//#include <jmutexautolock.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
//#include "map.h"
|
|
||||||
//#include "player.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
//#include "client.h"
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
@ -424,11 +396,10 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "guiMainMenu.h"
|
#include "guiMainMenu.h"
|
||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
//#include "noise.h"
|
|
||||||
//#include "tile.h"
|
|
||||||
#include "materials.h"
|
#include "materials.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
|
#include "tile.h"
|
||||||
|
|
||||||
// This makes textures
|
// This makes textures
|
||||||
ITextureSource *g_texturesource = NULL;
|
ITextureSource *g_texturesource = NULL;
|
||||||
|
@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
extern Settings g_settings;
|
extern Settings g_settings;
|
||||||
|
|
||||||
// This makes and maps textures
|
// This makes and maps textures
|
||||||
#include "tile.h"
|
class ITextureSource;
|
||||||
extern ITextureSource *g_texturesource;
|
extern ITextureSource *g_texturesource;
|
||||||
|
|
||||||
// Global profiler
|
// Global profiler
|
||||||
|
367
src/map.cpp
367
src/map.cpp
@ -18,18 +18,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "mapsector.h"
|
||||||
|
#include "mapblock.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "jmutexautolock.h"
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "mineral.h"
|
|
||||||
#include "noise.h"
|
|
||||||
#include "serverobject.h"
|
|
||||||
#include "content_mapnode.h"
|
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
#include "nodemetadata.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
@ -122,42 +120,23 @@ MapSector * Map::getSectorNoGenerate(v2s16 p)
|
|||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock * Map::getBlockNoCreate(v3s16 p3d)
|
|
||||||
{
|
|
||||||
v2s16 p2d(p3d.X, p3d.Z);
|
|
||||||
MapSector * sector = getSectorNoGenerate(p2d);
|
|
||||||
|
|
||||||
MapBlock *block = sector->getBlockNoCreate(p3d.Y);
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d)
|
MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
v2s16 p2d(p3d.X, p3d.Z);
|
v2s16 p2d(p3d.X, p3d.Z);
|
||||||
MapSector * sector = getSectorNoGenerate(p2d);
|
MapSector * sector = getSectorNoGenerateNoEx(p2d);
|
||||||
MapBlock *block = sector->getBlockNoCreate(p3d.Y);
|
if(sector == NULL)
|
||||||
return block;
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y);
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*MapBlock * Map::getBlockCreate(v3s16 p3d)
|
MapBlock * Map::getBlockNoCreate(v3s16 p3d)
|
||||||
{
|
{
|
||||||
v2s16 p2d(p3d.X, p3d.Z);
|
MapBlock *block = getBlockNoCreateNoEx(p3d);
|
||||||
MapSector * sector = getSectorCreate(p2d);
|
if(block == NULL)
|
||||||
assert(sector);
|
throw InvalidPositionException();
|
||||||
MapBlock *block = sector->getBlockNoCreate(p3d.Y);
|
|
||||||
if(block)
|
|
||||||
return block;
|
return block;
|
||||||
block = sector->createBlankBlock(p3d.Y);
|
}
|
||||||
return block;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool Map::isNodeUnderground(v3s16 p)
|
bool Map::isNodeUnderground(v3s16 p)
|
||||||
{
|
{
|
||||||
@ -172,6 +151,45 @@ bool Map::isNodeUnderground(v3s16 p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Map::isValidPosition(v3s16 p)
|
||||||
|
{
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
|
MapBlock *block = getBlockNoCreate(blockpos);
|
||||||
|
return (block != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a CONTENT_IGNORE node if not found
|
||||||
|
MapNode Map::getNodeNoEx(v3s16 p)
|
||||||
|
{
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block == NULL)
|
||||||
|
return MapNode(CONTENT_IGNORE);
|
||||||
|
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||||
|
return block->getNodeNoCheck(relpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// throws InvalidPositionException if not found
|
||||||
|
MapNode Map::getNode(v3s16 p)
|
||||||
|
{
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block == NULL)
|
||||||
|
throw InvalidPositionException();
|
||||||
|
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||||
|
return block->getNodeNoCheck(relpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// throws InvalidPositionException if not found
|
||||||
|
void Map::setNode(v3s16 p, MapNode & n)
|
||||||
|
{
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
|
MapBlock *block = getBlockNoCreate(blockpos);
|
||||||
|
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||||
|
block->setNodeNoCheck(relpos, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Goes recursively through the neighbours of the node.
|
Goes recursively through the neighbours of the node.
|
||||||
|
|
||||||
@ -738,6 +756,25 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Enable this to disable proper lighting for speeding up map
|
||||||
|
generation for testing or whatever
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
//if(g_settings.get(""))
|
||||||
|
{
|
||||||
|
core::map<v3s16, MapBlock*>::Iterator i;
|
||||||
|
i = blocks_to_update.getIterator();
|
||||||
|
for(; i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
MapBlock *block = i.getNode()->getValue();
|
||||||
|
v3s16 p = block->getPos();
|
||||||
|
block->setLightingExpired(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
TimeTaker timer("unspreadLight");
|
TimeTaker timer("unspreadLight");
|
||||||
@ -879,7 +916,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
/*
|
/*
|
||||||
If the new node is solid and there is grass below, change it to mud
|
If the new node is solid and there is grass below, change it to mud
|
||||||
*/
|
*/
|
||||||
@ -1357,9 +1394,14 @@ bool Map::dayNightDiffed(v3s16 blockpos)
|
|||||||
/*
|
/*
|
||||||
Updates usage timers
|
Updates usage timers
|
||||||
*/
|
*/
|
||||||
void Map::timerUpdate(float dtime)
|
void Map::timerUpdate(float dtime, float unload_timeout,
|
||||||
|
core::list<v3s16> *unloaded_blocks)
|
||||||
{
|
{
|
||||||
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
|
||||||
|
|
||||||
|
core::list<v2s16> sector_deletion_queue;
|
||||||
|
u32 deleted_blocks_count = 0;
|
||||||
|
u32 saved_blocks_count = 0;
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Iterator si;
|
core::map<v2s16, MapSector*>::Iterator si;
|
||||||
|
|
||||||
@ -1368,48 +1410,85 @@ void Map::timerUpdate(float dtime)
|
|||||||
{
|
{
|
||||||
MapSector *sector = si.getNode()->getValue();
|
MapSector *sector = si.getNode()->getValue();
|
||||||
|
|
||||||
|
bool all_blocks_deleted = true;
|
||||||
|
|
||||||
core::list<MapBlock*> blocks;
|
core::list<MapBlock*> blocks;
|
||||||
sector->getBlocks(blocks);
|
sector->getBlocks(blocks);
|
||||||
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
||||||
i != blocks.end(); i++)
|
i != blocks.end(); i++)
|
||||||
{
|
{
|
||||||
(*i)->incrementUsageTimer(dtime);
|
MapBlock *block = (*i);
|
||||||
|
|
||||||
|
block->incrementUsageTimer(dtime);
|
||||||
|
|
||||||
|
if(block->getUsageTimer() > unload_timeout)
|
||||||
|
{
|
||||||
|
v3s16 p = block->getPos();
|
||||||
|
|
||||||
|
// Save if modified
|
||||||
|
if(block->getModified() != MOD_STATE_CLEAN
|
||||||
|
&& save_before_unloading)
|
||||||
|
{
|
||||||
|
saveBlock(block);
|
||||||
|
saved_blocks_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete from memory
|
||||||
|
sector->deleteBlock(block);
|
||||||
|
|
||||||
|
if(unloaded_blocks)
|
||||||
|
unloaded_blocks->push_back(p);
|
||||||
|
|
||||||
|
deleted_blocks_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
all_blocks_deleted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::deleteSectors(core::list<v2s16> &list, bool only_blocks)
|
if(all_blocks_deleted)
|
||||||
|
{
|
||||||
|
sector_deletion_queue.push_back(si.getNode()->getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally delete the empty sectors
|
||||||
|
deleteSectors(sector_deletion_queue);
|
||||||
|
|
||||||
|
if(deleted_blocks_count != 0)
|
||||||
|
{
|
||||||
|
PrintInfo(dstream); // ServerMap/ClientMap:
|
||||||
|
dstream<<"Unloaded "<<deleted_blocks_count
|
||||||
|
<<" blocks from memory";
|
||||||
|
if(save_before_unloading)
|
||||||
|
dstream<<", of which "<<saved_blocks_count<<" were written";
|
||||||
|
dstream<<"."<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::deleteSectors(core::list<v2s16> &list)
|
||||||
{
|
{
|
||||||
core::list<v2s16>::Iterator j;
|
core::list<v2s16>::Iterator j;
|
||||||
for(j=list.begin(); j!=list.end(); j++)
|
for(j=list.begin(); j!=list.end(); j++)
|
||||||
{
|
{
|
||||||
MapSector *sector = m_sectors[*j];
|
MapSector *sector = m_sectors[*j];
|
||||||
if(only_blocks)
|
// If sector is in sector cache, remove it from there
|
||||||
{
|
|
||||||
sector->deleteBlocks();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
If sector is in sector cache, remove it from there
|
|
||||||
*/
|
|
||||||
if(m_sector_cache == sector)
|
if(m_sector_cache == sector)
|
||||||
{
|
|
||||||
m_sector_cache = NULL;
|
m_sector_cache = NULL;
|
||||||
}
|
// Remove from map and delete
|
||||||
/*
|
|
||||||
Remove from map and delete
|
|
||||||
*/
|
|
||||||
m_sectors.remove(*j);
|
m_sectors.remove(*j);
|
||||||
delete sector;
|
delete sector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
#if 0
|
||||||
|
void Map::unloadUnusedData(float timeout,
|
||||||
core::list<v3s16> *deleted_blocks)
|
core::list<v3s16> *deleted_blocks)
|
||||||
{
|
{
|
||||||
core::list<v2s16> sector_deletion_queue;
|
core::list<v2s16> sector_deletion_queue;
|
||||||
|
u32 deleted_blocks_count = 0;
|
||||||
|
u32 saved_blocks_count = 0;
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Iterator si = m_sectors.getIterator();
|
core::map<v2s16, MapSector*>::Iterator si = m_sectors.getIterator();
|
||||||
for(; si.atEnd() == false; si++)
|
for(; si.atEnd() == false; si++)
|
||||||
@ -1429,10 +1508,13 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
|||||||
{
|
{
|
||||||
// Save if modified
|
// Save if modified
|
||||||
if(block->getModified() != MOD_STATE_CLEAN)
|
if(block->getModified() != MOD_STATE_CLEAN)
|
||||||
|
{
|
||||||
saveBlock(block);
|
saveBlock(block);
|
||||||
// Unload
|
saved_blocks_count++;
|
||||||
sector->removeBlock(block);
|
}
|
||||||
delete block;
|
// Delete from memory
|
||||||
|
sector->deleteBlock(block);
|
||||||
|
deleted_blocks_count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1446,38 +1528,17 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
deleteSectors(sector_deletion_queue);
|
||||||
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
|
|
||||||
for(; i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapSector *sector = i.getNode()->getValue();
|
|
||||||
/*
|
|
||||||
Delete sector from memory if it hasn't been used in a long time
|
|
||||||
*/
|
|
||||||
if(sector->usage_timer > timeout)
|
|
||||||
{
|
|
||||||
sector_deletion_queue.push_back(i.getNode()->getKey());
|
|
||||||
|
|
||||||
if(deleted_blocks != NULL)
|
dstream<<"Map: Unloaded "<<deleted_blocks_count<<" blocks from memory"
|
||||||
{
|
<<", of which "<<saved_blocks_count<<" were wr."
|
||||||
// Collect positions of blocks of sector
|
<<std::endl;
|
||||||
MapSector *sector = i.getNode()->getValue();
|
|
||||||
core::list<MapBlock*> blocks;
|
//return sector_deletion_queue.getSize();
|
||||||
sector->getBlocks(blocks);
|
//return deleted_blocks_count;
|
||||||
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
|
||||||
i != blocks.end(); i++)
|
|
||||||
{
|
|
||||||
deleted_blocks->push_back((*i)->getPos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
deleteSectors(sector_deletion_queue, only_blocks);
|
|
||||||
return sector_deletion_queue.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::PrintInfo(std::ostream &out)
|
void Map::PrintInfo(std::ostream &out)
|
||||||
{
|
{
|
||||||
out<<"Map: ";
|
out<<"Map: ";
|
||||||
@ -1503,7 +1564,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
*/
|
*/
|
||||||
v3s16 p0 = m_transforming_liquid.pop_front();
|
v3s16 p0 = m_transforming_liquid.pop_front();
|
||||||
|
|
||||||
MapNode n0 = getNode(p0);
|
MapNode n0 = getNodeNoEx(p0);
|
||||||
|
|
||||||
// Don't deal with non-liquids
|
// Don't deal with non-liquids
|
||||||
if(content_liquid(n0.d) == false)
|
if(content_liquid(n0.d) == false)
|
||||||
@ -1538,13 +1599,10 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
};
|
};
|
||||||
for(u16 i=0; i<5; i++)
|
for(u16 i=0; i<5; i++)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
bool from_top = (i==0);
|
bool from_top = (i==0);
|
||||||
|
|
||||||
v3s16 p2 = p0 + dirs_from[i];
|
v3s16 p2 = p0 + dirs_from[i];
|
||||||
MapNode n2 = getNode(p2);
|
MapNode n2 = getNodeNoEx(p2);
|
||||||
|
|
||||||
if(content_liquid(n2.d))
|
if(content_liquid(n2.d))
|
||||||
{
|
{
|
||||||
@ -1593,10 +1651,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
if(new_liquid_level > new_liquid_level_max)
|
if(new_liquid_level > new_liquid_level_max)
|
||||||
new_liquid_level_max = new_liquid_level;
|
new_liquid_level_max = new_liquid_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
} //for
|
} //for
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1645,20 +1699,13 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
};
|
};
|
||||||
for(u16 i=0; i<6; i++)
|
for(u16 i=0; i<6; i++)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
v3s16 p2 = p0 + dirs[i];
|
v3s16 p2 = p0 + dirs[i];
|
||||||
|
|
||||||
MapNode n2 = getNode(p2);
|
MapNode n2 = getNodeNoEx(p2);
|
||||||
if(content_flowing_liquid(n2.d))
|
if(content_flowing_liquid(n2.d))
|
||||||
{
|
{
|
||||||
m_transforming_liquid.push_back(p2);
|
m_transforming_liquid.push_back(p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1679,9 +1726,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
};
|
};
|
||||||
for(u16 i=0; i<5; i++)
|
for(u16 i=0; i<5; i++)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
bool to_bottom = (i == 0);
|
bool to_bottom = (i == 0);
|
||||||
|
|
||||||
// If liquid is at lowest possible height, it's not going
|
// If liquid is at lowest possible height, it's not going
|
||||||
@ -1707,7 +1751,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
|
|
||||||
v3s16 p2 = p0 + dirs_to[i];
|
v3s16 p2 = p0 + dirs_to[i];
|
||||||
|
|
||||||
MapNode n2 = getNode(p2);
|
MapNode n2 = getNodeNoEx(p2);
|
||||||
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
|
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
|
||||||
|
|
||||||
if(content_liquid(n2.d))
|
if(content_liquid(n2.d))
|
||||||
@ -1773,10 +1817,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
// If n2_changed to bottom, don't flow anywhere else
|
// If n2_changed to bottom, don't flow anywhere else
|
||||||
if(to_bottom && flowed && !is_source)
|
if(to_bottom && flowed && !is_source)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loopcount++;
|
loopcount++;
|
||||||
@ -1972,7 +2012,6 @@ ServerMap::~ServerMap()
|
|||||||
{
|
{
|
||||||
if(m_map_saving_enabled)
|
if(m_map_saving_enabled)
|
||||||
{
|
{
|
||||||
//save(false);
|
|
||||||
// Save only changed parts
|
// Save only changed parts
|
||||||
save(true);
|
save(true);
|
||||||
dstream<<DTIME<<"Server: saved map to "<<m_savedir<<std::endl;
|
dstream<<DTIME<<"Server: saved map to "<<m_savedir<<std::endl;
|
||||||
@ -2079,6 +2118,8 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||||
|
|
||||||
/*dstream<<"Resulting vmanip:"<<std::endl;
|
/*dstream<<"Resulting vmanip:"<<std::endl;
|
||||||
data->vmanip.print(dstream);*/
|
data->vmanip.print(dstream);*/
|
||||||
|
|
||||||
@ -2091,10 +2132,11 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||||||
//TimeTaker timer("finishBlockMake() blitBackAll");
|
//TimeTaker timer("finishBlockMake() blitBackAll");
|
||||||
data->vmanip->blitBackAll(&changed_blocks);
|
data->vmanip->blitBackAll(&changed_blocks);
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
|
if(enable_mapgen_debug_info)
|
||||||
dstream<<"finishBlockMake: changed_blocks.size()="
|
dstream<<"finishBlockMake: changed_blocks.size()="
|
||||||
<<changed_blocks.size()<<std::endl;
|
<<changed_blocks.size()<<std::endl;
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
Copy transforming liquid information
|
Copy transforming liquid information
|
||||||
*/
|
*/
|
||||||
@ -2128,12 +2170,18 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||||||
/*
|
/*
|
||||||
NOTE: Lighting and object adding shouldn't really be here, but
|
NOTE: Lighting and object adding shouldn't really be here, but
|
||||||
lighting is a bit tricky to move properly to makeBlock.
|
lighting is a bit tricky to move properly to makeBlock.
|
||||||
TODO: Do this the right way anyway.
|
TODO: Do this the right way anyway, that is, move it to makeBlock.
|
||||||
|
- There needs to be some way for makeBlock to report back if
|
||||||
|
the lighting update is going further down because of the
|
||||||
|
new block blocking light
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update lighting
|
Update lighting
|
||||||
|
NOTE: This takes ~60ms, TODO: Investigate why
|
||||||
*/
|
*/
|
||||||
|
{
|
||||||
|
TimeTaker t("finishBlockMake lighting update");
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> lighting_update_blocks;
|
core::map<v3s16, MapBlock*> lighting_update_blocks;
|
||||||
// Center block
|
// Center block
|
||||||
@ -2150,6 +2198,10 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||||||
#endif
|
#endif
|
||||||
updateLighting(lighting_update_blocks, changed_blocks);
|
updateLighting(lighting_update_blocks, changed_blocks);
|
||||||
|
|
||||||
|
if(enable_mapgen_debug_info == false)
|
||||||
|
t.stop(true); // Hide output
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add random objects to block
|
Add random objects to block
|
||||||
*/
|
*/
|
||||||
@ -2262,6 +2314,8 @@ MapBlock * ServerMap::generateBlock(
|
|||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
|
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||||
|
|
||||||
TimeTaker timer("generateBlock");
|
TimeTaker timer("generateBlock");
|
||||||
|
|
||||||
//MapBlock *block = original_dummy;
|
//MapBlock *block = original_dummy;
|
||||||
@ -2290,6 +2344,9 @@ MapBlock * ServerMap::generateBlock(
|
|||||||
{
|
{
|
||||||
TimeTaker t("mapgen::make_block()");
|
TimeTaker t("mapgen::make_block()");
|
||||||
mapgen::make_block(&data);
|
mapgen::make_block(&data);
|
||||||
|
|
||||||
|
if(enable_mapgen_debug_info == false)
|
||||||
|
t.stop(true); // Hide output
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2348,6 +2405,9 @@ MapBlock * ServerMap::generateBlock(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(enable_mapgen_debug_info == false)
|
||||||
|
timer.stop(true); // Hide output
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2414,23 +2474,51 @@ MapBlock * ServerMap::createBlock(v3s16 p)
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
||||||
MapBlock * ServerMap::emergeBlock(
|
|
||||||
v3s16 p,
|
|
||||||
bool only_from_disk,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
DSTACKF("%s: p=(%d,%d,%d), only_from_disk=%d",
|
DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
|
||||||
__FUNCTION_NAME,
|
__FUNCTION_NAME,
|
||||||
p.X, p.Y, p.Z, only_from_disk);
|
p.X, p.Y, p.Z, allow_generate);
|
||||||
|
|
||||||
|
{
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(p);
|
||||||
|
if(block)
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MapBlock *block = loadBlock(p);
|
||||||
|
if(block)
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allow_generate)
|
||||||
|
{
|
||||||
|
core::map<v3s16, MapBlock*> modified_blocks;
|
||||||
|
MapBlock *block = generateBlock(p, modified_blocks);
|
||||||
|
if(block)
|
||||||
|
{
|
||||||
|
MapEditEvent event;
|
||||||
|
event.type = MEET_OTHER;
|
||||||
|
event.p = p;
|
||||||
|
|
||||||
|
// Copy modified_blocks to event
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = modified_blocks.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
event.modified_blocks.insert(i.getNode()->getKey(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue event
|
||||||
|
dispatchEvent(&event);
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This has to be redone or removed
|
|
||||||
assert(0);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
@ -2877,10 +2965,10 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
|
|||||||
// format. Just go ahead and create the sector.
|
// format. Just go ahead and create the sector.
|
||||||
if(fs::PathExists(sectordir))
|
if(fs::PathExists(sectordir))
|
||||||
{
|
{
|
||||||
dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
/*dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
||||||
<<fullpath<<" doesn't exist but directory does."
|
<<fullpath<<" doesn't exist but directory does."
|
||||||
<<" Continuing with a sector with no metadata."
|
<<" Continuing with a sector with no metadata."
|
||||||
<<std::endl;
|
<<std::endl;*/
|
||||||
sector = new ServerMapSector(this, p2d);
|
sector = new ServerMapSector(this, p2d);
|
||||||
m_sectors.insert(p2d, sector);
|
m_sectors.insert(p2d, sector);
|
||||||
}
|
}
|
||||||
@ -3094,10 +3182,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
|||||||
|
|
||||||
MapBlock *block = NULL;
|
MapBlock *block = NULL;
|
||||||
bool created_new = false;
|
bool created_new = false;
|
||||||
try{
|
block = sector->getBlockNoCreateNoEx(p3d.Y);
|
||||||
block = sector->getBlockNoCreate(p3d.Y);
|
if(block == NULL)
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
{
|
||||||
block = sector->createBlankBlockNoInsert(p3d.Y);
|
block = sector->createBlankBlockNoInsert(p3d.Y);
|
||||||
created_new = true;
|
created_new = true;
|
||||||
@ -3267,6 +3353,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d)
|
|||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
@ -3292,6 +3379,7 @@ void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
|||||||
|
|
||||||
sector->deSerialize(is);
|
sector->deSerialize(is);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ClientMap::OnRegisterSceneNode()
|
void ClientMap::OnRegisterSceneNode()
|
||||||
{
|
{
|
||||||
@ -3350,13 +3438,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
|
|
||||||
// Take a fair amount as we will be dropping more out later
|
// Take a fair amount as we will be dropping more out later
|
||||||
v3s16 p_blocks_min(
|
v3s16 p_blocks_min(
|
||||||
p_nodes_min.X / MAP_BLOCKSIZE - 1,
|
p_nodes_min.X / MAP_BLOCKSIZE - 2,
|
||||||
p_nodes_min.Y / MAP_BLOCKSIZE - 1,
|
p_nodes_min.Y / MAP_BLOCKSIZE - 2,
|
||||||
p_nodes_min.Z / MAP_BLOCKSIZE - 1);
|
p_nodes_min.Z / MAP_BLOCKSIZE - 2);
|
||||||
v3s16 p_blocks_max(
|
v3s16 p_blocks_max(
|
||||||
p_nodes_max.X / MAP_BLOCKSIZE,
|
p_nodes_max.X / MAP_BLOCKSIZE + 1,
|
||||||
p_nodes_max.Y / MAP_BLOCKSIZE,
|
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
||||||
p_nodes_max.Z / MAP_BLOCKSIZE);
|
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
||||||
|
|
||||||
u32 vertex_count = 0;
|
u32 vertex_count = 0;
|
||||||
|
|
||||||
@ -3429,6 +3517,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Okay, this block will be drawn. Reset usage timer.
|
||||||
|
block->resetUsageTimer();
|
||||||
|
|
||||||
// This is ugly (spherical distance limit?)
|
// This is ugly (spherical distance limit?)
|
||||||
/*if(m_control.range_all == false &&
|
/*if(m_control.range_all == false &&
|
||||||
d - 0.5*BS*MAP_BLOCKSIZE > range)
|
d - 0.5*BS*MAP_BLOCKSIZE > range)
|
||||||
|
130
src/map.h
130
src/map.h
@ -21,25 +21,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MAP_HEADER
|
#define MAP_HEADER
|
||||||
|
|
||||||
#include <jmutex.h>
|
#include <jmutex.h>
|
||||||
|
#include <jmutexautolock.h>
|
||||||
#include <jthread.h>
|
#include <jthread.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#define sleep_s(x) Sleep((x*1000))
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#define sleep_s(x) sleep(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "mapnode.h"
|
#include "mapnode.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock_nodemod.h"
|
||||||
#include "mapsector.h"
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "mapchunk.h"
|
|
||||||
#include "nodemetadata.h"
|
class MapSector;
|
||||||
|
class ServerMapSector;
|
||||||
|
class ClientMapSector;
|
||||||
|
class MapBlock;
|
||||||
|
class NodeMetadata;
|
||||||
|
|
||||||
namespace mapgen{
|
namespace mapgen{
|
||||||
struct BlockMakeData;
|
struct BlockMakeData;
|
||||||
@ -61,7 +57,7 @@ enum MapEditEventType{
|
|||||||
// Node metadata of block changed (not knowing which node exactly)
|
// Node metadata of block changed (not knowing which node exactly)
|
||||||
// p stores block coordinate
|
// p stores block coordinate
|
||||||
MEET_BLOCK_NODE_METADATA_CHANGED,
|
MEET_BLOCK_NODE_METADATA_CHANGED,
|
||||||
// Anything else
|
// Anything else (modified_blocks are set unsent)
|
||||||
MEET_OTHER
|
MEET_OTHER
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,17 +100,17 @@ public:
|
|||||||
virtual void onMapEditEvent(MapEditEvent *event) = 0;
|
virtual void onMapEditEvent(MapEditEvent *event) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Map : public NodeContainer
|
class Map /*: public NodeContainer*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Map(std::ostream &dout);
|
Map(std::ostream &dout);
|
||||||
virtual ~Map();
|
virtual ~Map();
|
||||||
|
|
||||||
virtual u16 nodeContainerId() const
|
/*virtual u16 nodeContainerId() const
|
||||||
{
|
{
|
||||||
return NODECONTAINER_ID_MAP;
|
return NODECONTAINER_ID_MAP;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
virtual s32 mapType() const
|
virtual s32 mapType() const
|
||||||
{
|
{
|
||||||
@ -155,66 +151,20 @@ public:
|
|||||||
MapBlock * getBlockNoCreate(v3s16 p);
|
MapBlock * getBlockNoCreate(v3s16 p);
|
||||||
// Returns NULL if not found
|
// Returns NULL if not found
|
||||||
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
||||||
// Gets an existing block or creates an empty one
|
|
||||||
//MapBlock * getBlockCreate(v3s16 p);
|
|
||||||
|
|
||||||
// Returns InvalidPositionException if not found
|
// Returns InvalidPositionException if not found
|
||||||
bool isNodeUnderground(v3s16 p);
|
bool isNodeUnderground(v3s16 p);
|
||||||
|
|
||||||
// virtual from NodeContainer
|
bool isValidPosition(v3s16 p);
|
||||||
bool isValidPosition(v3s16 p)
|
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
MapBlock *blockref;
|
|
||||||
try{
|
|
||||||
blockref = getBlockNoCreate(blockpos);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
/*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
bool is_valid = blockref->isValidPosition(relpos);
|
|
||||||
return is_valid;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual from NodeContainer
|
|
||||||
// throws InvalidPositionException if not found
|
// throws InvalidPositionException if not found
|
||||||
MapNode getNode(v3s16 p)
|
MapNode getNode(v3s16 p);
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
MapBlock * blockref = getBlockNoCreate(blockpos);
|
|
||||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
|
|
||||||
return blockref->getNodeNoCheck(relpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual from NodeContainer
|
|
||||||
// throws InvalidPositionException if not found
|
// throws InvalidPositionException if not found
|
||||||
void setNode(v3s16 p, MapNode & n)
|
void setNode(v3s16 p, MapNode & n);
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
MapBlock * blockref = getBlockNoCreate(blockpos);
|
|
||||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
blockref->setNodeNoCheck(relpos, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a CONTENT_IGNORE node if not found
|
// Returns a CONTENT_IGNORE node if not found
|
||||||
MapNode getNodeNoEx(v3s16 p)
|
MapNode getNodeNoEx(v3s16 p);
|
||||||
{
|
|
||||||
try{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
MapBlock * blockref = getBlockNoCreate(blockpos);
|
|
||||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
|
|
||||||
return blockref->getNodeNoCheck(relpos);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
return MapNode(CONTENT_IGNORE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unspreadLight(enum LightBank bank,
|
void unspreadLight(enum LightBank bank,
|
||||||
core::map<v3s16, u8> & from_nodes,
|
core::map<v3s16, u8> & from_nodes,
|
||||||
@ -273,23 +223,33 @@ public:
|
|||||||
|
|
||||||
virtual void save(bool only_changed){assert(0);};
|
virtual void save(bool only_changed){assert(0);};
|
||||||
|
|
||||||
// Server implements this
|
// Server implements this.
|
||||||
|
// Client leaves it as no-op.
|
||||||
virtual void saveBlock(MapBlock *block){};
|
virtual void saveBlock(MapBlock *block){};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Updates usage timers
|
Updates usage timers and unloads unused blocks and sectors.
|
||||||
|
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
||||||
*/
|
*/
|
||||||
void timerUpdate(float dtime);
|
void timerUpdate(float dtime, float unload_timeout,
|
||||||
|
core::list<v3s16> *unloaded_blocks=NULL);
|
||||||
|
|
||||||
|
// Deletes sectors and their blocks from memory
|
||||||
// Takes cache into account
|
// Takes cache into account
|
||||||
// sector mutex should be locked when calling
|
// If deleted sector is in sector cache, clears cache
|
||||||
void deleteSectors(core::list<v2s16> &list, bool only_blocks);
|
void deleteSectors(core::list<v2s16> &list);
|
||||||
|
|
||||||
// Returns count of deleted sectors
|
#if 0
|
||||||
u32 unloadUnusedData(float timeout, bool only_blocks=false,
|
/*
|
||||||
|
Unload unused data
|
||||||
|
= flush changed to disk and delete from memory, if usage timer of
|
||||||
|
block is more than timeout
|
||||||
|
*/
|
||||||
|
void unloadUnusedData(float timeout,
|
||||||
core::list<v3s16> *deleted_blocks=NULL);
|
core::list<v3s16> *deleted_blocks=NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
// For debug printing
|
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
@ -321,7 +281,6 @@ protected:
|
|||||||
core::map<MapEventReceiver*, bool> m_event_receivers;
|
core::map<MapEventReceiver*, bool> m_event_receivers;
|
||||||
|
|
||||||
core::map<v2s16, MapSector*> m_sectors;
|
core::map<v2s16, MapSector*> m_sectors;
|
||||||
//JMutex m_sector_mutex;
|
|
||||||
|
|
||||||
// Be sure to set this to NULL when the cached sector is deleted
|
// Be sure to set this to NULL when the cached sector is deleted
|
||||||
MapSector *m_sector_cache;
|
MapSector *m_sector_cache;
|
||||||
@ -379,24 +338,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
MapBlock * createBlock(v3s16 p);
|
MapBlock * createBlock(v3s16 p);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
NOTE: This comment might be outdated
|
|
||||||
|
|
||||||
Forcefully get a block from somewhere.
|
Forcefully get a block from somewhere.
|
||||||
|
- Memory
|
||||||
InvalidPositionException possible if only_from_disk==true
|
- Load from disk
|
||||||
|
- Generate
|
||||||
Parameters:
|
|
||||||
changed_blocks: Blocks that have been modified
|
|
||||||
*/
|
*/
|
||||||
MapBlock * emergeBlock(
|
MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
|
||||||
v3s16 p,
|
|
||||||
bool only_from_disk,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Helper for placing objects on ground level
|
// Helper for placing objects on ground level
|
||||||
s16 findGroundLevel(v2s16 p2d);
|
s16 findGroundLevel(v2s16 p2d);
|
||||||
@ -547,7 +495,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
MapSector * emergeSector(v2s16 p);
|
MapSector * emergeSector(v2s16 p);
|
||||||
|
|
||||||
void deSerializeSector(v2s16 p2d, std::istream &is);
|
//void deSerializeSector(v2s16 p2d, std::istream &is);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ISceneNode methods
|
ISceneNode methods
|
||||||
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
MapBlock
|
MapBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_pos(pos),
|
m_pos(pos),
|
||||||
m_modified(MOD_STATE_WRITE_NEEDED),
|
m_modified(MOD_STATE_WRITE_NEEDED),
|
||||||
@ -38,7 +38,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
|||||||
m_generated(false),
|
m_generated(false),
|
||||||
m_objects(this),
|
m_objects(this),
|
||||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED)
|
m_usage_timer(0)
|
||||||
{
|
{
|
||||||
data = NULL;
|
data = NULL;
|
||||||
if(dummy == false)
|
if(dummy == false)
|
||||||
@ -607,24 +607,20 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
|||||||
Get data
|
Get data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Serialize nodes
|
||||||
|
SharedBuffer<u8> databuf_nodelist(nodecount*3);
|
||||||
|
for(u32 i=0; i<nodecount; i++)
|
||||||
|
{
|
||||||
|
data[i].serialize(&databuf_nodelist[i*3], version);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create buffer with different parameters sorted
|
||||||
SharedBuffer<u8> databuf(nodecount*3);
|
SharedBuffer<u8> databuf(nodecount*3);
|
||||||
|
|
||||||
// Get contents
|
|
||||||
for(u32 i=0; i<nodecount; i++)
|
for(u32 i=0; i<nodecount; i++)
|
||||||
{
|
{
|
||||||
databuf[i] = data[i].d;
|
databuf[i] = databuf_nodelist[i*3];
|
||||||
}
|
databuf[i+nodecount] = databuf_nodelist[i*3+1];
|
||||||
|
databuf[i+nodecount*2] = databuf_nodelist[i*3+2];
|
||||||
// Get params
|
|
||||||
for(u32 i=0; i<nodecount; i++)
|
|
||||||
{
|
|
||||||
databuf[i+nodecount] = data[i].param;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get param2
|
|
||||||
for(u32 i=0; i<nodecount; i++)
|
|
||||||
{
|
|
||||||
databuf[i+nodecount*2] = data[i].param2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -773,20 +769,14 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||||||
("MapBlock::deSerialize: decompress resulted in size"
|
("MapBlock::deSerialize: decompress resulted in size"
|
||||||
" other than nodecount*3");
|
" other than nodecount*3");
|
||||||
|
|
||||||
// Set contents
|
// deserialize nodes from buffer
|
||||||
for(u32 i=0; i<nodecount; i++)
|
for(u32 i=0; i<nodecount; i++)
|
||||||
{
|
{
|
||||||
data[i].d = s[i];
|
u8 buf[3];
|
||||||
}
|
buf[0] = s[i];
|
||||||
// Set params
|
buf[1] = s[i+nodecount];
|
||||||
for(u32 i=0; i<nodecount; i++)
|
buf[2] = s[i+nodecount*2];
|
||||||
{
|
data[i].deSerialize(buf, version);
|
||||||
data[i].param = s[i+nodecount];
|
|
||||||
}
|
|
||||||
// Set param2
|
|
||||||
for(u32 i=0; i<nodecount; i++)
|
|
||||||
{
|
|
||||||
data[i].param2 = s[i+nodecount*2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -818,25 +808,6 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Translate nodes as specified in the translate_to fields of
|
|
||||||
node features
|
|
||||||
|
|
||||||
NOTE: This isn't really used. Should it be removed?
|
|
||||||
*/
|
|
||||||
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
|
|
||||||
{
|
|
||||||
MapNode &n = data[i];
|
|
||||||
|
|
||||||
MapNode *translate_to = content_features(n.d).translate_to;
|
|
||||||
if(translate_to)
|
|
||||||
{
|
|
||||||
dstream<<"MapBlock: WARNING: Translating node "<<n.d<<" to "
|
|
||||||
<<translate_to->d<<std::endl;
|
|
||||||
n = *translate_to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||||
|
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mapblock_mesh.h"
|
#include "mapblock_mesh.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class Map;
|
||||||
|
|
||||||
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
|
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ enum ModifiedState
|
|||||||
BLOCKGEN_FULLY_GENERATED=6
|
BLOCKGEN_FULLY_GENERATED=6
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NODECONTAINER_ID_MAPBLOCK,
|
NODECONTAINER_ID_MAPBLOCK,
|
||||||
@ -108,23 +110,24 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapBlock itself
|
MapBlock itself
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MapBlock : public NodeContainer
|
class MapBlock /*: public NodeContainer*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
|
MapBlock(Map *parent, v3s16 pos, bool dummy=false);
|
||||||
~MapBlock();
|
~MapBlock();
|
||||||
|
|
||||||
virtual u16 nodeContainerId() const
|
/*virtual u16 nodeContainerId() const
|
||||||
{
|
{
|
||||||
return NODECONTAINER_ID_MAPBLOCK;
|
return NODECONTAINER_ID_MAPBLOCK;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
NodeContainer * getParent()
|
Map * getParent()
|
||||||
{
|
{
|
||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
@ -640,7 +643,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// NOTE: Lots of things rely on this being the Map
|
// NOTE: Lots of things rely on this being the Map
|
||||||
NodeContainer *m_parent;
|
Map *m_parent;
|
||||||
// Position in blocks on parent
|
// Position in blocks on parent
|
||||||
v3s16 m_pos;
|
v3s16 m_pos;
|
||||||
|
|
||||||
|
@ -64,11 +64,7 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Get map
|
// Get map
|
||||||
NodeContainer *parentcontainer = block->getParent();
|
Map *map = block->getParent();
|
||||||
// This will only work if the parent is the map
|
|
||||||
assert(parentcontainer->nodeContainerId() == NODECONTAINER_ID_MAP);
|
|
||||||
// OK, we have the map!
|
|
||||||
Map *map = (Map*)parentcontainer;
|
|
||||||
|
|
||||||
for(u16 i=0; i<6; i++)
|
for(u16 i=0; i<6; i++)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapBlockObject
|
MapBlockObject
|
||||||
@ -856,16 +857,7 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
|||||||
assert(m_objects.find(object->m_id) != NULL);
|
assert(m_objects.find(object->m_id) != NULL);
|
||||||
assert(m_objects[object->m_id] == object);
|
assert(m_objects[object->m_id] == object);
|
||||||
|
|
||||||
NodeContainer *parentcontainer = m_block->getParent();
|
Map *map = m_block->getParent();
|
||||||
// This will only work if the parent is the map
|
|
||||||
if(parentcontainer->nodeContainerId() != NODECONTAINER_ID_MAP)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: Wrapping object not possible: "
|
|
||||||
"MapBlock's parent is not map"<<std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// OK, we have the map!
|
|
||||||
Map *map = (Map*)parentcontainer;
|
|
||||||
|
|
||||||
// Calculate blockpos on map
|
// Calculate blockpos on map
|
||||||
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
||||||
|
@ -20,6 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifndef MAPCHUNK_HEADER
|
#ifndef MAPCHUNK_HEADER
|
||||||
#define MAPCHUNK_HEADER
|
#define MAPCHUNK_HEADER
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: Remove
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
MapChunk contains map-generation-time metadata for an area of
|
MapChunk contains map-generation-time metadata for an area of
|
||||||
some MapSectors. (something like 16x16)
|
some MapSectors. (something like 16x16)
|
||||||
@ -66,6 +71,7 @@ private:
|
|||||||
u8 m_generation_level;
|
u8 m_generation_level;
|
||||||
bool m_modified;
|
bool m_modified;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
102
src/mapgen.cpp
102
src/mapgen.cpp
@ -23,8 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "noise.h"
|
#include "noise.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "serverobject.h"
|
|
||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
|
//#include "serverobject.h"
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
namespace mapgen
|
namespace mapgen
|
||||||
{
|
{
|
||||||
@ -531,7 +532,7 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
|
|||||||
else
|
else
|
||||||
length = random.range(1,6);
|
length = random.range(1,6);
|
||||||
length = random.range(1,13);
|
length = random.range(1,13);
|
||||||
u32 partlength = random.range(1,length);
|
u32 partlength = random.range(1,13);
|
||||||
u32 partcount = 0;
|
u32 partcount = 0;
|
||||||
s16 make_stairs = 0;
|
s16 make_stairs = 0;
|
||||||
if(random.next()%2 == 0 && partlength >= 3)
|
if(random.next()%2 == 0 && partlength >= 3)
|
||||||
@ -700,14 +701,30 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
v3s16 roomplace;
|
v3s16 roomplace;
|
||||||
// X east, Z north, Y up
|
// X east, Z north, Y up
|
||||||
|
#if 1
|
||||||
if(doordir == v3s16(1,0,0)) // X+
|
if(doordir == v3s16(1,0,0)) // X+
|
||||||
roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
|
roomplace = doorplace +
|
||||||
|
v3s16(0,-1,m_random.range(-roomsize.Z+2,-2));
|
||||||
if(doordir == v3s16(-1,0,0)) // X-
|
if(doordir == v3s16(-1,0,0)) // X-
|
||||||
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
|
roomplace = doorplace +
|
||||||
|
v3s16(-roomsize.X+1,-1,m_random.range(-roomsize.Z+2,-2));
|
||||||
if(doordir == v3s16(0,0,1)) // Z+
|
if(doordir == v3s16(0,0,1)) // Z+
|
||||||
roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0);
|
roomplace = doorplace +
|
||||||
|
v3s16(m_random.range(-roomsize.X+2,-2),-1,0);
|
||||||
if(doordir == v3s16(0,0,-1)) // Z-
|
if(doordir == v3s16(0,0,-1)) // Z-
|
||||||
roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,-roomsize.Z+1);
|
roomplace = doorplace +
|
||||||
|
v3s16(m_random.range(-roomsize.X+2,-2),-1,-roomsize.Z+1);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
if(doordir == v3s16(1,0,0)) // X+
|
||||||
|
roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2);
|
||||||
|
if(doordir == v3s16(-1,0,0)) // X-
|
||||||
|
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2);
|
||||||
|
if(doordir == v3s16(0,0,1)) // Z+
|
||||||
|
roomplace = doorplace + v3s16(-roomsize.X/2,-1,0);
|
||||||
|
if(doordir == v3s16(0,0,-1)) // Z-
|
||||||
|
roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check fit
|
// Check fit
|
||||||
bool fits = true;
|
bool fits = true;
|
||||||
@ -818,7 +835,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
|
|||||||
|
|
||||||
// Determine walker start position
|
// Determine walker start position
|
||||||
|
|
||||||
bool start_in_last_room = (random.range(0,1)==0);
|
bool start_in_last_room = (random.range(0,2)!=0);
|
||||||
//bool start_in_last_room = true;
|
//bool start_in_last_room = true;
|
||||||
|
|
||||||
v3s16 walker_start_place;
|
v3s16 walker_start_place;
|
||||||
@ -877,30 +894,47 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
|
|||||||
Noise functions. Make sure seed is mangled differently in each one.
|
Noise functions. Make sure seed is mangled differently in each one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This affects the shape of the contour
|
/*
|
||||||
|
Scaling the output of the noise function affects the overdrive of the
|
||||||
|
contour function, which affects the shape of the output considerably.
|
||||||
|
*/
|
||||||
|
#define CAVE_NOISE_SCALE 12.0
|
||||||
//#define CAVE_NOISE_SCALE 10.0
|
//#define CAVE_NOISE_SCALE 10.0
|
||||||
//#define CAVE_NOISE_SCALE 7.5
|
//#define CAVE_NOISE_SCALE 7.5
|
||||||
#define CAVE_NOISE_SCALE 5.0
|
//#define CAVE_NOISE_SCALE 5.0
|
||||||
|
//#define CAVE_NOISE_SCALE 1.0
|
||||||
|
|
||||||
|
//#define CAVE_NOISE_THRESHOLD (2.5/CAVE_NOISE_SCALE)
|
||||||
|
#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE)
|
||||||
|
|
||||||
NoiseParams get_cave_noise1_params(u64 seed)
|
NoiseParams get_cave_noise1_params(u64 seed)
|
||||||
{
|
{
|
||||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
|
||||||
200, CAVE_NOISE_SCALE);*/
|
200, CAVE_NOISE_SCALE);*/
|
||||||
return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
|
||||||
100, CAVE_NOISE_SCALE);
|
100, CAVE_NOISE_SCALE);*/
|
||||||
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.6,
|
||||||
|
100, CAVE_NOISE_SCALE);*/
|
||||||
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.3,
|
||||||
|
100, CAVE_NOISE_SCALE);*/
|
||||||
|
return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.5,
|
||||||
|
50, CAVE_NOISE_SCALE);
|
||||||
|
//return NoiseParams(NOISE_CONSTANT_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoiseParams get_cave_noise2_params(u64 seed)
|
NoiseParams get_cave_noise2_params(u64 seed)
|
||||||
{
|
{
|
||||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
|
||||||
200, CAVE_NOISE_SCALE);*/
|
200, CAVE_NOISE_SCALE);*/
|
||||||
return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
|
||||||
100, CAVE_NOISE_SCALE);
|
100, CAVE_NOISE_SCALE);*/
|
||||||
|
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.3,
|
||||||
|
100, CAVE_NOISE_SCALE);*/
|
||||||
|
return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.5,
|
||||||
|
50, CAVE_NOISE_SCALE);
|
||||||
|
//return NoiseParams(NOISE_CONSTANT_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define CAVE_NOISE_THRESHOLD (2.5/CAVE_NOISE_SCALE)
|
|
||||||
#define CAVE_NOISE_THRESHOLD (2.0/CAVE_NOISE_SCALE)
|
|
||||||
|
|
||||||
NoiseParams get_ground_noise1_params(u64 seed)
|
NoiseParams get_ground_noise1_params(u64 seed)
|
||||||
{
|
{
|
||||||
return NoiseParams(NOISE_PERLIN, seed+983240, 4,
|
return NoiseParams(NOISE_PERLIN, seed+983240, 4,
|
||||||
@ -937,13 +971,13 @@ bool val_is_ground(double ground_noise1_val, v3s16 p, u64 seed)
|
|||||||
{
|
{
|
||||||
//return ((double)p.Y < ground_noise1_val);
|
//return ((double)p.Y < ground_noise1_val);
|
||||||
|
|
||||||
double f = 0.8 + noise2d_perlin(
|
double f = 0.55 + noise2d_perlin(
|
||||||
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
||||||
seed+920381, 3, 0.45);
|
seed+920381, 3, 0.45);
|
||||||
if(f < 0.01)
|
if(f < 0.01)
|
||||||
f = 0.01;
|
f = 0.01;
|
||||||
else if(f >= 1.0)
|
else if(f >= 1.0)
|
||||||
f *= 2.0;
|
f *= 1.6;
|
||||||
double h = WATER_LEVEL + 10 * noise2d_perlin(
|
double h = WATER_LEVEL + 10 * noise2d_perlin(
|
||||||
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
||||||
seed+84174, 4, 0.5);
|
seed+84174, 4, 0.5);
|
||||||
@ -1082,6 +1116,7 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p)
|
|||||||
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
|
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
|
||||||
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
||||||
double a = -31000;
|
double a = -31000;
|
||||||
|
// Corners
|
||||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X, node_min.Y), p));
|
v2s16(node_min.X, node_min.Y), p));
|
||||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
@ -1090,8 +1125,18 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p)
|
|||||||
v2s16(node_max.X, node_max.Y), p));
|
v2s16(node_max.X, node_max.Y), p));
|
||||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X, node_min.Y), p));
|
v2s16(node_min.X, node_min.Y), p));
|
||||||
|
// Center
|
||||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
|
// Side middle points
|
||||||
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
|
||||||
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
|
||||||
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
|
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1102,6 +1147,7 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
|
|||||||
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
|
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
|
||||||
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
||||||
double a = 31000;
|
double a = 31000;
|
||||||
|
// Corners
|
||||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X, node_min.Y), p));
|
v2s16(node_min.X, node_min.Y), p));
|
||||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
@ -1110,8 +1156,18 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
|
|||||||
v2s16(node_max.X, node_max.Y), p));
|
v2s16(node_max.X, node_max.Y), p));
|
||||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X, node_min.Y), p));
|
v2s16(node_min.X, node_min.Y), p));
|
||||||
|
// Center
|
||||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
|
// Side middle points
|
||||||
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
|
||||||
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
|
||||||
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
|
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||||
|
v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,12 +1414,12 @@ void make_block(BlockMakeData *data)
|
|||||||
If block is deep underground, this is set to true and ground
|
If block is deep underground, this is set to true and ground
|
||||||
density noise is not generated, for speed optimization.
|
density noise is not generated, for speed optimization.
|
||||||
*/
|
*/
|
||||||
bool all_is_ground_except_caves = (minimum_ground_depth > 16);
|
bool all_is_ground_except_caves = (minimum_ground_depth > 40);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a block-specific seed
|
Create a block-specific seed
|
||||||
*/
|
*/
|
||||||
u32 blockseed = (data->seed%0x100000000) + full_node_min.Z*38134234
|
u32 blockseed = (u32)(data->seed%0x100000000) + full_node_min.Z*38134234
|
||||||
+ full_node_min.Y*42123 + full_node_min.X*23;
|
+ full_node_min.Y*42123 + full_node_min.X*23;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1385,13 +1441,13 @@ void make_block(BlockMakeData *data)
|
|||||||
/*
|
/*
|
||||||
Cave noise
|
Cave noise
|
||||||
*/
|
*/
|
||||||
|
#if 1
|
||||||
noisebuf_cave.create(get_cave_noise1_params(data->seed),
|
noisebuf_cave.create(get_cave_noise1_params(data->seed),
|
||||||
minpos_f.X, minpos_f.Y, minpos_f.Z,
|
minpos_f.X, minpos_f.Y, minpos_f.Z,
|
||||||
maxpos_f.X, maxpos_f.Y, maxpos_f.Z,
|
maxpos_f.X, maxpos_f.Y, maxpos_f.Z,
|
||||||
4, 3, 4);
|
2, 2, 2);
|
||||||
|
|
||||||
noisebuf_cave.multiply(get_cave_noise2_params(data->seed));
|
noisebuf_cave.multiply(get_cave_noise2_params(data->seed));
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ground noise
|
Ground noise
|
||||||
|
103
src/mapnode.cpp
103
src/mapnode.cpp
@ -30,8 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
ContentFeatures::~ContentFeatures()
|
ContentFeatures::~ContentFeatures()
|
||||||
{
|
{
|
||||||
if(translate_to)
|
/*if(translate_to)
|
||||||
delete translate_to;
|
delete translate_to;*/
|
||||||
if(initial_metadata)
|
if(initial_metadata)
|
||||||
delete initial_metadata;
|
delete initial_metadata;
|
||||||
}
|
}
|
||||||
@ -138,6 +138,17 @@ void init_mapnode()
|
|||||||
f->tiles[j].material_type = initial_material_type;
|
f->tiles[j].material_type = initial_material_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initially set every block to be shown as an unknown block.
|
||||||
|
Don't touch CONTENT_IGNORE or CONTENT_AIR.
|
||||||
|
*/
|
||||||
|
for(u16 i=0; i<=253; i++)
|
||||||
|
{
|
||||||
|
ContentFeatures *f = &g_content_features[i];
|
||||||
|
f->setAllTextures("unknown_block.png");
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize mapnode content
|
Initialize mapnode content
|
||||||
*/
|
*/
|
||||||
@ -230,6 +241,94 @@ u8 MapNode::getMineral()
|
|||||||
return MINERAL_NONE;
|
return MINERAL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 MapNode::serializedLength(u8 version)
|
||||||
|
{
|
||||||
|
if(!ser_ver_supported(version))
|
||||||
|
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||||
|
|
||||||
|
if(version == 0)
|
||||||
|
return 1;
|
||||||
|
else if(version <= 9)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
void MapNode::serialize(u8 *dest, u8 version)
|
||||||
|
{
|
||||||
|
if(!ser_ver_supported(version))
|
||||||
|
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||||
|
|
||||||
|
u8 actual_d = d;
|
||||||
|
|
||||||
|
// Convert from new version to old
|
||||||
|
if(version <= 18)
|
||||||
|
{
|
||||||
|
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||||
|
// are 255 and 254
|
||||||
|
if(d == CONTENT_IGNORE)
|
||||||
|
d = 255;
|
||||||
|
else if(d == CONTENT_AIR)
|
||||||
|
d = 254;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version == 0)
|
||||||
|
{
|
||||||
|
dest[0] = actual_d;
|
||||||
|
}
|
||||||
|
else if(version <= 9)
|
||||||
|
{
|
||||||
|
dest[0] = actual_d;
|
||||||
|
dest[1] = param;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest[0] = actual_d;
|
||||||
|
dest[1] = param;
|
||||||
|
dest[2] = param2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void MapNode::deSerialize(u8 *source, u8 version)
|
||||||
|
{
|
||||||
|
if(!ser_ver_supported(version))
|
||||||
|
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||||
|
|
||||||
|
if(version == 0)
|
||||||
|
{
|
||||||
|
d = source[0];
|
||||||
|
}
|
||||||
|
else if(version == 1)
|
||||||
|
{
|
||||||
|
d = source[0];
|
||||||
|
// This version doesn't support saved lighting
|
||||||
|
if(light_propagates() || light_source() > 0)
|
||||||
|
param = 0;
|
||||||
|
else
|
||||||
|
param = source[1];
|
||||||
|
}
|
||||||
|
else if(version <= 9)
|
||||||
|
{
|
||||||
|
d = source[0];
|
||||||
|
param = source[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d = source[0];
|
||||||
|
param = source[1];
|
||||||
|
param2 = source[2];
|
||||||
|
|
||||||
|
// Convert from old version to new
|
||||||
|
if(version <= 18)
|
||||||
|
{
|
||||||
|
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||||
|
// are 255 and 254
|
||||||
|
if(d == 255)
|
||||||
|
d = CONTENT_IGNORE;
|
||||||
|
else if(d == 254)
|
||||||
|
d = CONTENT_AIR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets lighting value at face of node
|
Gets lighting value at face of node
|
||||||
|
|
||||||
|
132
src/mapnode.h
132
src/mapnode.h
@ -36,6 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
- Tile = TileSpec at some side of a node of some content type
|
- Tile = TileSpec at some side of a node of some content type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ranges:
|
||||||
|
0x000...0x07f: param2 is fully usable
|
||||||
|
0x800...0xfff: param2 lower 4 bytes are free
|
||||||
|
*/
|
||||||
|
typedef u16 content_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initializes all kind of stuff in here.
|
Initializes all kind of stuff in here.
|
||||||
Many things depend on this.
|
Many things depend on this.
|
||||||
@ -59,14 +66,16 @@ void init_mapnode();
|
|||||||
Doesn't create faces with anything and is considered being
|
Doesn't create faces with anything and is considered being
|
||||||
out-of-map in the game map.
|
out-of-map in the game map.
|
||||||
*/
|
*/
|
||||||
#define CONTENT_IGNORE 255
|
//#define CONTENT_IGNORE 255
|
||||||
|
#define CONTENT_IGNORE 127
|
||||||
#define CONTENT_IGNORE_DEFAULT_PARAM 0
|
#define CONTENT_IGNORE_DEFAULT_PARAM 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The common material through which the player can walk and which
|
The common material through which the player can walk and which
|
||||||
is transparent to light
|
is transparent to light
|
||||||
*/
|
*/
|
||||||
#define CONTENT_AIR 254
|
//#define CONTENT_AIR 254
|
||||||
|
#define CONTENT_AIR 126
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Content feature list
|
Content feature list
|
||||||
@ -94,7 +103,7 @@ class NodeMetadata;
|
|||||||
struct ContentFeatures
|
struct ContentFeatures
|
||||||
{
|
{
|
||||||
// If non-NULL, content is translated to this when deserialized
|
// If non-NULL, content is translated to this when deserialized
|
||||||
MapNode *translate_to;
|
//MapNode *translate_to;
|
||||||
|
|
||||||
// Type of MapNode::param
|
// Type of MapNode::param
|
||||||
ContentParamType param_type;
|
ContentParamType param_type;
|
||||||
@ -156,7 +165,7 @@ struct ContentFeatures
|
|||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
translate_to = NULL;
|
//translate_to = NULL;
|
||||||
param_type = CPT_NONE;
|
param_type = CPT_NONE;
|
||||||
inventory_texture = NULL;
|
inventory_texture = NULL;
|
||||||
is_ground_content = false;
|
is_ground_content = false;
|
||||||
@ -196,6 +205,8 @@ struct ContentFeatures
|
|||||||
{
|
{
|
||||||
setTexture(i, name, alpha);
|
setTexture(i, name, alpha);
|
||||||
}
|
}
|
||||||
|
// Force inventory texture too
|
||||||
|
setInventoryTexture(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTile(u16 i, const TileSpec &tile)
|
void setTile(u16 i, const TileSpec &tile)
|
||||||
@ -399,8 +410,16 @@ enum LightBank
|
|||||||
|
|
||||||
struct MapNode
|
struct MapNode
|
||||||
{
|
{
|
||||||
// Content
|
/*
|
||||||
|
Main content
|
||||||
|
0x00-0x7f: Short content type
|
||||||
|
0x80-0xff: Long content type (param2>>4 makes up low bytes)
|
||||||
|
*/
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u8 param0;
|
||||||
u8 d;
|
u8 d;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Misc parameter. Initialized to 0.
|
Misc parameter. Initialized to 0.
|
||||||
@ -408,11 +427,13 @@ struct MapNode
|
|||||||
stored logarithmically from 0 to LIGHT_MAX.
|
stored logarithmically from 0 to LIGHT_MAX.
|
||||||
Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
|
Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
|
||||||
- Contains 2 values, day- and night lighting. Each takes 4 bits.
|
- Contains 2 values, day- and night lighting. Each takes 4 bits.
|
||||||
|
- Mineral content (should be removed from here)
|
||||||
|
- Uhh... well, most blocks have light or nothing in here.
|
||||||
*/
|
*/
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
s8 param;
|
|
||||||
u8 param1;
|
u8 param1;
|
||||||
|
s8 param;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -437,14 +458,6 @@ struct MapNode
|
|||||||
param2 = a_param2;
|
param2 = a_param2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*MapNode & operator=(const MapNode &other)
|
|
||||||
{
|
|
||||||
d = other.d;
|
|
||||||
param = other.param;
|
|
||||||
param2 = other.param2;
|
|
||||||
return *this;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool operator==(const MapNode &other)
|
bool operator==(const MapNode &other)
|
||||||
{
|
{
|
||||||
return (d == other.d
|
return (d == other.d
|
||||||
@ -452,6 +465,16 @@ struct MapNode
|
|||||||
&& param2 == other.param2);
|
&& param2 == other.param2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To be used everywhere
|
||||||
|
content_t getContent()
|
||||||
|
{
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
void setContent(content_t c)
|
||||||
|
{
|
||||||
|
d = c;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These four are DEPRECATED I guess. -c55
|
These four are DEPRECATED I guess. -c55
|
||||||
*/
|
*/
|
||||||
@ -568,86 +591,13 @@ struct MapNode
|
|||||||
u8 getMineral();
|
u8 getMineral();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These serialization functions are used when informing client
|
Serialization functions
|
||||||
of a single node add.
|
|
||||||
|
|
||||||
NOTE: When loading a MapBlock, these are not used. Should they?
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u32 serializedLength(u8 version)
|
static u32 serializedLength(u8 version);
|
||||||
{
|
void serialize(u8 *dest, u8 version);
|
||||||
if(!ser_ver_supported(version))
|
void deSerialize(u8 *source, u8 version);
|
||||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
|
||||||
|
|
||||||
if(version == 0)
|
|
||||||
return 1;
|
|
||||||
else if(version <= 9)
|
|
||||||
return 2;
|
|
||||||
else
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
void serialize(u8 *dest, u8 version)
|
|
||||||
{
|
|
||||||
if(!ser_ver_supported(version))
|
|
||||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
|
||||||
|
|
||||||
if(version == 0)
|
|
||||||
{
|
|
||||||
dest[0] = d;
|
|
||||||
}
|
|
||||||
else if(version <= 9)
|
|
||||||
{
|
|
||||||
dest[0] = d;
|
|
||||||
dest[1] = param;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dest[0] = d;
|
|
||||||
dest[1] = param;
|
|
||||||
dest[2] = param2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void deSerialize(u8 *source, u8 version)
|
|
||||||
{
|
|
||||||
if(!ser_ver_supported(version))
|
|
||||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
|
||||||
|
|
||||||
if(version == 0)
|
|
||||||
{
|
|
||||||
d = source[0];
|
|
||||||
}
|
|
||||||
else if(version == 1)
|
|
||||||
{
|
|
||||||
d = source[0];
|
|
||||||
// This version doesn't support saved lighting
|
|
||||||
if(light_propagates() || light_source() > 0)
|
|
||||||
param = 0;
|
|
||||||
else
|
|
||||||
param = source[1];
|
|
||||||
}
|
|
||||||
else if(version <= 9)
|
|
||||||
{
|
|
||||||
d = source[0];
|
|
||||||
param = source[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d = source[0];
|
|
||||||
param = source[1];
|
|
||||||
param2 = source[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate deprecated stuff
|
|
||||||
// NOTE: This doesn't get used because MapBlock handles node
|
|
||||||
// parameters directly
|
|
||||||
MapNode *translate_to = content_features(d).translate_to;
|
|
||||||
if(translate_to)
|
|
||||||
{
|
|
||||||
dstream<<"MapNode: WARNING: Translating "<<d<<" to "
|
|
||||||
<<translate_to->d<<std::endl;
|
|
||||||
*this = *translate_to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -21,15 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "jmutexautolock.h"
|
#include "jmutexautolock.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
|
||||||
MapSector::MapSector(NodeContainer *parent, v2s16 pos):
|
MapSector::MapSector(Map *parent, v2s16 pos):
|
||||||
differs_from_disk(true),
|
differs_from_disk(false),
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_pos(pos),
|
m_pos(pos),
|
||||||
m_block_cache(NULL)
|
m_block_cache(NULL)
|
||||||
{
|
{
|
||||||
m_mutex.Init();
|
|
||||||
assert(m_mutex.IsInitialized());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MapSector::~MapSector()
|
MapSector::~MapSector()
|
||||||
@ -39,8 +38,6 @@ MapSector::~MapSector()
|
|||||||
|
|
||||||
void MapSector::deleteBlocks()
|
void MapSector::deleteBlocks()
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
// Clear cache
|
// Clear cache
|
||||||
m_block_cache = NULL;
|
m_block_cache = NULL;
|
||||||
|
|
||||||
@ -83,26 +80,12 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
|
|||||||
|
|
||||||
MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
|
MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
return getBlockBuffered(y);
|
return getBlockBuffered(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock * MapSector::getBlockNoCreate(s16 y)
|
|
||||||
{
|
|
||||||
MapBlock *block = getBlockNoCreateNoEx(y);
|
|
||||||
|
|
||||||
if(block == NULL)
|
|
||||||
throw InvalidPositionException();
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
|
MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
|
||||||
{
|
{
|
||||||
// There should not be a block at this position
|
assert(getBlockBuffered(y) == NULL);
|
||||||
if(getBlockBuffered(y) != NULL)
|
|
||||||
throw AlreadyExistsException("Block already exists");
|
|
||||||
|
|
||||||
v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
|
v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
|
||||||
|
|
||||||
@ -113,8 +96,6 @@ MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
|
|||||||
|
|
||||||
MapBlock * MapSector::createBlankBlock(s16 y)
|
MapBlock * MapSector::createBlankBlock(s16 y)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
MapBlock *block = createBlankBlockNoInsert(y);
|
MapBlock *block = createBlankBlockNoInsert(y);
|
||||||
|
|
||||||
m_blocks.insert(y, block);
|
m_blocks.insert(y, block);
|
||||||
@ -126,9 +107,6 @@ void MapSector::insertBlock(MapBlock *block)
|
|||||||
{
|
{
|
||||||
s16 block_y = block->getPos().Y;
|
s16 block_y = block->getPos().Y;
|
||||||
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
MapBlock *block2 = getBlockBuffered(block_y);
|
MapBlock *block2 = getBlockBuffered(block_y);
|
||||||
if(block2 != NULL){
|
if(block2 != NULL){
|
||||||
throw AlreadyExistsException("Block already exists");
|
throw AlreadyExistsException("Block already exists");
|
||||||
@ -140,25 +118,23 @@ void MapSector::insertBlock(MapBlock *block)
|
|||||||
// Insert into container
|
// Insert into container
|
||||||
m_blocks.insert(block_y, block);
|
m_blocks.insert(block_y, block);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MapSector::removeBlock(MapBlock *block)
|
void MapSector::deleteBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
s16 block_y = block->getPos().Y;
|
s16 block_y = block->getPos().Y;
|
||||||
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
// Clear from cache
|
// Clear from cache
|
||||||
m_block_cache = NULL;
|
m_block_cache = NULL;
|
||||||
|
|
||||||
// Remove from container
|
// Remove from container
|
||||||
m_blocks.remove(block_y);
|
m_blocks.remove(block_y);
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
delete block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::list<MapBlock*> ref_list;
|
core::list<MapBlock*> ref_list;
|
||||||
|
|
||||||
core::map<s16, MapBlock*>::Iterator bi;
|
core::map<s16, MapBlock*>::Iterator bi;
|
||||||
@ -175,7 +151,7 @@ void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
|||||||
ServerMapSector
|
ServerMapSector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ServerMapSector::ServerMapSector(NodeContainer *parent, v2s16 pos):
|
ServerMapSector::ServerMapSector(Map *parent, v2s16 pos):
|
||||||
MapSector(parent, pos)
|
MapSector(parent, pos)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -184,15 +160,6 @@ ServerMapSector::~ServerMapSector()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 ServerMapSector::getGroundHeight(v2s16 p, bool generate)
|
|
||||||
{
|
|
||||||
return GROUNDHEIGHT_NOTFOUND_SETVALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerMapSector::setGroundHeight(v2s16 p, f32 y, bool generate)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerMapSector::serialize(std::ostream &os, u8 version)
|
void ServerMapSector::serialize(std::ostream &os, u8 version)
|
||||||
{
|
{
|
||||||
if(!ser_ver_supported(version))
|
if(!ser_ver_supported(version))
|
||||||
@ -217,7 +184,7 @@ void ServerMapSector::serialize(std::ostream &os, u8 version)
|
|||||||
|
|
||||||
ServerMapSector* ServerMapSector::deSerialize(
|
ServerMapSector* ServerMapSector::deSerialize(
|
||||||
std::istream &is,
|
std::istream &is,
|
||||||
NodeContainer *parent,
|
Map *parent,
|
||||||
v2s16 p2d,
|
v2s16 p2d,
|
||||||
core::map<v2s16, MapSector*> & sectors
|
core::map<v2s16, MapSector*> & sectors
|
||||||
)
|
)
|
||||||
@ -280,7 +247,7 @@ ServerMapSector* ServerMapSector::deSerialize(
|
|||||||
ClientMapSector
|
ClientMapSector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ClientMapSector::ClientMapSector(NodeContainer *parent, v2s16 pos):
|
ClientMapSector::ClientMapSector(Map *parent, v2s16 pos):
|
||||||
MapSector(parent, pos)
|
MapSector(parent, pos)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -289,45 +256,6 @@ ClientMapSector::~ClientMapSector()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientMapSector::deSerialize(std::istream &is)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
[0] u8 serialization version
|
|
||||||
[1] s16 corners[0]
|
|
||||||
[3] s16 corners[1]
|
|
||||||
[5] s16 corners[2]
|
|
||||||
[7] s16 corners[3]
|
|
||||||
size = 9
|
|
||||||
|
|
||||||
In which corners are in these positions
|
|
||||||
v2s16(0,0),
|
|
||||||
v2s16(1,0),
|
|
||||||
v2s16(1,1),
|
|
||||||
v2s16(0,1),
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Read version
|
|
||||||
u8 version = SER_FMT_VER_INVALID;
|
|
||||||
is.read((char*)&version, 1);
|
|
||||||
|
|
||||||
if(!ser_ver_supported(version))
|
|
||||||
throw VersionMismatchException("ERROR: MapSector format not supported");
|
|
||||||
|
|
||||||
u8 buf[2];
|
|
||||||
|
|
||||||
// Dummy read corners
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set stuff in sector
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Nothing here
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
|
||||||
//END
|
//END
|
||||||
|
178
src/mapsector.h
178
src/mapsector.h
@ -26,9 +26,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include <jmutex.h>
|
#include <jmutex.h>
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "mapblock.h"
|
|
||||||
//#include "heightmap.h"
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
class MapBlock;
|
||||||
|
class Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is an Y-wise stack of MapBlocks.
|
This is an Y-wise stack of MapBlocks.
|
||||||
@ -37,18 +39,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MAPSECTOR_SERVER 0
|
#define MAPSECTOR_SERVER 0
|
||||||
#define MAPSECTOR_CLIENT 1
|
#define MAPSECTOR_CLIENT 1
|
||||||
|
|
||||||
class MapSector: public NodeContainer
|
class MapSector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MapSector(NodeContainer *parent, v2s16 pos);
|
MapSector(Map *parent, v2s16 pos);
|
||||||
virtual ~MapSector();
|
virtual ~MapSector();
|
||||||
|
|
||||||
virtual u16 nodeContainerId() const
|
|
||||||
{
|
|
||||||
return NODECONTAINER_ID_MAPSECTOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual u32 getId() const = 0;
|
virtual u32 getId() const = 0;
|
||||||
|
|
||||||
void deleteBlocks();
|
void deleteBlocks();
|
||||||
@ -59,167 +56,32 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
MapBlock * getBlockNoCreateNoEx(s16 y);
|
MapBlock * getBlockNoCreateNoEx(s16 y);
|
||||||
MapBlock * getBlockNoCreate(s16 y);
|
|
||||||
MapBlock * createBlankBlockNoInsert(s16 y);
|
MapBlock * createBlankBlockNoInsert(s16 y);
|
||||||
MapBlock * createBlankBlock(s16 y);
|
MapBlock * createBlankBlock(s16 y);
|
||||||
//MapBlock * getBlock(s16 y, bool generate=true);
|
|
||||||
|
|
||||||
void insertBlock(MapBlock *block);
|
void insertBlock(MapBlock *block);
|
||||||
|
|
||||||
// This is used to remove a dummy from the sector while generating it.
|
void deleteBlock(MapBlock *block);
|
||||||
// Block is only removed from internal container, not deleted.
|
|
||||||
void removeBlock(MapBlock *block);
|
|
||||||
|
|
||||||
/*
|
|
||||||
This might not be a thread-safe depending on the day.
|
|
||||||
See the implementation.
|
|
||||||
*/
|
|
||||||
void getBlocks(core::list<MapBlock*> &dest);
|
void getBlocks(core::list<MapBlock*> &dest);
|
||||||
|
|
||||||
/*
|
// Always false at the moment, because sector contains no metadata.
|
||||||
If all nodes in area can be accessed, returns true and
|
|
||||||
adds all blocks in area to blocks.
|
|
||||||
|
|
||||||
If all nodes in area cannot be accessed, returns false.
|
|
||||||
|
|
||||||
The implementation of this is quite slow
|
|
||||||
|
|
||||||
if blocks==NULL; it is not accessed at all.
|
|
||||||
*/
|
|
||||||
bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
|
|
||||||
core::map<s16, MapBlock*> *blocks)
|
|
||||||
{
|
|
||||||
core::map<s16, MapBlock*> bs;
|
|
||||||
|
|
||||||
v3s16 p_min = getNodeBlockPos(p_min_nodes);
|
|
||||||
v3s16 p_max = getNodeBlockPos(p_max_nodes);
|
|
||||||
if(p_min.X != 0 || p_min.Z != 0
|
|
||||||
|| p_max.X != 0 || p_max.Z != 0)
|
|
||||||
return false;
|
|
||||||
v3s16 y;
|
|
||||||
for(s16 y=p_min.Y; y<=p_max.Y; y++)
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
MapBlock *block = getBlockNoCreate(y);
|
|
||||||
if(block->isDummy())
|
|
||||||
return false;
|
|
||||||
if(blocks!=NULL)
|
|
||||||
bs[y] = block;
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(blocks!=NULL)
|
|
||||||
{
|
|
||||||
for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
|
|
||||||
i.atEnd()==false; i++)
|
|
||||||
{
|
|
||||||
MapBlock *block = i.getNode()->getValue();
|
|
||||||
s16 y = i.getNode()->getKey();
|
|
||||||
blocks->insert(y, block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
|
|
||||||
core::map<v3s16, MapBlock*> &blocks)
|
|
||||||
{
|
|
||||||
v3s16 p_min = getNodeBlockPos(p_min_nodes);
|
|
||||||
v3s16 p_max = getNodeBlockPos(p_max_nodes);
|
|
||||||
v3s16 y;
|
|
||||||
for(s16 y=p_min.Y; y<=p_max.Y; y++)
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
MapBlock *block = getBlockNoCreate(y);
|
|
||||||
blocks.insert(block->getPos(), block);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual from NodeContainer
|
|
||||||
bool isValidPosition(v3s16 p)
|
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
|
|
||||||
if(blockpos.X != 0 || blockpos.Z != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MapBlock *blockref;
|
|
||||||
try{
|
|
||||||
blockref = getBlockNoCreate(blockpos.Y);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual from NodeContainer
|
|
||||||
MapNode getNode(v3s16 p)
|
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
if(blockpos.X != 0 || blockpos.Z != 0)
|
|
||||||
throw InvalidPositionException
|
|
||||||
("MapSector only allows Y");
|
|
||||||
|
|
||||||
MapBlock * blockref = getBlockNoCreate(blockpos.Y);
|
|
||||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
|
|
||||||
return blockref->getNode(relpos);
|
|
||||||
}
|
|
||||||
// virtual from NodeContainer
|
|
||||||
void setNode(v3s16 p, MapNode & n)
|
|
||||||
{
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
|
||||||
if(blockpos.X != 0 || blockpos.Z != 0)
|
|
||||||
throw InvalidPositionException
|
|
||||||
("MapSector only allows Y");
|
|
||||||
|
|
||||||
MapBlock * blockref = getBlockNoCreate(blockpos.Y);
|
|
||||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
|
||||||
blockref->setNode(relpos, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED?
|
|
||||||
virtual f32 getGroundHeight(v2s16 p, bool generate=false)
|
|
||||||
{
|
|
||||||
return GROUNDHEIGHT_NOTFOUND_SETVALUE;
|
|
||||||
}
|
|
||||||
virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// When true, sector metadata is changed from the one on disk
|
|
||||||
// (sector metadata = all but blocks)
|
|
||||||
// Basically, this should be changed to true in every setter method
|
|
||||||
bool differs_from_disk;
|
bool differs_from_disk;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The pile of MapBlocks
|
// The pile of MapBlocks
|
||||||
core::map<s16, MapBlock*> m_blocks;
|
core::map<s16, MapBlock*> m_blocks;
|
||||||
//JMutex m_blocks_mutex; // For public access functions
|
|
||||||
|
|
||||||
NodeContainer *m_parent;
|
Map *m_parent;
|
||||||
// Position on parent (in MapBlock widths)
|
// Position on parent (in MapBlock widths)
|
||||||
v2s16 m_pos;
|
v2s16 m_pos;
|
||||||
|
|
||||||
|
// Last-used block is cached here for quicker access.
|
||||||
// Be sure to set this to NULL when the cached block is deleted
|
// Be sure to set this to NULL when the cached block is deleted
|
||||||
MapBlock *m_block_cache;
|
MapBlock *m_block_cache;
|
||||||
s16 m_block_cache_y;
|
s16 m_block_cache_y;
|
||||||
|
|
||||||
// This is used for protecting m_blocks
|
|
||||||
JMutex m_mutex;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Private methods
|
Private methods
|
||||||
*/
|
*/
|
||||||
@ -230,7 +92,7 @@ protected:
|
|||||||
class ServerMapSector : public MapSector
|
class ServerMapSector : public MapSector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerMapSector(NodeContainer *parent, v2s16 pos);
|
ServerMapSector(Map *parent, v2s16 pos);
|
||||||
~ServerMapSector();
|
~ServerMapSector();
|
||||||
|
|
||||||
u32 getId() const
|
u32 getId() const
|
||||||
@ -238,19 +100,16 @@ public:
|
|||||||
return MAPSECTOR_SERVER;
|
return MAPSECTOR_SERVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEPRECATED?
|
|
||||||
f32 getGroundHeight(v2s16 p, bool generate=false);
|
|
||||||
void setGroundHeight(v2s16 p, f32 y, bool generate=false);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These functions handle metadata.
|
These functions handle metadata.
|
||||||
They do not handle blocks.
|
They do not handle blocks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serialize(std::ostream &os, u8 version);
|
void serialize(std::ostream &os, u8 version);
|
||||||
|
|
||||||
static ServerMapSector* deSerialize(
|
static ServerMapSector* deSerialize(
|
||||||
std::istream &is,
|
std::istream &is,
|
||||||
NodeContainer *parent,
|
Map *parent,
|
||||||
v2s16 p2d,
|
v2s16 p2d,
|
||||||
core::map<v2s16, MapSector*> & sectors
|
core::map<v2s16, MapSector*> & sectors
|
||||||
);
|
);
|
||||||
@ -262,7 +121,7 @@ private:
|
|||||||
class ClientMapSector : public MapSector
|
class ClientMapSector : public MapSector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClientMapSector(NodeContainer *parent, v2s16 pos);
|
ClientMapSector(Map *parent, v2s16 pos);
|
||||||
~ClientMapSector();
|
~ClientMapSector();
|
||||||
|
|
||||||
u32 getId() const
|
u32 getId() const
|
||||||
@ -270,16 +129,7 @@ public:
|
|||||||
return MAPSECTOR_CLIENT;
|
return MAPSECTOR_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deSerialize(std::istream &is);
|
|
||||||
|
|
||||||
/*s16 getCorner(u16 i)
|
|
||||||
{
|
|
||||||
return m_corners[i];
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The ground height of the corners is stored in here
|
|
||||||
//s16 m_corners[4];
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MINERAL_HEADER
|
#define MINERAL_HEADER
|
||||||
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "tile.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Minerals
|
Minerals
|
||||||
|
@ -238,7 +238,11 @@ double noise3d_param(const NoiseParams ¶m, double x, double y, double z)
|
|||||||
y /= s;
|
y /= s;
|
||||||
z /= s;
|
z /= s;
|
||||||
|
|
||||||
if(param.type == NOISE_PERLIN)
|
if(param.type == NOISE_CONSTANT_ONE)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
else if(param.type == NOISE_PERLIN)
|
||||||
{
|
{
|
||||||
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
|
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
|
||||||
param.octaves,
|
param.octaves,
|
||||||
|
@ -82,10 +82,11 @@ double noise3d_perlin_abs(double x, double y, double z, int seed,
|
|||||||
|
|
||||||
enum NoiseType
|
enum NoiseType
|
||||||
{
|
{
|
||||||
|
NOISE_CONSTANT_ONE,
|
||||||
NOISE_PERLIN,
|
NOISE_PERLIN,
|
||||||
NOISE_PERLIN_ABS,
|
NOISE_PERLIN_ABS,
|
||||||
NOISE_PERLIN_CONTOUR,
|
NOISE_PERLIN_CONTOUR,
|
||||||
NOISE_PERLIN_CONTOUR_FLIP_YZ
|
NOISE_PERLIN_CONTOUR_FLIP_YZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NoiseParams
|
struct NoiseParams
|
||||||
|
@ -309,6 +309,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||||||
v3f oldpos = position;
|
v3f oldpos = position;
|
||||||
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
||||||
|
|
||||||
|
v3f old_speed = m_speed;
|
||||||
|
|
||||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||||
|
|
||||||
@ -405,8 +407,23 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||||||
if(position.Y < min_y)
|
if(position.Y < min_y)
|
||||||
{
|
{
|
||||||
position.Y = min_y;
|
position.Y = min_y;
|
||||||
|
|
||||||
|
//v3f old_speed = m_speed;
|
||||||
|
|
||||||
if(m_speed.Y < 0)
|
if(m_speed.Y < 0)
|
||||||
m_speed.Y = 0;
|
m_speed.Y = 0;
|
||||||
|
|
||||||
|
/*if(collision_info)
|
||||||
|
{
|
||||||
|
// Report fall collision
|
||||||
|
if(old_speed.Y < m_speed.Y - 0.1)
|
||||||
|
{
|
||||||
|
CollisionInfo info;
|
||||||
|
info.t = COLLISION_FALL;
|
||||||
|
info.speed = m_speed.Y - old_speed.Y;
|
||||||
|
collision_info->push_back(info);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,13 +574,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||||||
*/
|
*/
|
||||||
if(other_axes_overlap && main_axis_collides)
|
if(other_axes_overlap && main_axis_collides)
|
||||||
{
|
{
|
||||||
v3f old_speed = m_speed;
|
//v3f old_speed = m_speed;
|
||||||
|
|
||||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
|
||||||
if(collision_info)
|
/*if(collision_info)
|
||||||
{
|
{
|
||||||
// Report fall collision
|
// Report fall collision
|
||||||
if(old_speed.Y < m_speed.Y - 0.1)
|
if(old_speed.Y < m_speed.Y - 0.1)
|
||||||
@ -573,7 +590,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||||||
info.speed = m_speed.Y - old_speed.Y;
|
info.speed = m_speed.Y - old_speed.Y;
|
||||||
collision_info->push_back(info);
|
collision_info->push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -656,6 +673,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||||||
Set new position
|
Set new position
|
||||||
*/
|
*/
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Report collisions
|
||||||
|
*/
|
||||||
|
if(collision_info)
|
||||||
|
{
|
||||||
|
// Report fall collision
|
||||||
|
if(old_speed.Y < m_speed.Y - 0.1)
|
||||||
|
{
|
||||||
|
CollisionInfo info;
|
||||||
|
info.t = COLLISION_FALL;
|
||||||
|
info.speed = m_speed.Y - old_speed.Y;
|
||||||
|
collision_info->push_back(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||||
|
@ -53,12 +53,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
15: StaticObjects
|
15: StaticObjects
|
||||||
16: larger maximum size of node metadata, and compression
|
16: larger maximum size of node metadata, and compression
|
||||||
17: MapBlocks contain timestamp
|
17: MapBlocks contain timestamp
|
||||||
18: sqlite/new generator/whatever
|
18: new generator (not really necessary, but it's there)
|
||||||
|
19: new content type handling
|
||||||
*/
|
*/
|
||||||
// This represents an uninitialized or invalid format
|
// This represents an uninitialized or invalid format
|
||||||
#define SER_FMT_VER_INVALID 255
|
#define SER_FMT_VER_INVALID 255
|
||||||
// Highest supported serialization version
|
// Highest supported serialization version
|
||||||
#define SER_FMT_VER_HIGHEST 18
|
#define SER_FMT_VER_HIGHEST 19
|
||||||
// Lowest supported serialization version
|
// Lowest supported serialization version
|
||||||
#define SER_FMT_VER_LOWEST 0
|
#define SER_FMT_VER_LOWEST 0
|
||||||
|
|
||||||
|
153
src/server.cpp
153
src/server.cpp
@ -34,6 +34,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
#include "content_craft.h"
|
#include "content_craft.h"
|
||||||
#include "content_nodemeta.h"
|
#include "content_nodemeta.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
#include "serverobject.h"
|
||||||
|
|
||||||
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
||||||
|
|
||||||
@ -600,6 +602,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
bool block_is_invalid = false;
|
bool block_is_invalid = false;
|
||||||
if(block != NULL)
|
if(block != NULL)
|
||||||
{
|
{
|
||||||
|
// Reset usage timer, this block will be of use in the future.
|
||||||
|
block->resetUsageTimer();
|
||||||
|
|
||||||
// Block is dummy if data doesn't exist.
|
// Block is dummy if data doesn't exist.
|
||||||
// It means it has been not found from disk and not generated
|
// It means it has been not found from disk and not generated
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
@ -1295,13 +1300,22 @@ void Server::AsyncRunStep()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Step environment
|
|
||||||
// This also runs Map's timers
|
|
||||||
JMutexAutoLock lock(m_env_mutex);
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
|
// Step environment
|
||||||
ScopeProfiler sp(&g_profiler, "Server: environment step");
|
ScopeProfiler sp(&g_profiler, "Server: environment step");
|
||||||
m_env.step(dtime);
|
m_env.step(dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float map_timer_and_unload_dtime = 5.15;
|
||||||
|
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
|
// Run Map's timers and unload unused data
|
||||||
|
ScopeProfiler sp(&g_profiler, "Server: map timer and unload");
|
||||||
|
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||||
|
g_settings.getFloat("server_unload_unused_data_timeout"));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do background stuff
|
Do background stuff
|
||||||
*/
|
*/
|
||||||
@ -1656,9 +1670,22 @@ void Server::AsyncRunStep()
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
// Don't send too many at a time
|
// Don't send too many at a time
|
||||||
u32 count = 0;
|
//u32 count = 0;
|
||||||
|
|
||||||
|
// Single change sending is disabled if queue size is not small
|
||||||
|
bool disable_single_change_sending = false;
|
||||||
|
if(m_unsent_map_edit_queue.size() >= 4)
|
||||||
|
disable_single_change_sending = true;
|
||||||
|
|
||||||
|
bool got_any_events = false;
|
||||||
|
|
||||||
|
// We'll log the amount of each
|
||||||
|
Profiler prof;
|
||||||
|
|
||||||
while(m_unsent_map_edit_queue.size() != 0)
|
while(m_unsent_map_edit_queue.size() != 0)
|
||||||
{
|
{
|
||||||
|
got_any_events = true;
|
||||||
|
|
||||||
MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
|
MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
|
||||||
|
|
||||||
// Players far away from the change are stored here.
|
// Players far away from the change are stored here.
|
||||||
@ -1668,28 +1695,41 @@ void Server::AsyncRunStep()
|
|||||||
|
|
||||||
if(event->type == MEET_ADDNODE)
|
if(event->type == MEET_ADDNODE)
|
||||||
{
|
{
|
||||||
dstream<<"Server: MEET_ADDNODE"<<std::endl;
|
//dstream<<"Server: MEET_ADDNODE"<<std::endl;
|
||||||
|
prof.add("MEET_ADDNODE", 1);
|
||||||
|
if(disable_single_change_sending)
|
||||||
|
sendAddNode(event->p, event->n, event->already_known_by_peer,
|
||||||
|
&far_players, 5);
|
||||||
|
else
|
||||||
sendAddNode(event->p, event->n, event->already_known_by_peer,
|
sendAddNode(event->p, event->n, event->already_known_by_peer,
|
||||||
&far_players, 30);
|
&far_players, 30);
|
||||||
}
|
}
|
||||||
else if(event->type == MEET_REMOVENODE)
|
else if(event->type == MEET_REMOVENODE)
|
||||||
{
|
{
|
||||||
dstream<<"Server: MEET_REMOVENODE"<<std::endl;
|
//dstream<<"Server: MEET_REMOVENODE"<<std::endl;
|
||||||
|
prof.add("MEET_REMOVENODE", 1);
|
||||||
|
if(disable_single_change_sending)
|
||||||
|
sendRemoveNode(event->p, event->already_known_by_peer,
|
||||||
|
&far_players, 5);
|
||||||
|
else
|
||||||
sendRemoveNode(event->p, event->already_known_by_peer,
|
sendRemoveNode(event->p, event->already_known_by_peer,
|
||||||
&far_players, 30);
|
&far_players, 30);
|
||||||
}
|
}
|
||||||
else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
|
else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
|
||||||
{
|
{
|
||||||
dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
|
dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
|
||||||
|
prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
|
||||||
setBlockNotSent(event->p);
|
setBlockNotSent(event->p);
|
||||||
}
|
}
|
||||||
else if(event->type == MEET_OTHER)
|
else if(event->type == MEET_OTHER)
|
||||||
{
|
{
|
||||||
|
prof.add("MEET_OTHER", 1);
|
||||||
dstream<<"WARNING: Server: MEET_OTHER not implemented"
|
dstream<<"WARNING: Server: MEET_OTHER not implemented"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
prof.add("unknown", 1);
|
||||||
dstream<<"WARNING: Server: Unknown MapEditEvent "
|
dstream<<"WARNING: Server: Unknown MapEditEvent "
|
||||||
<<((u32)event->type)<<std::endl;
|
<<((u32)event->type)<<std::endl;
|
||||||
}
|
}
|
||||||
@ -1697,14 +1737,19 @@ void Server::AsyncRunStep()
|
|||||||
/*
|
/*
|
||||||
Set blocks not sent to far players
|
Set blocks not sent to far players
|
||||||
*/
|
*/
|
||||||
|
if(far_players.size() > 0)
|
||||||
|
{
|
||||||
|
// Convert list format to that wanted by SetBlocksNotSent
|
||||||
core::map<v3s16, MapBlock*> modified_blocks2;
|
core::map<v3s16, MapBlock*> modified_blocks2;
|
||||||
for(core::map<v3s16, bool>::Iterator
|
for(core::map<v3s16, bool>::Iterator
|
||||||
i = event->modified_blocks.getIterator();
|
i = event->modified_blocks.getIterator();
|
||||||
i.atEnd()==false; i++)
|
i.atEnd()==false; i++)
|
||||||
{
|
{
|
||||||
v3s16 p = i.getNode()->getKey();
|
v3s16 p = i.getNode()->getKey();
|
||||||
modified_blocks2.insert(p, m_env.getMap().getBlockNoCreateNoEx(p));
|
modified_blocks2.insert(p,
|
||||||
|
m_env.getMap().getBlockNoCreateNoEx(p));
|
||||||
}
|
}
|
||||||
|
// Set blocks not sent
|
||||||
for(core::list<u16>::Iterator
|
for(core::list<u16>::Iterator
|
||||||
i = far_players.begin();
|
i = far_players.begin();
|
||||||
i != far_players.end(); i++)
|
i != far_players.end(); i++)
|
||||||
@ -1715,14 +1760,22 @@ void Server::AsyncRunStep()
|
|||||||
continue;
|
continue;
|
||||||
client->SetBlocksNotSent(modified_blocks2);
|
client->SetBlocksNotSent(modified_blocks2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete event;
|
delete event;
|
||||||
|
|
||||||
// Don't send too many at a time
|
/*// Don't send too many at a time
|
||||||
count++;
|
count++;
|
||||||
if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
|
if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
|
||||||
break;
|
break;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(got_any_events)
|
||||||
|
{
|
||||||
|
dstream<<"Server: MapEditEvents:"<<std::endl;
|
||||||
|
prof.print(dstream);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1745,39 +1798,6 @@ void Server::AsyncRunStep()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Step node metadata
|
|
||||||
TODO: Move to ServerEnvironment and utilize active block stuff
|
|
||||||
*/
|
|
||||||
/*{
|
|
||||||
//TimeTaker timer("Step node metadata");
|
|
||||||
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
JMutexAutoLock conlock(m_con_mutex);
|
|
||||||
|
|
||||||
ScopeProfiler sp(&g_profiler, "Server: stepping node metadata");
|
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> changed_blocks;
|
|
||||||
m_env.getMap().nodeMetadataStep(dtime, changed_blocks);
|
|
||||||
|
|
||||||
// Use setBlockNotSent
|
|
||||||
|
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
|
||||||
i = changed_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlock *block = i.getNode()->getValue();
|
|
||||||
|
|
||||||
for(core::map<u16, RemoteClient*>::Iterator
|
|
||||||
i = m_clients.getIterator();
|
|
||||||
i.atEnd()==false; i++)
|
|
||||||
{
|
|
||||||
RemoteClient *client = i.getNode()->getValue();
|
|
||||||
client->SetBlockNotSent(block->getPos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Trigger emergethread (it somehow gets to a non-triggered but
|
Trigger emergethread (it somehow gets to a non-triggered but
|
||||||
bysy state sometimes)
|
bysy state sometimes)
|
||||||
@ -1809,19 +1829,23 @@ void Server::AsyncRunStep()
|
|||||||
|
|
||||||
// Map
|
// Map
|
||||||
JMutexAutoLock lock(m_env_mutex);
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == true)
|
|
||||||
{
|
/*// Unload unused data (delete from memory)
|
||||||
|
m_env.getMap().unloadUnusedData(
|
||||||
|
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||||
|
*/
|
||||||
|
/*u32 deleted_count = m_env.getMap().unloadUnusedData(
|
||||||
|
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||||
|
*/
|
||||||
|
|
||||||
// Save only changed parts
|
// Save only changed parts
|
||||||
m_env.getMap().save(true);
|
m_env.getMap().save(true);
|
||||||
|
|
||||||
// Delete unused sectors
|
/*if(deleted_count > 0)
|
||||||
u32 deleted_count = m_env.getMap().unloadUnusedData(
|
|
||||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
|
||||||
if(deleted_count > 0)
|
|
||||||
{
|
{
|
||||||
dout_server<<"Server: Unloaded "<<deleted_count
|
dout_server<<"Server: Unloaded "<<deleted_count
|
||||||
<<" sectors from memory"<<std::endl;
|
<<" blocks from memory"<<std::endl;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Save players
|
// Save players
|
||||||
m_env.serializePlayers(m_mapsavedir);
|
m_env.serializePlayers(m_mapsavedir);
|
||||||
@ -1831,7 +1855,6 @@ void Server::AsyncRunStep()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Server::Receive()
|
void Server::Receive()
|
||||||
{
|
{
|
||||||
@ -2393,7 +2416,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 wear = obj->punch(toolname);
|
v3f playerpos = player->getPosition();
|
||||||
|
v3f objpos = obj->getBasePosition();
|
||||||
|
v3f dir = (objpos - playerpos).normalize();
|
||||||
|
|
||||||
|
u16 wear = obj->punch(toolname, dir);
|
||||||
|
|
||||||
if(titem)
|
if(titem)
|
||||||
{
|
{
|
||||||
@ -2710,9 +2737,31 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
MaterialItem *mitem = (MaterialItem*)item;
|
MaterialItem *mitem = (MaterialItem*)item;
|
||||||
MapNode n;
|
MapNode n;
|
||||||
n.d = mitem->getMaterial();
|
n.d = mitem->getMaterial();
|
||||||
|
|
||||||
|
// Calculate direction for wall mounted stuff
|
||||||
if(content_features(n.d).wall_mounted)
|
if(content_features(n.d).wall_mounted)
|
||||||
n.dir = packDir(p_under - p_over);
|
n.dir = packDir(p_under - p_over);
|
||||||
|
|
||||||
|
// Calculate the direction for furnaces and chests and stuff
|
||||||
|
if(content_features(n.d).param_type == CPT_FACEDIR_SIMPLE)
|
||||||
|
{
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v3f blockpos = intToFloat(p_over, BS) - playerpos;
|
||||||
|
blockpos = blockpos.normalize();
|
||||||
|
n.param1 = 0;
|
||||||
|
if (fabs(blockpos.X) > fabs(blockpos.Z)) {
|
||||||
|
if (blockpos.X < 0)
|
||||||
|
n.param1 = 3;
|
||||||
|
else
|
||||||
|
n.param1 = 1;
|
||||||
|
} else {
|
||||||
|
if (blockpos.Z < 0)
|
||||||
|
n.param1 = 2;
|
||||||
|
else
|
||||||
|
n.param1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send to all close-by players
|
Send to all close-by players
|
||||||
*/
|
*/
|
||||||
@ -3286,7 +3335,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
|
|
||||||
void Server::onMapEditEvent(MapEditEvent *event)
|
void Server::onMapEditEvent(MapEditEvent *event)
|
||||||
{
|
{
|
||||||
dstream<<"Server::onMapEditEvent()"<<std::endl;
|
//dstream<<"Server::onMapEditEvent()"<<std::endl;
|
||||||
if(m_ignore_map_edit_events)
|
if(m_ignore_map_edit_events)
|
||||||
return;
|
return;
|
||||||
MapEditEvent *e = event->clone();
|
MapEditEvent *e = event->clone();
|
||||||
|
@ -534,6 +534,7 @@ private:
|
|||||||
float m_objectdata_timer;
|
float m_objectdata_timer;
|
||||||
float m_emergethread_trigger_timer;
|
float m_emergethread_trigger_timer;
|
||||||
float m_savemap_timer;
|
float m_savemap_timer;
|
||||||
|
IntervalLimiter m_map_timer_and_unload_interval;
|
||||||
|
|
||||||
// NOTE: If connection and environment are both to be locked,
|
// NOTE: If connection and environment are both to be locked,
|
||||||
// environment shall be locked first.
|
// environment shall be locked first.
|
||||||
|
@ -19,9 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "environment.h"
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "collision.h"
|
|
||||||
|
|
||||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||||
|
|
||||||
@ -71,600 +69,4 @@ void ServerActiveObject::registerType(u16 type, Factory f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TestSAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
|
|
||||||
|
|
||||||
TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
|
|
||||||
ServerActiveObject(env, id, pos),
|
|
||||||
m_timer1(0),
|
|
||||||
m_age(0)
|
|
||||||
{
|
|
||||||
ServerActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data)
|
|
||||||
{
|
|
||||||
return new TestSAO(env, id, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended)
|
|
||||||
{
|
|
||||||
m_age += dtime;
|
|
||||||
if(m_age > 10)
|
|
||||||
{
|
|
||||||
m_removed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_base_position.Y += dtime * BS * 2;
|
|
||||||
if(m_base_position.Y > 8*BS)
|
|
||||||
m_base_position.Y = 2*BS;
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_timer1 -= dtime;
|
|
||||||
if(m_timer1 < 0.0)
|
|
||||||
{
|
|
||||||
m_timer1 += 0.125;
|
|
||||||
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
|
|
||||||
|
|
||||||
std::string data;
|
|
||||||
|
|
||||||
data += itos(0); // 0 = position
|
|
||||||
data += " ";
|
|
||||||
data += itos(m_base_position.X);
|
|
||||||
data += " ";
|
|
||||||
data += itos(m_base_position.Y);
|
|
||||||
data += " ";
|
|
||||||
data += itos(m_base_position.Z);
|
|
||||||
|
|
||||||
ActiveObjectMessage aom(getId(), false, data);
|
|
||||||
messages.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
ItemSAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
|
|
||||||
|
|
||||||
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string inventorystring):
|
|
||||||
ServerActiveObject(env, id, pos),
|
|
||||||
m_inventorystring(inventorystring),
|
|
||||||
m_speed_f(0,0,0),
|
|
||||||
m_last_sent_position(0,0,0)
|
|
||||||
{
|
|
||||||
ServerActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data)
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
char buf[1];
|
|
||||||
// read version
|
|
||||||
is.read(buf, 1);
|
|
||||||
u8 version = buf[0];
|
|
||||||
// check if version is supported
|
|
||||||
if(version != 0)
|
|
||||||
return NULL;
|
|
||||||
std::string inventorystring = deSerializeString(is);
|
|
||||||
dstream<<"ItemSAO::create(): Creating item \""
|
|
||||||
<<inventorystring<<"\""<<std::endl;
|
|
||||||
return new ItemSAO(env, id, pos, inventorystring);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended)
|
|
||||||
{
|
|
||||||
assert(m_env);
|
|
||||||
|
|
||||||
const float interval = 0.2;
|
|
||||||
if(m_move_interval.step(dtime, interval)==false)
|
|
||||||
return;
|
|
||||||
dtime = interval;
|
|
||||||
|
|
||||||
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
|
||||||
collisionMoveResult moveresult;
|
|
||||||
// Apply gravity
|
|
||||||
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
|
|
||||||
// Maximum movement without glitches
|
|
||||||
f32 pos_max_d = BS*0.25;
|
|
||||||
// Limit speed
|
|
||||||
if(m_speed_f.getLength()*dtime > pos_max_d)
|
|
||||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
|
||||||
v3f pos_f = getBasePosition();
|
|
||||||
v3f pos_f_old = pos_f;
|
|
||||||
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
|
||||||
box, dtime, pos_f, m_speed_f);
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
|
||||||
{
|
|
||||||
setBasePosition(pos_f);
|
|
||||||
m_last_sent_position = pos_f;
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
char buf[6];
|
|
||||||
// command (0 = update position)
|
|
||||||
buf[0] = 0;
|
|
||||||
os.write(buf, 1);
|
|
||||||
// pos
|
|
||||||
writeS32((u8*)buf, m_base_position.X*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
messages.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ItemSAO::getClientInitializationData()
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
char buf[6];
|
|
||||||
// version
|
|
||||||
buf[0] = 0;
|
|
||||||
os.write(buf, 1);
|
|
||||||
// pos
|
|
||||||
writeS32((u8*)buf, m_base_position.X*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
|
||||||
os.write(buf, 4);
|
|
||||||
// inventorystring
|
|
||||||
os<<serializeString(m_inventorystring);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ItemSAO::getStaticData()
|
|
||||||
{
|
|
||||||
dstream<<__FUNCTION_NAME<<std::endl;
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
char buf[1];
|
|
||||||
// version
|
|
||||||
buf[0] = 0;
|
|
||||||
os.write(buf, 1);
|
|
||||||
// inventorystring
|
|
||||||
os<<serializeString(m_inventorystring);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryItem * ItemSAO::createInventoryItem()
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
|
||||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
|
||||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
|
||||||
<<m_inventorystring<<"\" -> item="<<item
|
|
||||||
<<std::endl;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
catch(SerializationError &e)
|
|
||||||
{
|
|
||||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
|
||||||
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
RatSAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
|
|
||||||
|
|
||||||
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
|
|
||||||
ServerActiveObject(env, id, pos),
|
|
||||||
m_is_active(false),
|
|
||||||
m_speed_f(0,0,0)
|
|
||||||
{
|
|
||||||
ServerActiveObject::registerType(getType(), create);
|
|
||||||
|
|
||||||
m_oldpos = v3f(0,0,0);
|
|
||||||
m_last_sent_position = v3f(0,0,0);
|
|
||||||
m_yaw = 0;
|
|
||||||
m_counter1 = 0;
|
|
||||||
m_counter2 = 0;
|
|
||||||
m_age = 0;
|
|
||||||
m_touching_ground = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data)
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
char buf[1];
|
|
||||||
// read version
|
|
||||||
is.read(buf, 1);
|
|
||||||
u8 version = buf[0];
|
|
||||||
// check if version is supported
|
|
||||||
if(version != 0)
|
|
||||||
return NULL;
|
|
||||||
return new RatSAO(env, id, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended)
|
|
||||||
{
|
|
||||||
assert(m_env);
|
|
||||||
|
|
||||||
if(m_is_active == false)
|
|
||||||
{
|
|
||||||
if(m_inactive_interval.step(dtime, 0.5)==false)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The AI
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*m_age += dtime;
|
|
||||||
if(m_age > 60)
|
|
||||||
{
|
|
||||||
// Die
|
|
||||||
m_removed = true;
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Apply gravity
|
|
||||||
m_speed_f.Y -= dtime*9.81*BS;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Move around if some player is close
|
|
||||||
*/
|
|
||||||
bool player_is_close = false;
|
|
||||||
// Check connected players
|
|
||||||
core::list<Player*> players = m_env->getPlayers(true);
|
|
||||||
core::list<Player*>::Iterator i;
|
|
||||||
for(i = players.begin();
|
|
||||||
i != players.end(); i++)
|
|
||||||
{
|
|
||||||
Player *player = *i;
|
|
||||||
v3f playerpos = player->getPosition();
|
|
||||||
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
|
|
||||||
{
|
|
||||||
player_is_close = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_is_active = player_is_close;
|
|
||||||
|
|
||||||
if(player_is_close == false)
|
|
||||||
{
|
|
||||||
m_speed_f.X = 0;
|
|
||||||
m_speed_f.Z = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move around
|
|
||||||
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
|
||||||
f32 speed = 2*BS;
|
|
||||||
m_speed_f.X = speed * dir.X;
|
|
||||||
m_speed_f.Z = speed * dir.Z;
|
|
||||||
|
|
||||||
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
|
||||||
< dtime*speed/2)
|
|
||||||
{
|
|
||||||
m_counter1 -= dtime;
|
|
||||||
if(m_counter1 < 0.0)
|
|
||||||
{
|
|
||||||
m_counter1 += 1.0;
|
|
||||||
m_speed_f.Y = 5.0*BS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
m_counter2 -= dtime;
|
|
||||||
if(m_counter2 < 0.0)
|
|
||||||
{
|
|
||||||
m_counter2 += (float)(myrand()%100)/100*3.0;
|
|
||||||
m_yaw += ((float)(myrand()%200)-100)/100*180;
|
|
||||||
m_yaw = wrapDegrees(m_yaw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_oldpos = m_base_position;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Move it, with collision detection
|
|
||||||
*/
|
|
||||||
|
|
||||||
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
|
||||||
collisionMoveResult moveresult;
|
|
||||||
// Maximum movement without glitches
|
|
||||||
f32 pos_max_d = BS*0.25;
|
|
||||||
// Limit speed
|
|
||||||
if(m_speed_f.getLength()*dtime > pos_max_d)
|
|
||||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
|
||||||
v3f pos_f = getBasePosition();
|
|
||||||
v3f pos_f_old = pos_f;
|
|
||||||
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
|
||||||
box, dtime, pos_f, m_speed_f);
|
|
||||||
m_touching_ground = moveresult.touching_ground;
|
|
||||||
|
|
||||||
setBasePosition(pos_f);
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
|
||||||
{
|
|
||||||
m_last_sent_position = pos_f;
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// command (0 = update position)
|
|
||||||
writeU8(os, 0);
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, m_base_position);
|
|
||||||
// yaw
|
|
||||||
writeF1000(os, m_yaw);
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
messages.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RatSAO::getClientInitializationData()
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// version
|
|
||||||
writeU8(os, 0);
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, m_base_position);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RatSAO::getStaticData()
|
|
||||||
{
|
|
||||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// version
|
|
||||||
writeU8(os, 0);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryItem* RatSAO::createPickedUpItem()
|
|
||||||
{
|
|
||||||
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
|
|
||||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Oerkki1SAO
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
|
||||||
|
|
||||||
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
|
|
||||||
ServerActiveObject(env, id, pos),
|
|
||||||
m_is_active(false),
|
|
||||||
m_speed_f(0,0,0)
|
|
||||||
{
|
|
||||||
ServerActiveObject::registerType(getType(), create);
|
|
||||||
|
|
||||||
m_oldpos = v3f(0,0,0);
|
|
||||||
m_last_sent_position = v3f(0,0,0);
|
|
||||||
m_yaw = 0;
|
|
||||||
m_counter1 = 0;
|
|
||||||
m_counter2 = 0;
|
|
||||||
m_age = 0;
|
|
||||||
m_touching_ground = false;
|
|
||||||
m_hp = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data)
|
|
||||||
{
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
|
||||||
// read version
|
|
||||||
u8 version = readU8(is);
|
|
||||||
// read hp
|
|
||||||
u8 hp = readU8(is);
|
|
||||||
// check if version is supported
|
|
||||||
if(version != 0)
|
|
||||||
return NULL;
|
|
||||||
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
|
|
||||||
o->m_hp = hp;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oerkki1SAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended)
|
|
||||||
{
|
|
||||||
assert(m_env);
|
|
||||||
|
|
||||||
if(m_is_active == false)
|
|
||||||
{
|
|
||||||
if(m_inactive_interval.step(dtime, 0.5)==false)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The AI
|
|
||||||
*/
|
|
||||||
|
|
||||||
m_age += dtime;
|
|
||||||
if(m_age > 120)
|
|
||||||
{
|
|
||||||
// Die
|
|
||||||
m_removed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply gravity
|
|
||||||
m_speed_f.Y -= dtime*9.81*BS;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Move around if some player is close
|
|
||||||
*/
|
|
||||||
bool player_is_close = false;
|
|
||||||
v3f near_player_pos;
|
|
||||||
// Check connected players
|
|
||||||
core::list<Player*> players = m_env->getPlayers(true);
|
|
||||||
core::list<Player*>::Iterator i;
|
|
||||||
for(i = players.begin();
|
|
||||||
i != players.end(); i++)
|
|
||||||
{
|
|
||||||
Player *player = *i;
|
|
||||||
v3f playerpos = player->getPosition();
|
|
||||||
if(m_base_position.getDistanceFrom(playerpos) < BS*15.0)
|
|
||||||
{
|
|
||||||
player_is_close = true;
|
|
||||||
near_player_pos = playerpos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_is_active = player_is_close;
|
|
||||||
|
|
||||||
if(player_is_close == false)
|
|
||||||
{
|
|
||||||
m_speed_f.X = 0;
|
|
||||||
m_speed_f.Z = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move around
|
|
||||||
|
|
||||||
v3f ndir = near_player_pos - m_base_position;
|
|
||||||
ndir.Y = 0;
|
|
||||||
ndir /= ndir.getLength();
|
|
||||||
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
|
|
||||||
if(nyaw < m_yaw - 180)
|
|
||||||
nyaw += 360;
|
|
||||||
else if(nyaw > m_yaw + 180)
|
|
||||||
nyaw -= 360;
|
|
||||||
m_yaw = 0.95*m_yaw + 0.05*nyaw;
|
|
||||||
m_yaw = wrapDegrees(m_yaw);
|
|
||||||
|
|
||||||
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
|
||||||
f32 speed = 2*BS;
|
|
||||||
m_speed_f.X = speed * dir.X;
|
|
||||||
m_speed_f.Z = speed * dir.Z;
|
|
||||||
|
|
||||||
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
|
||||||
< dtime*speed/2)
|
|
||||||
{
|
|
||||||
m_counter1 -= dtime;
|
|
||||||
if(m_counter1 < 0.0)
|
|
||||||
{
|
|
||||||
m_counter1 += 1.0;
|
|
||||||
// Jump
|
|
||||||
m_speed_f.Y = 5.0*BS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
m_counter2 -= dtime;
|
|
||||||
if(m_counter2 < 0.0)
|
|
||||||
{
|
|
||||||
m_counter2 += (float)(myrand()%100)/100*3.0;
|
|
||||||
//m_yaw += ((float)(myrand()%200)-100)/100*180;
|
|
||||||
m_yaw += ((float)(myrand()%200)-100)/100*90;
|
|
||||||
m_yaw = wrapDegrees(m_yaw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_oldpos = m_base_position;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Move it, with collision detection
|
|
||||||
*/
|
|
||||||
|
|
||||||
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
|
|
||||||
collisionMoveResult moveresult;
|
|
||||||
// Maximum movement without glitches
|
|
||||||
f32 pos_max_d = BS*0.25;
|
|
||||||
// Limit speed
|
|
||||||
if(m_speed_f.getLength()*dtime > pos_max_d)
|
|
||||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
|
||||||
v3f pos_f = getBasePosition();
|
|
||||||
v3f pos_f_old = pos_f;
|
|
||||||
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
|
||||||
box, dtime, pos_f, m_speed_f);
|
|
||||||
m_touching_ground = moveresult.touching_ground;
|
|
||||||
|
|
||||||
setBasePosition(pos_f);
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
|
||||||
{
|
|
||||||
m_last_sent_position = pos_f;
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// command (0 = update position)
|
|
||||||
writeU8(os, 0);
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, m_base_position);
|
|
||||||
// yaw
|
|
||||||
writeF1000(os, m_yaw);
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
messages.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Oerkki1SAO::getClientInitializationData()
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// version
|
|
||||||
writeU8(os, 0);
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, m_base_position);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Oerkki1SAO::getStaticData()
|
|
||||||
{
|
|
||||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// version
|
|
||||||
writeU8(os, 0);
|
|
||||||
// hp
|
|
||||||
writeU8(os, m_hp);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 Oerkki1SAO::punch(const std::string &toolname)
|
|
||||||
{
|
|
||||||
u16 amount = 5;
|
|
||||||
if(amount < m_hp)
|
|
||||||
{
|
|
||||||
m_hp -= amount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Die
|
|
||||||
m_removed = true;
|
|
||||||
}
|
|
||||||
return 65536/100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,8 +78,7 @@ public:
|
|||||||
same time so that the data can be combined in a single
|
same time so that the data can be combined in a single
|
||||||
packet.
|
packet.
|
||||||
*/
|
*/
|
||||||
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
virtual void step(float dtime, bool send_recommended){}
|
||||||
bool send_recommended){}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The return value of this is passed to the client-side object
|
The return value of this is passed to the client-side object
|
||||||
@ -104,7 +103,8 @@ public:
|
|||||||
If the object doesn't return an item, this will be called.
|
If the object doesn't return an item, this will be called.
|
||||||
Return value is tool wear.
|
Return value is tool wear.
|
||||||
*/
|
*/
|
||||||
virtual u16 punch(const std::string &toolname){return 0;}
|
virtual u16 punch(const std::string &toolname, v3f dir)
|
||||||
|
{return 0;}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Number of players which know about this object. Object won't be
|
Number of players which know about this object. Object won't be
|
||||||
@ -144,6 +144,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
v3s16 m_static_block;
|
v3s16 m_static_block;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Queue of messages to be sent to the client
|
||||||
|
*/
|
||||||
|
Queue<ActiveObjectMessage> m_messages_out;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Used for creating objects based on type
|
// Used for creating objects based on type
|
||||||
typedef ServerActiveObject* (*Factory)
|
typedef ServerActiveObject* (*Factory)
|
||||||
@ -159,96 +164,5 @@ private:
|
|||||||
static core::map<u16, Factory> m_types;
|
static core::map<u16, Factory> m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestSAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_TEST;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended);
|
|
||||||
private:
|
|
||||||
float m_timer1;
|
|
||||||
float m_age;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ItemSAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string inventorystring);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_ITEM;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
InventoryItem* createInventoryItem();
|
|
||||||
InventoryItem* createPickedUpItem(){return createInventoryItem();}
|
|
||||||
private:
|
|
||||||
std::string m_inventorystring;
|
|
||||||
v3f m_speed_f;
|
|
||||||
v3f m_last_sent_position;
|
|
||||||
IntervalLimiter m_move_interval;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RatSAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_RAT;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
InventoryItem* createPickedUpItem();
|
|
||||||
private:
|
|
||||||
bool m_is_active;
|
|
||||||
IntervalLimiter m_inactive_interval;
|
|
||||||
v3f m_speed_f;
|
|
||||||
v3f m_oldpos;
|
|
||||||
v3f m_last_sent_position;
|
|
||||||
float m_yaw;
|
|
||||||
float m_counter1;
|
|
||||||
float m_counter2;
|
|
||||||
float m_age;
|
|
||||||
bool m_touching_ground;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Oerkki1SAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_OERKKI1;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
|
||||||
bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
InventoryItem* createPickedUpItem(){return NULL;}
|
|
||||||
u16 punch(const std::string &toolname);
|
|
||||||
private:
|
|
||||||
bool m_is_active;
|
|
||||||
IntervalLimiter m_inactive_interval;
|
|
||||||
v3f m_speed_f;
|
|
||||||
v3f m_oldpos;
|
|
||||||
v3f m_last_sent_position;
|
|
||||||
float m_yaw;
|
|
||||||
float m_counter1;
|
|
||||||
float m_counter2;
|
|
||||||
float m_age;
|
|
||||||
bool m_touching_ground;
|
|
||||||
u8 m_hp;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
20
src/test.cpp
20
src/test.cpp
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
|
#include "mapsector.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Asserts that the exception occurs
|
Asserts that the exception occurs
|
||||||
@ -339,6 +340,12 @@ struct TestVoxelManipulator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: These tests became non-working then NodeContainer was removed.
|
||||||
|
These should be redone, utilizing some kind of a virtual
|
||||||
|
interface for Map (IMap would be fine).
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
struct TestMapBlock
|
struct TestMapBlock
|
||||||
{
|
{
|
||||||
class TC : public NodeContainer
|
class TC : public NodeContainer
|
||||||
@ -641,13 +648,13 @@ struct TestMapSector
|
|||||||
// Create one with no heightmaps
|
// Create one with no heightmaps
|
||||||
ServerMapSector sector(&parent, v2s16(1,1));
|
ServerMapSector sector(&parent, v2s16(1,1));
|
||||||
|
|
||||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
|
assert(sector.getBlockNoCreateNoEx(0) == 0);
|
||||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(1));
|
assert(sector.getBlockNoCreateNoEx(1) == 0);
|
||||||
|
|
||||||
MapBlock * bref = sector.createBlankBlock(-2);
|
MapBlock * bref = sector.createBlankBlock(-2);
|
||||||
|
|
||||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
|
assert(sector.getBlockNoCreateNoEx(0) == 0);
|
||||||
assert(sector.getBlockNoCreate(-2) == bref);
|
assert(sector.getBlockNoCreateNoEx(-2) == bref);
|
||||||
|
|
||||||
//TODO: Check for AlreadyExistsException
|
//TODO: Check for AlreadyExistsException
|
||||||
|
|
||||||
@ -662,6 +669,7 @@ struct TestMapSector
|
|||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct TestSocket
|
struct TestSocket
|
||||||
{
|
{
|
||||||
@ -1028,8 +1036,8 @@ void run_tests()
|
|||||||
TEST(TestCompress);
|
TEST(TestCompress);
|
||||||
TEST(TestMapNode);
|
TEST(TestMapNode);
|
||||||
TEST(TestVoxelManipulator);
|
TEST(TestVoxelManipulator);
|
||||||
TEST(TestMapBlock);
|
//TEST(TestMapBlock);
|
||||||
TEST(TestMapSector);
|
//TEST(TestMapSector);
|
||||||
if(INTERNET_SIMULATOR == false){
|
if(INTERNET_SIMULATOR == false){
|
||||||
TEST(TestSocket);
|
TEST(TestSocket);
|
||||||
dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user