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/cmake_config.h
|
||||
src/jthread/cmake_install.cmake
|
||||
src/.*.swp
|
||||
src/sqlite/libsqlite3.a
|
||||
src/session.vim
|
||||
util/uloste.png
|
||||
minetest.conf
|
||||
debug.txt
|
||||
bin/
|
||||
CMakeCache.txt
|
||||
CPackConfig.cmake
|
||||
|
|
|
@ -9,7 +9,7 @@ project(minetest)
|
|||
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 2)
|
||||
set(VERSION_PATCH 20110618_0_dev)
|
||||
set(VERSION_PATCH 20110704_0)
|
||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
# Configuration options
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 341 B |
Binary file not shown.
After Width: | Height: | Size: 582 B |
|
@ -3,6 +3,11 @@ Minetest-c55 changelog
|
|||
This should contain all the major changes.
|
||||
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:
|
||||
- Password crash on windows fixed
|
||||
- Optimized server CPU usage a lot
|
||||
|
|
|
@ -9,25 +9,28 @@
|
|||
#
|
||||
# Further documentation:
|
||||
# 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
|
||||
#screenW = 800
|
||||
#screenH = 600
|
||||
|
||||
# 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.
|
||||
# Network port (UDP)
|
||||
#port =
|
||||
# Name of player; on a server this is the main admin
|
||||
#name =
|
||||
|
||||
# Key configuration.
|
||||
#
|
||||
# Client stuff
|
||||
#
|
||||
|
||||
# Key mappings
|
||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||
#keymap_forward = KEY_KEY_W
|
||||
#keymap_backward = KEY_KEY_S
|
||||
|
@ -38,108 +41,99 @@
|
|||
#keymap_inventory = KEY_KEY_I
|
||||
#keymap_chat = KEY_KEY_T
|
||||
#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_print_debug_stacks = KEY_KEY_P
|
||||
|
||||
#invert_mouse = false
|
||||
|
||||
# The desired FPS
|
||||
#wanted_fps = 30
|
||||
|
||||
# If FPS would go higher than this, limit it by sleeping
|
||||
# (to not waste CPU power for no benefit)
|
||||
#fps_max = 60
|
||||
|
||||
# The allowed adjustment range for the automatic rendering range adjustment
|
||||
#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
|
||||
#enable_fog = true
|
||||
|
||||
# Enable/disable clouds
|
||||
#enable_clouds = true
|
||||
|
||||
# Experimental
|
||||
#enable_farmesh = false
|
||||
|
||||
# Enable a bit lower water surface; disable for speed
|
||||
#new_style_water = true
|
||||
|
||||
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
||||
#new_style_water = false
|
||||
# Enable nice leaves; disable for speed
|
||||
#new_style_leaves = true
|
||||
|
||||
# Enable smooth lighting with simple ambient occlusion;
|
||||
# disable for speed or for different looks.
|
||||
#smooth_lighting = true
|
||||
|
||||
# Whether to draw a frametime graph (for debugging frametime)
|
||||
#frametime_graph = false
|
||||
|
||||
# Enable combining mainly used textures to a bigger one for improved speed
|
||||
# disable if it causes graphics glitches.
|
||||
#enable_texture_atlas = true
|
||||
|
||||
# Path to texture directory. All textures are first searched from here.
|
||||
#texture_path =
|
||||
|
||||
# Video back-end.
|
||||
# Possible values: null, software, burningsvideo, direct3d8, direct3d9, opengl
|
||||
#video_driver = opengl
|
||||
|
||||
# Enable random user input, for testing
|
||||
#random_input = false
|
||||
|
||||
# Timeout for client to remove unused map data from memory
|
||||
#client_delete_unused_sectors_timeout = 1200
|
||||
# Unobstructed movement without physics, downwards key is keymap_special1
|
||||
#free_move = false
|
||||
# Continuous forward movement (for testing)
|
||||
#continuous_forward = false
|
||||
# Fast movement (keymap_special1)
|
||||
#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-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)
|
||||
#creative_mode = 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
|
||||
#give_initial_stuff = false
|
||||
|
||||
# Set to true to enable experimental features
|
||||
# (varies from version to version, see wiki)
|
||||
#enable_experimental = false
|
||||
|
||||
# Profiler data print interval. 0 = disable.
|
||||
#profiler_print_interval = 10
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
#enable_mapgen_debug_info = false
|
||||
|
||||
# Player and object positions are sent at intervals specified by this
|
||||
#objectdata_inverval = 0.2
|
||||
|
||||
#objectdata_interval = 0.2
|
||||
#active_object_range = 2
|
||||
|
||||
#max_simultaneous_block_sends_per_client = 1
|
||||
#max_simultaneous_block_sends_server_total = 4
|
||||
|
||||
#max_block_send_distance = 5
|
||||
#max_block_generate_distance = 4
|
||||
|
||||
# 20 min/day
|
||||
#max_simultaneous_block_sends_per_client = 2
|
||||
#max_simultaneous_block_sends_server_total = 8
|
||||
#max_block_send_distance = 8
|
||||
#max_block_generate_distance = 8
|
||||
#time_send_interval = 20
|
||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||
#time_speed = 72
|
||||
# 4 min/day
|
||||
#time_speed = 360
|
||||
# 1 min/day
|
||||
#time_speed = 1440
|
||||
|
||||
#time_send_interval = 5
|
||||
#server_unload_unused_sectors_timeout = 60
|
||||
#server_unload_unused_data_timeout = 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
|
||||
content_sao.cpp
|
||||
mapgen.cpp
|
||||
content_inventory.cpp
|
||||
content_nodemeta.cpp
|
||||
|
@ -102,6 +103,7 @@ set(common_SRCS
|
|||
# Client sources
|
||||
set(minetest_SRCS
|
||||
${common_SRCS}
|
||||
content_cao.cpp
|
||||
mapblock_mesh.cpp
|
||||
farmesh.cpp
|
||||
keycode.cpp
|
||||
|
|
|
@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
|
||||
#define ACTIVEOBJECT_TYPE_INVALID 0
|
||||
// Other types are defined in content_object.h
|
||||
|
||||
struct ActiveObjectMessage
|
||||
{
|
||||
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
|
||||
|
@ -36,12 +39,6 @@ struct ActiveObjectMessage
|
|||
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
|
||||
*/
|
||||
|
|
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 <sstream>
|
||||
#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()
|
||||
{
|
||||
|
@ -36,6 +135,15 @@ void * MeshUpdateThread::Thread()
|
|||
|
||||
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();
|
||||
if(q == NULL)
|
||||
{
|
||||
|
@ -91,7 +199,7 @@ Client::Client(
|
|||
m_access_denied(false)
|
||||
{
|
||||
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_avg_rtt_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
|
||||
|
@ -225,16 +337,16 @@ void Client::step(float dtime)
|
|||
true, &deleted_blocks);*/
|
||||
|
||||
// Delete whole sectors
|
||||
u32 num = m_env.getMap().unloadUnusedData
|
||||
m_env.getMap().unloadUnusedData
|
||||
(delete_unused_sectors_timeout,
|
||||
false, &deleted_blocks);
|
||||
&deleted_blocks);
|
||||
|
||||
if(num > 0)
|
||||
if(deleted_blocks.size() > 0)
|
||||
{
|
||||
/*dstream<<DTIME<<"Client: Deleted blocks of "<<num
|
||||
<<" unused sectors"<<std::endl;*/
|
||||
dstream<<DTIME<<"Client: Deleted "<<num
|
||||
<<" unused sectors"<<std::endl;
|
||||
/*dstream<<DTIME<<"Client: Deleted "<<num
|
||||
<<" unused sectors"<<std::endl;*/
|
||||
|
||||
/*
|
||||
Send info to server
|
||||
|
@ -284,8 +396,7 @@ void Client::step(float dtime)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool connected = connectedAndInitialized();
|
||||
#endif
|
||||
|
||||
if(connected == false)
|
||||
{
|
||||
|
@ -330,6 +441,67 @@ void Client::step(float dtime)
|
|||
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
|
||||
*/
|
||||
|
@ -346,23 +518,23 @@ void Client::step(float dtime)
|
|||
// Step environment
|
||||
m_env.step(dtime);
|
||||
|
||||
// Step active blocks
|
||||
/*
|
||||
Handle active blocks
|
||||
NOTE: These old objects are DEPRECATED. TODO: Remove
|
||||
*/
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
MapBlock *block = NULL;
|
||||
try
|
||||
{
|
||||
block = m_env.getMap().getBlockNoCreate(p);
|
||||
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
||||
if(block == NULL)
|
||||
continue;
|
||||
|
||||
// Step MapBlockObjects
|
||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get events
|
||||
|
@ -695,36 +867,24 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
MapSector *sector;
|
||||
MapBlock *block;
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
v2s16 p2d(p.X, p.Z);
|
||||
sector = m_env.getMap().emergeSector(p2d);
|
||||
|
||||
v2s16 sp = sector->getPos();
|
||||
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);
|
||||
assert(sector->getPos() == p2d);
|
||||
|
||||
//TimeTaker timer("MapBlock deSerialize");
|
||||
// 0ms
|
||||
|
||||
try{
|
||||
block = sector->getBlockNoCreate(p.Y);
|
||||
block = sector->getBlockNoCreateNoEx(p.Y);
|
||||
if(block)
|
||||
{
|
||||
/*
|
||||
Update an existing block
|
||||
*/
|
||||
//dstream<<"Updating"<<std::endl;
|
||||
block->deSerialize(istr, ser_version);
|
||||
//block->setChangedFlag();
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
else
|
||||
{
|
||||
/*
|
||||
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->deSerialize(istr, ser_version);
|
||||
sector->insertBlock(block);
|
||||
//block->setChangedFlag();
|
||||
|
||||
//DEBUG
|
||||
/*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,7,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
|
||||
/*
|
||||
|
@ -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.
|
||||
*/
|
||||
//std::cerr<<"Adding mesh update task for received block"<<std::endl;
|
||||
addUpdateMeshTaskWithEdge(p, true);
|
||||
}
|
||||
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)
|
||||
{
|
||||
dstream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl;
|
||||
#if 0
|
||||
/*
|
||||
[0] u16 command
|
||||
[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);
|
||||
}
|
||||
} //envlock
|
||||
#endif
|
||||
}
|
||||
else if(command == TOCLIENT_INVENTORY)
|
||||
{
|
||||
|
@ -1105,6 +1246,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
/*
|
||||
Read block objects
|
||||
NOTE: Deprecated stuff here, TODO: Remove
|
||||
*/
|
||||
|
||||
// Read active block count
|
||||
|
@ -1753,7 +1895,7 @@ void Client::addNode(v3s16 p, MapNode n)
|
|||
|
||||
try
|
||||
{
|
||||
TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
||||
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
@ -1981,12 +2123,6 @@ void Client::printDebugInfo(std::ostream &os)
|
|||
<<std::endl;*/
|
||||
}
|
||||
|
||||
/*s32 Client::getDayNightIndex()
|
||||
{
|
||||
assert(m_daynight_i >= 0 && m_daynight_i < DAYNIGHT_CACHE_COUNT);
|
||||
return m_daynight_i;
|
||||
}*/
|
||||
|
||||
u32 Client::getDayNightRatio()
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
@ -2000,6 +2136,40 @@ u16 Client::getHP()
|
|||
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)
|
||||
{
|
||||
/*dstream<<"Client::addUpdateMeshTask(): "
|
||||
|
@ -2018,7 +2188,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
|||
|
||||
{
|
||||
//TimeTaker timer("data fill");
|
||||
// 0ms
|
||||
// Release: ~0ms
|
||||
// Debug: 1-6ms, avg=2ms
|
||||
data->fill(getDayNightRatio(), b);
|
||||
}
|
||||
|
||||
|
@ -2044,6 +2215,10 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
|||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
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 <ostream>
|
||||
#include "clientobject.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
|
||||
struct MeshMakeData;
|
||||
|
||||
class ClientNotReadyException : public BaseException
|
||||
{
|
||||
|
@ -43,18 +46,8 @@ struct QueuedMeshUpdate
|
|||
MeshMakeData *data;
|
||||
bool ack_block_to_server;
|
||||
|
||||
QueuedMeshUpdate():
|
||||
p(-1337,-1337,-1337),
|
||||
data(NULL),
|
||||
ack_block_to_server(false)
|
||||
{
|
||||
}
|
||||
|
||||
~QueuedMeshUpdate()
|
||||
{
|
||||
if(data)
|
||||
delete data;
|
||||
}
|
||||
QueuedMeshUpdate();
|
||||
~QueuedMeshUpdate();
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -63,76 +56,18 @@ struct QueuedMeshUpdate
|
|||
class MeshUpdateQueue
|
||||
{
|
||||
public:
|
||||
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;
|
||||
}
|
||||
}
|
||||
~MeshUpdateQueue();
|
||||
|
||||
/*
|
||||
peer_id=0 adds with nobody to send to
|
||||
*/
|
||||
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);
|
||||
}
|
||||
void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server);
|
||||
|
||||
// Returned pointer must be deleted
|
||||
// Returns NULL if queue is empty
|
||||
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;
|
||||
}
|
||||
QueuedMeshUpdate * pop();
|
||||
|
||||
u32 size()
|
||||
{
|
||||
|
@ -309,40 +244,8 @@ public:
|
|||
|
||||
u16 getHP();
|
||||
|
||||
//void updateSomeExpiredMeshes();
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
void setTempMod(v3s16 p, NodeMod mod);
|
||||
void clearTempMod(v3s16 p);
|
||||
|
||||
float getAvgRtt()
|
||||
{
|
||||
|
@ -390,6 +293,15 @@ public:
|
|||
return m_access_denied_reason;
|
||||
}
|
||||
|
||||
/*
|
||||
This should only be used for calling the special drawing stuff in
|
||||
ClientEnvironment
|
||||
*/
|
||||
ClientEnvironment * getEnv()
|
||||
{
|
||||
return &m_env;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Virtual methods from con::PeerHandler
|
||||
|
@ -404,11 +316,11 @@ private:
|
|||
void sendPlayerInfo();
|
||||
|
||||
float m_packetcounter_timer;
|
||||
float m_delete_unused_sectors_timer;
|
||||
float m_connection_reinit_timer;
|
||||
float m_avg_rtt_timer;
|
||||
float m_playerpos_send_timer;
|
||||
float m_ignore_damage_timer; // Used after server moves player
|
||||
IntervalLimiter m_map_timer_and_unload_interval;
|
||||
|
||||
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 "porting.h"
|
||||
#include "constants.h"
|
||||
#include "utility.h"
|
||||
#include "environment.h"
|
||||
#include "tile.h"
|
||||
|
||||
/*
|
||||
ClientActiveObject
|
||||
|
@ -68,674 +65,4 @@ void ClientActiveObject::registerType(u16 type, Factory 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 "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 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
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ enum ToClientCommand
|
|||
[0] u16 TOSERVER_INIT
|
||||
[2] u8 deployed version
|
||||
[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
|
||||
explicitly sent afterwards
|
||||
|
|
|
@ -182,4 +182,58 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
|||
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,
|
||||
const core::aabbox3d<f32> &box_0,
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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 "inventory.h"
|
||||
#include "serverobject.h"
|
||||
#include "content_mapnode.h"
|
||||
//#include "serverobject.h"
|
||||
#include "content_sao.h"
|
||||
|
||||
bool item_material_is_cookable(u8 content)
|
||||
{
|
||||
|
|
|
@ -272,7 +272,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
/*
|
||||
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));
|
||||
video::SColor c(255,l,l,l);
|
||||
|
|
|
@ -224,7 +224,6 @@ void content_mapnode_init()
|
|||
// Deprecated
|
||||
i = CONTENT_COALSTONE;
|
||||
f = &content_features(i);
|
||||
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
||||
f->setAllTextures("stone.png^mineral_coal.png");
|
||||
f->is_ground_content = true;
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 1.5);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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_freemove", "KEY_KEY_K");
|
||||
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
|
||||
g_settings.setDefault("keymap_special1", "KEY_KEY_E");
|
||||
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("address", "");
|
||||
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("new_style_water", "false");
|
||||
g_settings.setDefault("new_style_leaves", "true");
|
||||
|
@ -72,6 +74,7 @@ void set_default_settings()
|
|||
g_settings.setDefault("farmesh_distance", "40");
|
||||
g_settings.setDefault("enable_clouds", "true");
|
||||
g_settings.setDefault("invisible_stone", "false");
|
||||
g_settings.setDefault("screenshot_path", ".");
|
||||
|
||||
// Server stuff
|
||||
g_settings.setDefault("enable_experimental", "false");
|
||||
|
@ -81,17 +84,19 @@ void set_default_settings()
|
|||
g_settings.setDefault("default_password", "");
|
||||
g_settings.setDefault("default_privs", "build, shout");
|
||||
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("active_object_range", "2");
|
||||
//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_server_total", "8");
|
||||
g_settings.setDefault("max_block_send_distance", "8");
|
||||
g_settings.setDefault("max_block_generate_distance", "8");
|
||||
g_settings.setDefault("time_send_interval", "20");
|
||||
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("full_block_send_enable_min_time_from_building", "2.0");
|
||||
//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 "collision.h"
|
||||
#include "content_mapnode.h"
|
||||
|
||||
#include "mapblock.h"
|
||||
#include "serverobject.h"
|
||||
#include "content_sao.h"
|
||||
|
||||
Environment::Environment():
|
||||
m_time_of_day(9000)
|
||||
|
@ -658,14 +660,6 @@ void ServerEnvironment::step(float dtime)
|
|||
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
|
||||
*/
|
||||
|
@ -868,6 +862,9 @@ void ServerEnvironment::step(float dtime)
|
|||
if(block==NULL)
|
||||
continue;
|
||||
|
||||
// Reset block usage timer
|
||||
block->resetUsageTimer();
|
||||
|
||||
// Set current time as timestamp
|
||||
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
|
||||
if(obj->m_removed || obj->m_pending_deactivation)
|
||||
continue;
|
||||
// Step object, putting messages directly to the queue
|
||||
obj->step(dtime, m_active_object_messages, send_recommended);
|
||||
// Step object
|
||||
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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1414,7 +1417,20 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
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)
|
||||
{
|
||||
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_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{
|
||||
dstream<<"WARNING: Server: Could not find a block for "
|
||||
<<"storing static object"<<std::endl;
|
||||
dstream<<"WARNING: ServerEnv: Could not find or generate "
|
||||
<<"a block for storing static object"<<std::endl;
|
||||
obj->m_static_exists = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -1526,11 +1534,6 @@ void ClientEnvironment::step(float dtime)
|
|||
bool free_move = g_settings.getBool("free_move");
|
||||
bool footprints = g_settings.getBool("footprints");
|
||||
|
||||
{
|
||||
//TimeTaker timer("Client m_map->timerUpdate()");
|
||||
m_map->timerUpdate(dtime);
|
||||
}
|
||||
|
||||
// Get local player
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
assert(lplayer);
|
||||
|
@ -1728,6 +1731,9 @@ void ClientEnvironment::step(float dtime)
|
|||
ClientActiveObject* obj = i.getNode()->getValue();
|
||||
// Step object
|
||||
obj->step(dtime, this);
|
||||
|
||||
if(m_active_object_light_update_interval.step(dtime, 0.21))
|
||||
{
|
||||
// Update lighting
|
||||
//u8 light = LIGHT_MAX;
|
||||
u8 light = 0;
|
||||
|
@ -1741,6 +1747,7 @@ void ClientEnvironment::step(float dtime)
|
|||
obj->updateLight(light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientEnvironment::updateMeshes(v3s16 blockpos)
|
||||
{
|
||||
|
@ -1926,6 +1933,22 @@ ClientEnvEvent ClientEnvironment::getClientEvent()
|
|||
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
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "map.h"
|
||||
#include <ostream>
|
||||
#include "utility.h"
|
||||
#include "activeobject.h"
|
||||
|
||||
class Server;
|
||||
class ActiveBlockModifier;
|
||||
class ServerActiveObject;
|
||||
|
||||
class Environment
|
||||
{
|
||||
|
@ -118,11 +123,6 @@ private:
|
|||
This is not thread-safe. Server uses an environment mutex.
|
||||
*/
|
||||
|
||||
#include "serverobject.h"
|
||||
|
||||
class Server;
|
||||
class ActiveBlockModifier;
|
||||
|
||||
class ServerEnvironment : public Environment
|
||||
{
|
||||
public:
|
||||
|
@ -407,11 +407,15 @@ public:
|
|||
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||
ClientEnvEvent getClientEvent();
|
||||
|
||||
// Post effects
|
||||
void drawPostFx(video::IVideoDriver* driver, v3f camera_pos);
|
||||
|
||||
private:
|
||||
ClientMap *m_map;
|
||||
scene::ISceneManager *m_smgr;
|
||||
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||
Queue<ClientEnvEvent> m_client_event_queue;
|
||||
IntervalLimiter m_active_object_light_update_interval;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -280,7 +280,8 @@ void FarMesh::render()
|
|||
if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS)
|
||||
{
|
||||
//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
|
||||
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 "keycode.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_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(
|
||||
bool &kill,
|
||||
bool random_input,
|
||||
|
@ -689,12 +721,17 @@ void the_game(
|
|||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
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 last_screensize(0,0);
|
||||
screensize = driver->getScreenSize();
|
||||
|
||||
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
|
||||
|
||||
|
@ -705,20 +742,10 @@ void the_game(
|
|||
/*
|
||||
Draw "Loading" screen
|
||||
*/
|
||||
const wchar_t *loadingtext = L"Loading and connecting...";
|
||||
u32 text_height = font->getDimension(loadingtext).Height;
|
||||
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();
|
||||
/*gui::IGUIStaticText *gui_loadingtext = */
|
||||
//draw_load_screen(L"Loading and connecting...", driver, font);
|
||||
|
||||
draw_load_screen(L"Loading...", driver, font);
|
||||
|
||||
/*
|
||||
Create server.
|
||||
|
@ -726,6 +753,7 @@ void the_game(
|
|||
*/
|
||||
SharedPtr<Server> server;
|
||||
if(address == ""){
|
||||
draw_load_screen(L"Creating server...", driver, font);
|
||||
std::cout<<DTIME<<"Creating server"<<std::endl;
|
||||
server = new Server(map_dir);
|
||||
server->start(port);
|
||||
|
@ -735,9 +763,11 @@ void the_game(
|
|||
Create client
|
||||
*/
|
||||
|
||||
draw_load_screen(L"Creating client...", driver, font);
|
||||
std::cout<<DTIME<<"Creating client"<<std::endl;
|
||||
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);
|
||||
try{
|
||||
if(address == "")
|
||||
|
@ -751,7 +781,7 @@ void the_game(
|
|||
std::cout<<DTIME<<"Couldn't resolve address"<<std::endl;
|
||||
//return 0;
|
||||
error_message = L"Couldn't resolve address";
|
||||
gui_loadingtext->remove();
|
||||
//gui_loadingtext->remove();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -785,10 +815,16 @@ void the_game(
|
|||
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));
|
||||
guienv->drawAll();
|
||||
driver->endScene();
|
||||
driver->endScene();*/
|
||||
|
||||
// Update client and server
|
||||
|
||||
|
@ -818,7 +854,7 @@ void the_game(
|
|||
error_message = L"Connection timed out.";
|
||||
std::cout<<DTIME<<"Timed out."<<std::endl;
|
||||
}
|
||||
gui_loadingtext->remove();
|
||||
//gui_loadingtext->remove();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -880,7 +916,7 @@ void the_game(
|
|||
Move into game
|
||||
*/
|
||||
|
||||
gui_loadingtext->remove();
|
||||
//gui_loadingtext->remove();
|
||||
|
||||
/*
|
||||
Add some gui stuff
|
||||
|
@ -973,6 +1009,8 @@ void the_game(
|
|||
|
||||
while(device->run() && kill == false)
|
||||
{
|
||||
//std::cerr<<"frame"<<std::endl;
|
||||
|
||||
if(g_gamecallback->disconnect_requested)
|
||||
{
|
||||
g_gamecallback->disconnect_requested = false;
|
||||
|
@ -999,6 +1037,14 @@ void the_game(
|
|||
v2s32 displaycenter(screensize.X/2,screensize.Y/2);
|
||||
//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
|
||||
core::list< core::aabbox3d<f32> > hilightboxes;
|
||||
|
||||
|
@ -1090,7 +1136,7 @@ void the_game(
|
|||
*/
|
||||
|
||||
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;
|
||||
|
||||
static f32 dtime_jitter1_max_sample = 0.0;
|
||||
|
@ -1254,6 +1300,38 @@ void the_game(
|
|||
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
|
||||
{
|
||||
|
@ -2195,6 +2273,13 @@ void the_game(
|
|||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
Environment post fx
|
||||
*/
|
||||
{
|
||||
client.getEnv()->drawPostFx(driver, camera_position);
|
||||
}
|
||||
|
||||
/*
|
||||
End scene
|
||||
*/
|
||||
|
@ -2237,15 +2322,12 @@ void the_game(
|
|||
generator and other stuff quits
|
||||
*/
|
||||
{
|
||||
const wchar_t *shuttingdowntext = L"Shutting down stuff...";
|
||||
gui::IGUIStaticText *gui_shuttingdowntext = guienv->addStaticText(
|
||||
shuttingdowntext, textrect, false, false);
|
||||
gui_shuttingdowntext->setTextAlignment(gui::EGUIA_CENTER,
|
||||
gui::EGUIA_UPPERLEFT);
|
||||
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||
/*gui::IGUIStaticText *gui_shuttingdowntext = */
|
||||
draw_load_screen(L"Shutting down stuff...", driver, font);
|
||||
/*driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||
guienv->drawAll();
|
||||
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 "content_mapnode.h"
|
||||
#include "content_inventory.h"
|
||||
#include "content_sao.h"
|
||||
|
||||
/*
|
||||
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
|
||||
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:
|
||||
-------------------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
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?
|
||||
http://www.earslap.com/projectslab/otomata
|
||||
|
||||
|
@ -90,6 +114,8 @@ SUGG: Make a system for pregenerating quick information for mapblocks, so
|
|||
or even generated.
|
||||
|
||||
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
|
||||
then turn stone into gravel and sand and relocate it.
|
||||
- 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
|
||||
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:
|
||||
-------------
|
||||
|
||||
|
@ -173,12 +209,13 @@ SUGG: Make fetching sector's blocks more efficient when rendering
|
|||
sectors that have very large amounts of blocks (on client)
|
||||
- Is this necessary at all?
|
||||
|
||||
TODO: Flowing water animation
|
||||
|
||||
SUGG: Draw cubes in inventory directly with 3D drawing commands, so that
|
||||
animating them is easier.
|
||||
|
||||
SUGG: Option for enabling proper alpha channel for textures
|
||||
|
||||
TODO: Flowing water animation
|
||||
|
||||
TODO: A setting for enabling bilinear filtering for textures
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
--------------
|
||||
|
||||
|
@ -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
|
||||
blocks? List the first saved block, maybe it explains.
|
||||
- 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
|
||||
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
|
||||
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:
|
||||
------------
|
||||
|
||||
TODO: 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
|
||||
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.
|
||||
TODO: Add proper hooks to when adding and removing active blocks
|
||||
|
||||
TODO: Finish the ActiveBlockModifier stuff and use it for something
|
||||
|
||||
Objects:
|
||||
--------
|
||||
|
@ -287,6 +299,7 @@ TODO: Get rid of MapBlockObjects and use only ActiveObjects
|
|||
|
||||
SUGG: MovingObject::move and Player::move are basically the same.
|
||||
combine them.
|
||||
- NOTE: This is a bit tricky because player has the sneaking ability
|
||||
- NOTE: Player::move is more up-to-date.
|
||||
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
||||
- 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
|
||||
- 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
|
||||
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.
|
||||
TODO: Consider smoothening cave floors after generating them
|
||||
|
||||
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
|
||||
- Block cube placement around player's head
|
||||
- Protocol version field
|
||||
- Consider getting some textures from cisoun's texture pack
|
||||
- Ask from Cisoun
|
||||
- Make sure the fence implementation and data format is good
|
||||
- Think about using same bits for material for fences and doors, for
|
||||
- NOTE: I think nobody does it currently...
|
||||
TODO: Block cube placement around player's head
|
||||
TODO: Protocol version field
|
||||
TODO: Think about using same bits for material for fences and doors, for
|
||||
example
|
||||
- Finish the ActiveBlockModifier stuff and use it for something
|
||||
- Move mineral to param2, increment map serialization version, add 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: Move mineral to param2, increment map serialization version, add
|
||||
conversion
|
||||
|
||||
TODO: Restart irrlicht completely when coming back to main menu from game.
|
||||
- This gets rid of everything that is stored in irrlicht's caches.
|
||||
|
||||
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)
|
||||
|
||||
Making it more portable:
|
||||
|
@ -375,9 +354,6 @@ Stuff to do after release:
|
|||
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 <fstream>
|
||||
//#include <jmutexautolock.h>
|
||||
#include <locale.h>
|
||||
#include "main.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
//#include "map.h"
|
||||
//#include "player.h"
|
||||
#include "test.h"
|
||||
#include "server.h"
|
||||
//#include "client.h"
|
||||
#include "constants.h"
|
||||
#include "porting.h"
|
||||
#include "gettime.h"
|
||||
|
@ -424,11 +396,10 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
|||
#include "config.h"
|
||||
#include "guiMainMenu.h"
|
||||
#include "mineral.h"
|
||||
//#include "noise.h"
|
||||
//#include "tile.h"
|
||||
#include "materials.h"
|
||||
#include "game.h"
|
||||
#include "keycode.h"
|
||||
#include "tile.h"
|
||||
|
||||
// This makes textures
|
||||
ITextureSource *g_texturesource = NULL;
|
||||
|
|
|
@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
extern Settings g_settings;
|
||||
|
||||
// This makes and maps textures
|
||||
#include "tile.h"
|
||||
class ITextureSource;
|
||||
extern ITextureSource *g_texturesource;
|
||||
|
||||
// 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 "mapsector.h"
|
||||
#include "mapblock.h"
|
||||
#include "main.h"
|
||||
#include "jmutexautolock.h"
|
||||
#include "client.h"
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "voxel.h"
|
||||
#include "porting.h"
|
||||
#include "mineral.h"
|
||||
#include "noise.h"
|
||||
#include "serverobject.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "mapgen.h"
|
||||
#include "nodemetadata.h"
|
||||
|
||||
extern "C" {
|
||||
#include "sqlite3.h"
|
||||
|
@ -122,42 +120,23 @@ MapSector * Map::getSectorNoGenerate(v2s16 p)
|
|||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
v2s16 p2d(p3d.X, p3d.Z);
|
||||
MapSector * sector = getSectorNoGenerate(p2d);
|
||||
MapBlock *block = sector->getBlockNoCreate(p3d.Y);
|
||||
return block;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
MapSector * sector = getSectorNoGenerateNoEx(p2d);
|
||||
if(sector == 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);
|
||||
MapSector * sector = getSectorCreate(p2d);
|
||||
assert(sector);
|
||||
MapBlock *block = sector->getBlockNoCreate(p3d.Y);
|
||||
if(block)
|
||||
MapBlock *block = getBlockNoCreateNoEx(p3d);
|
||||
if(block == NULL)
|
||||
throw InvalidPositionException();
|
||||
return block;
|
||||
block = sector->createBlankBlock(p3d.Y);
|
||||
return block;
|
||||
}*/
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
@ -1357,9 +1394,14 @@ bool Map::dayNightDiffed(v3s16 blockpos)
|
|||
/*
|
||||
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;
|
||||
|
||||
|
@ -1368,48 +1410,85 @@ void Map::timerUpdate(float dtime)
|
|||
{
|
||||
MapSector *sector = si.getNode()->getValue();
|
||||
|
||||
bool all_blocks_deleted = true;
|
||||
|
||||
core::list<MapBlock*> blocks;
|
||||
sector->getBlocks(blocks);
|
||||
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
||||
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;
|
||||
for(j=list.begin(); j!=list.end(); j++)
|
||||
{
|
||||
MapSector *sector = m_sectors[*j];
|
||||
if(only_blocks)
|
||||
{
|
||||
sector->deleteBlocks();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
If sector is in sector cache, remove it from there
|
||||
*/
|
||||
// If sector is in sector cache, remove it from there
|
||||
if(m_sector_cache == sector)
|
||||
{
|
||||
m_sector_cache = NULL;
|
||||
}
|
||||
/*
|
||||
Remove from map and delete
|
||||
*/
|
||||
// Remove from map and delete
|
||||
m_sectors.remove(*j);
|
||||
delete sector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
||||
#if 0
|
||||
void Map::unloadUnusedData(float timeout,
|
||||
core::list<v3s16> *deleted_blocks)
|
||||
{
|
||||
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();
|
||||
for(; si.atEnd() == false; si++)
|
||||
|
@ -1429,10 +1508,13 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
|||
{
|
||||
// Save if modified
|
||||
if(block->getModified() != MOD_STATE_CLEAN)
|
||||
{
|
||||
saveBlock(block);
|
||||
// Unload
|
||||
sector->removeBlock(block);
|
||||
delete block;
|
||||
saved_blocks_count++;
|
||||
}
|
||||
// Delete from memory
|
||||
sector->deleteBlock(block);
|
||||
deleted_blocks_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1446,38 +1528,17 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks,
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
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());
|
||||
deleteSectors(sector_deletion_queue);
|
||||
|
||||
if(deleted_blocks != NULL)
|
||||
{
|
||||
// Collect positions of blocks of sector
|
||||
MapSector *sector = i.getNode()->getValue();
|
||||
core::list<MapBlock*> blocks;
|
||||
sector->getBlocks(blocks);
|
||||
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
||||
i != blocks.end(); i++)
|
||||
{
|
||||
deleted_blocks->push_back((*i)->getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
dstream<<"Map: Unloaded "<<deleted_blocks_count<<" blocks from memory"
|
||||
<<", of which "<<saved_blocks_count<<" were wr."
|
||||
<<std::endl;
|
||||
|
||||
//return sector_deletion_queue.getSize();
|
||||
//return deleted_blocks_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
deleteSectors(sector_deletion_queue, only_blocks);
|
||||
return sector_deletion_queue.getSize();
|
||||
}
|
||||
|
||||
void Map::PrintInfo(std::ostream &out)
|
||||
{
|
||||
out<<"Map: ";
|
||||
|
@ -1503,7 +1564,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||
*/
|
||||
v3s16 p0 = m_transforming_liquid.pop_front();
|
||||
|
||||
MapNode n0 = getNode(p0);
|
||||
MapNode n0 = getNodeNoEx(p0);
|
||||
|
||||
// Don't deal with non-liquids
|
||||
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++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
bool from_top = (i==0);
|
||||
|
||||
v3s16 p2 = p0 + dirs_from[i];
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
|
||||
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)
|
||||
new_liquid_level_max = new_liquid_level;
|
||||
}
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
} //for
|
||||
|
||||
/*
|
||||
|
@ -1645,20 +1699,13 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||
};
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
v3s16 p2 = p0 + dirs[i];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
if(content_flowing_liquid(n2.d))
|
||||
{
|
||||
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++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
bool to_bottom = (i == 0);
|
||||
|
||||
// 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];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
|
||||
|
||||
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(to_bottom && flowed && !is_source)
|
||||
break;
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
loopcount++;
|
||||
|
@ -1972,7 +2012,6 @@ ServerMap::~ServerMap()
|
|||
{
|
||||
if(m_map_saving_enabled)
|
||||
{
|
||||
//save(false);
|
||||
// Save only changed parts
|
||||
save(true);
|
||||
dstream<<DTIME<<"Server: saved map to "<<m_savedir<<std::endl;
|
||||
|
@ -2079,6 +2118,8 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||
|
||||
/*dstream<<"Resulting vmanip:"<<std::endl;
|
||||
data->vmanip.print(dstream);*/
|
||||
|
||||
|
@ -2091,10 +2132,11 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
//TimeTaker timer("finishBlockMake() blitBackAll");
|
||||
data->vmanip->blitBackAll(&changed_blocks);
|
||||
}
|
||||
#if 1
|
||||
|
||||
if(enable_mapgen_debug_info)
|
||||
dstream<<"finishBlockMake: changed_blocks.size()="
|
||||
<<changed_blocks.size()<<std::endl;
|
||||
#endif
|
||||
|
||||
/*
|
||||
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
|
||||
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
|
||||
NOTE: This takes ~60ms, TODO: Investigate why
|
||||
*/
|
||||
{
|
||||
TimeTaker t("finishBlockMake lighting update");
|
||||
|
||||
core::map<v3s16, MapBlock*> lighting_update_blocks;
|
||||
// Center block
|
||||
|
@ -2150,6 +2198,10 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
#endif
|
||||
updateLighting(lighting_update_blocks, changed_blocks);
|
||||
|
||||
if(enable_mapgen_debug_info == false)
|
||||
t.stop(true); // Hide output
|
||||
}
|
||||
|
||||
/*
|
||||
Add random objects to block
|
||||
*/
|
||||
|
@ -2262,6 +2314,8 @@ MapBlock * ServerMap::generateBlock(
|
|||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||
|
||||
TimeTaker timer("generateBlock");
|
||||
|
||||
//MapBlock *block = original_dummy;
|
||||
|
@ -2290,6 +2344,9 @@ MapBlock * ServerMap::generateBlock(
|
|||
{
|
||||
TimeTaker t("mapgen::make_block()");
|
||||
mapgen::make_block(&data);
|
||||
|
||||
if(enable_mapgen_debug_info == false)
|
||||
t.stop(true); // Hide output
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2348,6 +2405,9 @@ MapBlock * ServerMap::generateBlock(
|
|||
}
|
||||
#endif
|
||||
|
||||
if(enable_mapgen_debug_info == false)
|
||||
timer.stop(true); // Hide output
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -2414,23 +2474,51 @@ MapBlock * ServerMap::createBlock(v3s16 p)
|
|||
return block;
|
||||
}
|
||||
|
||||
#if 0
|
||||
MapBlock * ServerMap::emergeBlock(
|
||||
v3s16 p,
|
||||
bool only_from_disk,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||
)
|
||||
MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
||||
{
|
||||
DSTACKF("%s: p=(%d,%d,%d), only_from_disk=%d",
|
||||
DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
|
||||
__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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
|
@ -2877,10 +2965,10 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
|
|||
// format. Just go ahead and create the sector.
|
||||
if(fs::PathExists(sectordir))
|
||||
{
|
||||
dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
||||
/*dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
||||
<<fullpath<<" doesn't exist but directory does."
|
||||
<<" Continuing with a sector with no metadata."
|
||||
<<std::endl;
|
||||
<<std::endl;*/
|
||||
sector = new ServerMapSector(this, p2d);
|
||||
m_sectors.insert(p2d, sector);
|
||||
}
|
||||
|
@ -3094,10 +3182,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
|||
|
||||
MapBlock *block = NULL;
|
||||
bool created_new = false;
|
||||
try{
|
||||
block = sector->getBlockNoCreate(p3d.Y);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
block = sector->getBlockNoCreateNoEx(p3d.Y);
|
||||
if(block == NULL)
|
||||
{
|
||||
block = sector->createBlankBlockNoInsert(p3d.Y);
|
||||
created_new = true;
|
||||
|
@ -3267,6 +3353,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d)
|
|||
return sector;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
@ -3292,6 +3379,7 @@ void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
|||
|
||||
sector->deSerialize(is);
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
v3s16 p_blocks_min(
|
||||
p_nodes_min.X / MAP_BLOCKSIZE - 1,
|
||||
p_nodes_min.Y / MAP_BLOCKSIZE - 1,
|
||||
p_nodes_min.Z / MAP_BLOCKSIZE - 1);
|
||||
p_nodes_min.X / MAP_BLOCKSIZE - 2,
|
||||
p_nodes_min.Y / MAP_BLOCKSIZE - 2,
|
||||
p_nodes_min.Z / MAP_BLOCKSIZE - 2);
|
||||
v3s16 p_blocks_max(
|
||||
p_nodes_max.X / MAP_BLOCKSIZE,
|
||||
p_nodes_max.Y / MAP_BLOCKSIZE,
|
||||
p_nodes_max.Z / MAP_BLOCKSIZE);
|
||||
p_nodes_max.X / MAP_BLOCKSIZE + 1,
|
||||
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
||||
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
||||
|
||||
u32 vertex_count = 0;
|
||||
|
||||
|
@ -3429,6 +3517,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||
continue;
|
||||
}
|
||||
|
||||
// Okay, this block will be drawn. Reset usage timer.
|
||||
block->resetUsageTimer();
|
||||
|
||||
// This is ugly (spherical distance limit?)
|
||||
/*if(m_control.range_all == false &&
|
||||
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
|
||||
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <jthread.h>
|
||||
#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 "mapnode.h"
|
||||
#include "mapblock.h"
|
||||
#include "mapsector.h"
|
||||
#include "mapblock_nodemod.h"
|
||||
#include "constants.h"
|
||||
#include "voxel.h"
|
||||
#include "mapchunk.h"
|
||||
#include "nodemetadata.h"
|
||||
|
||||
class MapSector;
|
||||
class ServerMapSector;
|
||||
class ClientMapSector;
|
||||
class MapBlock;
|
||||
class NodeMetadata;
|
||||
|
||||
namespace mapgen{
|
||||
struct BlockMakeData;
|
||||
|
@ -61,7 +57,7 @@ enum MapEditEventType{
|
|||
// Node metadata of block changed (not knowing which node exactly)
|
||||
// p stores block coordinate
|
||||
MEET_BLOCK_NODE_METADATA_CHANGED,
|
||||
// Anything else
|
||||
// Anything else (modified_blocks are set unsent)
|
||||
MEET_OTHER
|
||||
};
|
||||
|
||||
|
@ -104,17 +100,17 @@ public:
|
|||
virtual void onMapEditEvent(MapEditEvent *event) = 0;
|
||||
};
|
||||
|
||||
class Map : public NodeContainer
|
||||
class Map /*: public NodeContainer*/
|
||||
{
|
||||
public:
|
||||
|
||||
Map(std::ostream &dout);
|
||||
virtual ~Map();
|
||||
|
||||
virtual u16 nodeContainerId() const
|
||||
/*virtual u16 nodeContainerId() const
|
||||
{
|
||||
return NODECONTAINER_ID_MAP;
|
||||
}
|
||||
}*/
|
||||
|
||||
virtual s32 mapType() const
|
||||
{
|
||||
|
@ -155,66 +151,20 @@ public:
|
|||
MapBlock * getBlockNoCreate(v3s16 p);
|
||||
// Returns NULL if not found
|
||||
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
||||
// Gets an existing block or creates an empty one
|
||||
//MapBlock * getBlockCreate(v3s16 p);
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
bool isNodeUnderground(v3s16 p);
|
||||
|
||||
// virtual from NodeContainer
|
||||
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;*/
|
||||
}
|
||||
bool isValidPosition(v3s16 p);
|
||||
|
||||
// virtual from NodeContainer
|
||||
// throws InvalidPositionException if not found
|
||||
MapNode getNode(v3s16 p)
|
||||
{
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
MapBlock * blockref = getBlockNoCreate(blockpos);
|
||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||
MapNode getNode(v3s16 p);
|
||||
|
||||
return blockref->getNodeNoCheck(relpos);
|
||||
}
|
||||
|
||||
// virtual from NodeContainer
|
||||
// throws InvalidPositionException if not found
|
||||
void setNode(v3s16 p, MapNode & n)
|
||||
{
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
MapBlock * blockref = getBlockNoCreate(blockpos);
|
||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||
blockref->setNodeNoCheck(relpos, n);
|
||||
}
|
||||
void setNode(v3s16 p, MapNode & n);
|
||||
|
||||
// Returns a CONTENT_IGNORE node if not found
|
||||
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);
|
||||
}
|
||||
}
|
||||
MapNode getNodeNoEx(v3s16 p);
|
||||
|
||||
void unspreadLight(enum LightBank bank,
|
||||
core::map<v3s16, u8> & from_nodes,
|
||||
|
@ -273,23 +223,33 @@ public:
|
|||
|
||||
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){};
|
||||
|
||||
/*
|
||||
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
|
||||
// sector mutex should be locked when calling
|
||||
void deleteSectors(core::list<v2s16> &list, bool only_blocks);
|
||||
// If deleted sector is in sector cache, clears cache
|
||||
void deleteSectors(core::list<v2s16> &list);
|
||||
|
||||
// Returns count of deleted sectors
|
||||
u32 unloadUnusedData(float timeout, bool only_blocks=false,
|
||||
#if 0
|
||||
/*
|
||||
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);
|
||||
#endif
|
||||
|
||||
// For debug printing
|
||||
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||
virtual void PrintInfo(std::ostream &out);
|
||||
|
||||
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
@ -321,7 +281,6 @@ protected:
|
|||
core::map<MapEventReceiver*, bool> m_event_receivers;
|
||||
|
||||
core::map<v2s16, MapSector*> m_sectors;
|
||||
//JMutex m_sector_mutex;
|
||||
|
||||
// Be sure to set this to NULL when the cached sector is deleted
|
||||
MapSector *m_sector_cache;
|
||||
|
@ -379,24 +338,13 @@ public:
|
|||
*/
|
||||
MapBlock * createBlock(v3s16 p);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
NOTE: This comment might be outdated
|
||||
|
||||
Forcefully get a block from somewhere.
|
||||
|
||||
InvalidPositionException possible if only_from_disk==true
|
||||
|
||||
Parameters:
|
||||
changed_blocks: Blocks that have been modified
|
||||
- Memory
|
||||
- Load from disk
|
||||
- Generate
|
||||
*/
|
||||
MapBlock * emergeBlock(
|
||||
v3s16 p,
|
||||
bool only_from_disk,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||
);
|
||||
#endif
|
||||
MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
|
||||
|
||||
// Helper for placing objects on ground level
|
||||
s16 findGroundLevel(v2s16 p2d);
|
||||
|
@ -547,7 +495,7 @@ public:
|
|||
*/
|
||||
MapSector * emergeSector(v2s16 p);
|
||||
|
||||
void deSerializeSector(v2s16 p2d, std::istream &is);
|
||||
//void deSerializeSector(v2s16 p2d, std::istream &is);
|
||||
|
||||
/*
|
||||
ISceneNode methods
|
||||
|
|
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
MapBlock
|
||||
*/
|
||||
|
||||
MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
||||
MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
||||
m_parent(parent),
|
||||
m_pos(pos),
|
||||
m_modified(MOD_STATE_WRITE_NEEDED),
|
||||
|
@ -38,7 +38,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
|||
m_generated(false),
|
||||
m_objects(this),
|
||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||
m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED)
|
||||
m_usage_timer(0)
|
||||
{
|
||||
data = NULL;
|
||||
if(dummy == false)
|
||||
|
@ -607,24 +607,20 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
|||
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);
|
||||
|
||||
// Get contents
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
databuf[i] = data[i].d;
|
||||
}
|
||||
|
||||
// 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;
|
||||
databuf[i] = databuf_nodelist[i*3];
|
||||
databuf[i+nodecount] = databuf_nodelist[i*3+1];
|
||||
databuf[i+nodecount*2] = databuf_nodelist[i*3+2];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -773,20 +769,14 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||
("MapBlock::deSerialize: decompress resulted in size"
|
||||
" other than nodecount*3");
|
||||
|
||||
// Set contents
|
||||
// deserialize nodes from buffer
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
data[i].d = s[i];
|
||||
}
|
||||
// Set params
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
data[i].param = s[i+nodecount];
|
||||
}
|
||||
// Set param2
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
data[i].param2 = s[i+nodecount*2];
|
||||
u8 buf[3];
|
||||
buf[0] = s[i];
|
||||
buf[1] = s[i+nodecount];
|
||||
buf[2] = s[i+nodecount*2];
|
||||
data[i].deSerialize(buf, version);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
|
|
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapblock_mesh.h"
|
||||
#endif
|
||||
|
||||
class Map;
|
||||
|
||||
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
|
||||
|
||||
|
@ -81,6 +82,7 @@ enum ModifiedState
|
|||
BLOCKGEN_FULLY_GENERATED=6
|
||||
};*/
|
||||
|
||||
#if 0
|
||||
enum
|
||||
{
|
||||
NODECONTAINER_ID_MAPBLOCK,
|
||||
|
@ -108,23 +110,24 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
MapBlock itself
|
||||
*/
|
||||
|
||||
class MapBlock : public NodeContainer
|
||||
class MapBlock /*: public NodeContainer*/
|
||||
{
|
||||
public:
|
||||
MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
|
||||
MapBlock(Map *parent, v3s16 pos, bool dummy=false);
|
||||
~MapBlock();
|
||||
|
||||
virtual u16 nodeContainerId() const
|
||||
/*virtual u16 nodeContainerId() const
|
||||
{
|
||||
return NODECONTAINER_ID_MAPBLOCK;
|
||||
}
|
||||
}*/
|
||||
|
||||
NodeContainer * getParent()
|
||||
Map * getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
@ -640,7 +643,7 @@ private:
|
|||
*/
|
||||
|
||||
// NOTE: Lots of things rely on this being the Map
|
||||
NodeContainer *m_parent;
|
||||
Map *m_parent;
|
||||
// Position in blocks on parent
|
||||
v3s16 m_pos;
|
||||
|
||||
|
|
|
@ -64,11 +64,7 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
|||
*/
|
||||
|
||||
// Get map
|
||||
NodeContainer *parentcontainer = 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;
|
||||
Map *map = block->getParent();
|
||||
|
||||
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 "inventory.h"
|
||||
#include "utility.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
/*
|
||||
MapBlockObject
|
||||
|
@ -856,16 +857,7 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
|||
assert(m_objects.find(object->m_id) != NULL);
|
||||
assert(m_objects[object->m_id] == object);
|
||||
|
||||
NodeContainer *parentcontainer = 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;
|
||||
Map *map = m_block->getParent();
|
||||
|
||||
// Calculate blockpos on map
|
||||
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
|
||||
#define MAPCHUNK_HEADER
|
||||
|
||||
/*
|
||||
TODO: Remove
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
MapChunk contains map-generation-time metadata for an area of
|
||||
some MapSectors. (something like 16x16)
|
||||
|
@ -66,6 +71,7 @@ private:
|
|||
u8 m_generation_level;
|
||||
bool m_modified;
|
||||
};
|
||||
#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 "mapblock.h"
|
||||
#include "map.h"
|
||||
#include "serverobject.h"
|
||||
#include "mineral.h"
|
||||
//#include "serverobject.h"
|
||||
#include "content_sao.h"
|
||||
|
||||
namespace mapgen
|
||||
{
|
||||
|
@ -531,7 +532,7 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
|
|||
else
|
||||
length = random.range(1,6);
|
||||
length = random.range(1,13);
|
||||
u32 partlength = random.range(1,length);
|
||||
u32 partlength = random.range(1,13);
|
||||
u32 partcount = 0;
|
||||
s16 make_stairs = 0;
|
||||
if(random.next()%2 == 0 && partlength >= 3)
|
||||
|
@ -700,14 +701,30 @@ public:
|
|||
continue;
|
||||
v3s16 roomplace;
|
||||
// X east, Z north, Y up
|
||||
#if 1
|
||||
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-
|
||||
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+
|
||||
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-
|
||||
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
|
||||
bool fits = true;
|
||||
|
@ -818,7 +835,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
|
|||
|
||||
// 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;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
|
||||
200, CAVE_NOISE_SCALE);*/
|
||||
return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
|
||||
100, CAVE_NOISE_SCALE);
|
||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
|
||||
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)
|
||||
{
|
||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
|
||||
200, CAVE_NOISE_SCALE);*/
|
||||
return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
|
||||
100, CAVE_NOISE_SCALE);
|
||||
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
double f = 0.8 + noise2d_perlin(
|
||||
double f = 0.55 + noise2d_perlin(
|
||||
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
||||
seed+920381, 3, 0.45);
|
||||
if(f < 0.01)
|
||||
f = 0.01;
|
||||
else if(f >= 1.0)
|
||||
f *= 2.0;
|
||||
f *= 1.6;
|
||||
double h = WATER_LEVEL + 10 * noise2d_perlin(
|
||||
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
|
||||
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_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
||||
double a = -31000;
|
||||
// Corners
|
||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||
v2s16(node_min.X, node_min.Y), p));
|
||||
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));
|
||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||
v2s16(node_min.X, node_min.Y), p));
|
||||
// Center
|
||||
a = MYMAX(a, find_ground_level_from_noise(seed,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1102,6 +1147,7 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
|
|||
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
|
||||
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
|
||||
double a = 31000;
|
||||
// Corners
|
||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||
v2s16(node_min.X, node_min.Y), p));
|
||||
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));
|
||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||
v2s16(node_min.X, node_min.Y), p));
|
||||
// Center
|
||||
a = MYMIN(a, find_ground_level_from_noise(seed,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1358,12 +1414,12 @@ void make_block(BlockMakeData *data)
|
|||
If block is deep underground, this is set to true and ground
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -1385,13 +1441,13 @@ void make_block(BlockMakeData *data)
|
|||
/*
|
||||
Cave noise
|
||||
*/
|
||||
|
||||
#if 1
|
||||
noisebuf_cave.create(get_cave_noise1_params(data->seed),
|
||||
minpos_f.X, minpos_f.Y, minpos_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));
|
||||
#endif
|
||||
|
||||
/*
|
||||
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()
|
||||
{
|
||||
if(translate_to)
|
||||
delete translate_to;
|
||||
/*if(translate_to)
|
||||
delete translate_to;*/
|
||||
if(initial_metadata)
|
||||
delete initial_metadata;
|
||||
}
|
||||
|
@ -138,6 +138,17 @@ void init_mapnode()
|
|||
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
|
||||
*/
|
||||
|
@ -230,6 +241,94 @@ u8 MapNode::getMineral()
|
|||
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
|
||||
|
||||
|
|
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
|
||||
*/
|
||||
|
||||
/*
|
||||
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.
|
||||
Many things depend on this.
|
||||
|
@ -59,14 +66,16 @@ void init_mapnode();
|
|||
Doesn't create faces with anything and is considered being
|
||||
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
|
||||
|
||||
/*
|
||||
The common material through which the player can walk and which
|
||||
is transparent to light
|
||||
*/
|
||||
#define CONTENT_AIR 254
|
||||
//#define CONTENT_AIR 254
|
||||
#define CONTENT_AIR 126
|
||||
|
||||
/*
|
||||
Content feature list
|
||||
|
@ -94,7 +103,7 @@ class NodeMetadata;
|
|||
struct ContentFeatures
|
||||
{
|
||||
// If non-NULL, content is translated to this when deserialized
|
||||
MapNode *translate_to;
|
||||
//MapNode *translate_to;
|
||||
|
||||
// Type of MapNode::param
|
||||
ContentParamType param_type;
|
||||
|
@ -156,7 +165,7 @@ struct ContentFeatures
|
|||
|
||||
void reset()
|
||||
{
|
||||
translate_to = NULL;
|
||||
//translate_to = NULL;
|
||||
param_type = CPT_NONE;
|
||||
inventory_texture = NULL;
|
||||
is_ground_content = false;
|
||||
|
@ -196,6 +205,8 @@ struct ContentFeatures
|
|||
{
|
||||
setTexture(i, name, alpha);
|
||||
}
|
||||
// Force inventory texture too
|
||||
setInventoryTexture(name);
|
||||
}
|
||||
|
||||
void setTile(u16 i, const TileSpec &tile)
|
||||
|
@ -399,8 +410,16 @@ enum LightBank
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
Misc parameter. Initialized to 0.
|
||||
|
@ -408,11 +427,13 @@ struct MapNode
|
|||
stored logarithmically from 0 to LIGHT_MAX.
|
||||
Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
|
||||
- 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
|
||||
{
|
||||
s8 param;
|
||||
u8 param1;
|
||||
s8 param;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -437,14 +458,6 @@ struct MapNode
|
|||
param2 = a_param2;
|
||||
}
|
||||
|
||||
/*MapNode & operator=(const MapNode &other)
|
||||
{
|
||||
d = other.d;
|
||||
param = other.param;
|
||||
param2 = other.param2;
|
||||
return *this;
|
||||
}*/
|
||||
|
||||
bool operator==(const MapNode &other)
|
||||
{
|
||||
return (d == other.d
|
||||
|
@ -452,6 +465,16 @@ struct MapNode
|
|||
&& 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
|
||||
*/
|
||||
|
@ -568,86 +591,13 @@ struct MapNode
|
|||
u8 getMineral();
|
||||
|
||||
/*
|
||||
These serialization functions are used when informing client
|
||||
of a single node add.
|
||||
|
||||
NOTE: When loading a MapBlock, these are not used. Should they?
|
||||
Serialization functions
|
||||
*/
|
||||
|
||||
static u32 serializedLength(u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
static u32 serializedLength(u8 version);
|
||||
void serialize(u8 *dest, u8 version);
|
||||
void deSerialize(u8 *source, u8 version);
|
||||
|
||||
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 "client.h"
|
||||
#include "exceptions.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
MapSector::MapSector(NodeContainer *parent, v2s16 pos):
|
||||
differs_from_disk(true),
|
||||
MapSector::MapSector(Map *parent, v2s16 pos):
|
||||
differs_from_disk(false),
|
||||
m_parent(parent),
|
||||
m_pos(pos),
|
||||
m_block_cache(NULL)
|
||||
{
|
||||
m_mutex.Init();
|
||||
assert(m_mutex.IsInitialized());
|
||||
}
|
||||
|
||||
MapSector::~MapSector()
|
||||
|
@ -39,8 +38,6 @@ MapSector::~MapSector()
|
|||
|
||||
void MapSector::deleteBlocks()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Clear cache
|
||||
m_block_cache = NULL;
|
||||
|
||||
|
@ -83,26 +80,12 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
|
|||
|
||||
MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return getBlockBuffered(y);
|
||||
}
|
||||
|
||||
MapBlock * MapSector::getBlockNoCreate(s16 y)
|
||||
{
|
||||
MapBlock *block = getBlockNoCreateNoEx(y);
|
||||
|
||||
if(block == NULL)
|
||||
throw InvalidPositionException();
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
|
||||
{
|
||||
// There should not be a block at this position
|
||||
if(getBlockBuffered(y) != NULL)
|
||||
throw AlreadyExistsException("Block already exists");
|
||||
assert(getBlockBuffered(y) == NULL);
|
||||
|
||||
v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
|
||||
|
||||
|
@ -113,8 +96,6 @@ MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
|
|||
|
||||
MapBlock * MapSector::createBlankBlock(s16 y)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
MapBlock *block = createBlankBlockNoInsert(y);
|
||||
|
||||
m_blocks.insert(y, block);
|
||||
|
@ -126,9 +107,6 @@ void MapSector::insertBlock(MapBlock *block)
|
|||
{
|
||||
s16 block_y = block->getPos().Y;
|
||||
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
MapBlock *block2 = getBlockBuffered(block_y);
|
||||
if(block2 != NULL){
|
||||
throw AlreadyExistsException("Block already exists");
|
||||
|
@ -140,25 +118,23 @@ void MapSector::insertBlock(MapBlock *block)
|
|||
// Insert into container
|
||||
m_blocks.insert(block_y, block);
|
||||
}
|
||||
}
|
||||
|
||||
void MapSector::removeBlock(MapBlock *block)
|
||||
void MapSector::deleteBlock(MapBlock *block)
|
||||
{
|
||||
s16 block_y = block->getPos().Y;
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Clear from cache
|
||||
m_block_cache = NULL;
|
||||
|
||||
// Remove from container
|
||||
m_blocks.remove(block_y);
|
||||
|
||||
// Delete
|
||||
delete block;
|
||||
}
|
||||
|
||||
void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::list<MapBlock*> ref_list;
|
||||
|
||||
core::map<s16, MapBlock*>::Iterator bi;
|
||||
|
@ -175,7 +151,7 @@ void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
|||
ServerMapSector
|
||||
*/
|
||||
|
||||
ServerMapSector::ServerMapSector(NodeContainer *parent, v2s16 pos):
|
||||
ServerMapSector::ServerMapSector(Map *parent, v2s16 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)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
|
@ -217,7 +184,7 @@ void ServerMapSector::serialize(std::ostream &os, u8 version)
|
|||
|
||||
ServerMapSector* ServerMapSector::deSerialize(
|
||||
std::istream &is,
|
||||
NodeContainer *parent,
|
||||
Map *parent,
|
||||
v2s16 p2d,
|
||||
core::map<v2s16, MapSector*> & sectors
|
||||
)
|
||||
|
@ -280,7 +247,7 @@ ServerMapSector* ServerMapSector::deSerialize(
|
|||
ClientMapSector
|
||||
*/
|
||||
|
||||
ClientMapSector::ClientMapSector(NodeContainer *parent, v2s16 pos):
|
||||
ClientMapSector::ClientMapSector(Map *parent, v2s16 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
|
||||
|
||||
//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 "common_irrlicht.h"
|
||||
#include "mapblock.h"
|
||||
//#include "heightmap.h"
|
||||
#include "exceptions.h"
|
||||
#include <ostream>
|
||||
|
||||
class MapBlock;
|
||||
class Map;
|
||||
|
||||
/*
|
||||
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_CLIENT 1
|
||||
|
||||
class MapSector: public NodeContainer
|
||||
class MapSector
|
||||
{
|
||||
public:
|
||||
|
||||
MapSector(NodeContainer *parent, v2s16 pos);
|
||||
MapSector(Map *parent, v2s16 pos);
|
||||
virtual ~MapSector();
|
||||
|
||||
virtual u16 nodeContainerId() const
|
||||
{
|
||||
return NODECONTAINER_ID_MAPSECTOR;
|
||||
}
|
||||
|
||||
virtual u32 getId() const = 0;
|
||||
|
||||
void deleteBlocks();
|
||||
|
@ -59,167 +56,32 @@ public:
|
|||
}
|
||||
|
||||
MapBlock * getBlockNoCreateNoEx(s16 y);
|
||||
MapBlock * getBlockNoCreate(s16 y);
|
||||
MapBlock * createBlankBlockNoInsert(s16 y);
|
||||
MapBlock * createBlankBlock(s16 y);
|
||||
//MapBlock * getBlock(s16 y, bool generate=true);
|
||||
|
||||
void insertBlock(MapBlock *block);
|
||||
|
||||
// This is used to remove a dummy from the sector while generating it.
|
||||
// Block is only removed from internal container, not deleted.
|
||||
void removeBlock(MapBlock *block);
|
||||
void deleteBlock(MapBlock *block);
|
||||
|
||||
/*
|
||||
This might not be a thread-safe depending on the day.
|
||||
See the implementation.
|
||||
*/
|
||||
void getBlocks(core::list<MapBlock*> &dest);
|
||||
|
||||
/*
|
||||
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
|
||||
// Always false at the moment, because sector contains no metadata.
|
||||
bool differs_from_disk;
|
||||
|
||||
protected:
|
||||
|
||||
// The pile of MapBlocks
|
||||
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)
|
||||
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
|
||||
MapBlock *m_block_cache;
|
||||
s16 m_block_cache_y;
|
||||
|
||||
// This is used for protecting m_blocks
|
||||
JMutex m_mutex;
|
||||
|
||||
/*
|
||||
Private methods
|
||||
*/
|
||||
|
@ -230,7 +92,7 @@ protected:
|
|||
class ServerMapSector : public MapSector
|
||||
{
|
||||
public:
|
||||
ServerMapSector(NodeContainer *parent, v2s16 pos);
|
||||
ServerMapSector(Map *parent, v2s16 pos);
|
||||
~ServerMapSector();
|
||||
|
||||
u32 getId() const
|
||||
|
@ -238,19 +100,16 @@ public:
|
|||
return MAPSECTOR_SERVER;
|
||||
}
|
||||
|
||||
// DEPRECATED?
|
||||
f32 getGroundHeight(v2s16 p, bool generate=false);
|
||||
void setGroundHeight(v2s16 p, f32 y, bool generate=false);
|
||||
|
||||
/*
|
||||
These functions handle metadata.
|
||||
They do not handle blocks.
|
||||
*/
|
||||
|
||||
void serialize(std::ostream &os, u8 version);
|
||||
|
||||
static ServerMapSector* deSerialize(
|
||||
std::istream &is,
|
||||
NodeContainer *parent,
|
||||
Map *parent,
|
||||
v2s16 p2d,
|
||||
core::map<v2s16, MapSector*> & sectors
|
||||
);
|
||||
|
@ -262,7 +121,7 @@ private:
|
|||
class ClientMapSector : public MapSector
|
||||
{
|
||||
public:
|
||||
ClientMapSector(NodeContainer *parent, v2s16 pos);
|
||||
ClientMapSector(Map *parent, v2s16 pos);
|
||||
~ClientMapSector();
|
||||
|
||||
u32 getId() const
|
||||
|
@ -270,16 +129,7 @@ public:
|
|||
return MAPSECTOR_CLIENT;
|
||||
}
|
||||
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
/*s16 getCorner(u16 i)
|
||||
{
|
||||
return m_corners[i];
|
||||
}*/
|
||||
|
||||
private:
|
||||
// The ground height of the corners is stored in here
|
||||
//s16 m_corners[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MINERAL_HEADER
|
||||
|
||||
#include "inventory.h"
|
||||
#include "tile.h"
|
||||
|
||||
/*
|
||||
Minerals
|
||||
|
|
|
@ -238,7 +238,11 @@ double noise3d_param(const NoiseParams ¶m, double x, double y, double z)
|
|||
y /= 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,
|
||||
param.octaves,
|
||||
|
|
|
@ -82,10 +82,11 @@ double noise3d_perlin_abs(double x, double y, double z, int seed,
|
|||
|
||||
enum NoiseType
|
||||
{
|
||||
NOISE_CONSTANT_ONE,
|
||||
NOISE_PERLIN,
|
||||
NOISE_PERLIN_ABS,
|
||||
NOISE_PERLIN_CONTOUR,
|
||||
NOISE_PERLIN_CONTOUR_FLIP_YZ
|
||||
NOISE_PERLIN_CONTOUR_FLIP_YZ,
|
||||
};
|
||||
|
||||
struct NoiseParams
|
||||
|
|
|
@ -309,6 +309,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
v3f oldpos = position;
|
||||
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
||||
|
||||
v3f old_speed = m_speed;
|
||||
|
||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||
|
||||
|
@ -405,8 +407,23 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
if(position.Y < min_y)
|
||||
{
|
||||
position.Y = min_y;
|
||||
|
||||
//v3f old_speed = m_speed;
|
||||
|
||||
if(m_speed.Y < 0)
|
||||
m_speed.Y = 0;
|
||||
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
info.speed = m_speed.Y - old_speed.Y;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,13 +574,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
*/
|
||||
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];
|
||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||
|
||||
if(collision_info)
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
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;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -656,6 +673,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
Set new 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)
|
||||
|
|
|
@ -53,12 +53,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
15: StaticObjects
|
||||
16: larger maximum size of node metadata, and compression
|
||||
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
|
||||
#define SER_FMT_VER_INVALID 255
|
||||
// Highest supported serialization version
|
||||
#define SER_FMT_VER_HIGHEST 18
|
||||
#define SER_FMT_VER_HIGHEST 19
|
||||
// Lowest supported serialization version
|
||||
#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_craft.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "mapblock.h"
|
||||
#include "serverobject.h"
|
||||
|
||||
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
||||
|
||||
|
@ -600,6 +602,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||
bool block_is_invalid = false;
|
||||
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.
|
||||
// It means it has been not found from disk and not generated
|
||||
if(block->isDummy())
|
||||
|
@ -1295,13 +1300,22 @@ void Server::AsyncRunStep()
|
|||
}
|
||||
|
||||
{
|
||||
// Step environment
|
||||
// This also runs Map's timers
|
||||
JMutexAutoLock lock(m_env_mutex);
|
||||
// Step environment
|
||||
ScopeProfiler sp(&g_profiler, "Server: environment step");
|
||||
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
|
||||
*/
|
||||
|
@ -1656,9 +1670,22 @@ void Server::AsyncRunStep()
|
|||
*/
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
got_any_events = true;
|
||||
|
||||
MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
|
||||
|
||||
// Players far away from the change are stored here.
|
||||
|
@ -1668,28 +1695,41 @@ void Server::AsyncRunStep()
|
|||
|
||||
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,
|
||||
&far_players, 30);
|
||||
}
|
||||
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,
|
||||
&far_players, 30);
|
||||
}
|
||||
else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
|
||||
{
|
||||
dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
|
||||
prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
|
||||
setBlockNotSent(event->p);
|
||||
}
|
||||
else if(event->type == MEET_OTHER)
|
||||
{
|
||||
prof.add("MEET_OTHER", 1);
|
||||
dstream<<"WARNING: Server: MEET_OTHER not implemented"
|
||||
<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
prof.add("unknown", 1);
|
||||
dstream<<"WARNING: Server: Unknown MapEditEvent "
|
||||
<<((u32)event->type)<<std::endl;
|
||||
}
|
||||
|
@ -1697,14 +1737,19 @@ void Server::AsyncRunStep()
|
|||
/*
|
||||
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;
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = event->modified_blocks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
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
|
||||
i = far_players.begin();
|
||||
i != far_players.end(); i++)
|
||||
|
@ -1715,14 +1760,22 @@ void Server::AsyncRunStep()
|
|||
continue;
|
||||
client->SetBlocksNotSent(modified_blocks2);
|
||||
}
|
||||
}
|
||||
|
||||
delete event;
|
||||
|
||||
// Don't send too many at a time
|
||||
/*// Don't send too many at a time
|
||||
count++;
|
||||
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
|
||||
bysy state sometimes)
|
||||
|
@ -1809,19 +1829,23 @@ void Server::AsyncRunStep()
|
|||
|
||||
// Map
|
||||
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
|
||||
m_env.getMap().save(true);
|
||||
|
||||
// Delete unused sectors
|
||||
u32 deleted_count = m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
if(deleted_count > 0)
|
||||
/*if(deleted_count > 0)
|
||||
{
|
||||
dout_server<<"Server: Unloaded "<<deleted_count
|
||||
<<" sectors from memory"<<std::endl;
|
||||
}
|
||||
<<" blocks from memory"<<std::endl;
|
||||
}*/
|
||||
|
||||
// Save players
|
||||
m_env.serializePlayers(m_mapsavedir);
|
||||
|
@ -1831,7 +1855,6 @@ void Server::AsyncRunStep()
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -2710,9 +2737,31 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
MaterialItem *mitem = (MaterialItem*)item;
|
||||
MapNode n;
|
||||
n.d = mitem->getMaterial();
|
||||
|
||||
// Calculate direction for wall mounted stuff
|
||||
if(content_features(n.d).wall_mounted)
|
||||
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
|
||||
*/
|
||||
|
@ -3286,7 +3335,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
|
||||
void Server::onMapEditEvent(MapEditEvent *event)
|
||||
{
|
||||
dstream<<"Server::onMapEditEvent()"<<std::endl;
|
||||
//dstream<<"Server::onMapEditEvent()"<<std::endl;
|
||||
if(m_ignore_map_edit_events)
|
||||
return;
|
||||
MapEditEvent *e = event->clone();
|
||||
|
|
|
@ -534,6 +534,7 @@ private:
|
|||
float m_objectdata_timer;
|
||||
float m_emergethread_trigger_timer;
|
||||
float m_savemap_timer;
|
||||
IntervalLimiter m_map_timer_and_unload_interval;
|
||||
|
||||
// NOTE: If connection and environment are both to be locked,
|
||||
// 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 <fstream>
|
||||
#include "environment.h"
|
||||
#include "inventory.h"
|
||||
#include "collision.h"
|
||||
|
||||
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
|
||||
packet.
|
||||
*/
|
||||
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||
bool send_recommended){}
|
||||
virtual void step(float dtime, bool send_recommended){}
|
||||
|
||||
/*
|
||||
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.
|
||||
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
|
||||
|
@ -144,6 +144,11 @@ public:
|
|||
*/
|
||||
v3s16 m_static_block;
|
||||
|
||||
/*
|
||||
Queue of messages to be sent to the client
|
||||
*/
|
||||
Queue<ActiveObjectMessage> m_messages_out;
|
||||
|
||||
protected:
|
||||
// Used for creating objects based on type
|
||||
typedef ServerActiveObject* (*Factory)
|
||||
|
@ -159,96 +164,5 @@ private:
|
|||
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
|
||||
|
||||
|
|
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 "porting.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "mapsector.h"
|
||||
|
||||
/*
|
||||
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
|
||||
{
|
||||
class TC : public NodeContainer
|
||||
|
@ -641,13 +648,13 @@ struct TestMapSector
|
|||
// Create one with no heightmaps
|
||||
ServerMapSector sector(&parent, v2s16(1,1));
|
||||
|
||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
|
||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(1));
|
||||
assert(sector.getBlockNoCreateNoEx(0) == 0);
|
||||
assert(sector.getBlockNoCreateNoEx(1) == 0);
|
||||
|
||||
MapBlock * bref = sector.createBlankBlock(-2);
|
||||
|
||||
EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
|
||||
assert(sector.getBlockNoCreate(-2) == bref);
|
||||
assert(sector.getBlockNoCreateNoEx(0) == 0);
|
||||
assert(sector.getBlockNoCreateNoEx(-2) == bref);
|
||||
|
||||
//TODO: Check for AlreadyExistsException
|
||||
|
||||
|
@ -662,6 +669,7 @@ struct TestMapSector
|
|||
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TestSocket
|
||||
{
|
||||
|
@ -1028,8 +1036,8 @@ void run_tests()
|
|||
TEST(TestCompress);
|
||||
TEST(TestMapNode);
|
||||
TEST(TestVoxelManipulator);
|
||||
TEST(TestMapBlock);
|
||||
TEST(TestMapSector);
|
||||
//TEST(TestMapBlock);
|
||||
//TEST(TestMapSector);
|
||||
if(INTERNET_SIMULATOR == false){
|
||||
TEST(TestSocket);
|
||||
dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
||||
|
|
Loading…
Reference in New Issue