Merge branch 'master' of git://github.com/celeron55/minetest
Also: Some changes, bigger teleportsmaster
commit
0d367550bc
|
@ -10,7 +10,7 @@ project(minetest)
|
||||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 3)
|
set(VERSION_MINOR 3)
|
||||||
set(VERSION_PATCH dev-20111016)
|
set(VERSION_PATCH dev-20111021)
|
||||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
|
|
||||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||||
|
|
|
@ -3,6 +3,11 @@ Minetest-c55 changelog
|
||||||
This should contain all the major changes.
|
This should contain all the major changes.
|
||||||
For minor stuff, refer to the commit log of the repository.
|
For minor stuff, refer to the commit log of the repository.
|
||||||
|
|
||||||
|
0.3.dev-20111021:
|
||||||
|
- Modify dungeon masters to only try to shoot players
|
||||||
|
- Fix object duplication bug at block load/unload bug
|
||||||
|
- Improve network layer
|
||||||
|
|
||||||
0.3.dev-20111016:
|
0.3.dev-20111016:
|
||||||
- Locked chest
|
- Locked chest
|
||||||
- Server user limit setting (max_users)
|
- Server user limit setting (max_users)
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#keymap_jump = KEY_SPACE
|
#keymap_jump = KEY_SPACE
|
||||||
#keymap_sneak = KEY_LSHIFT
|
#keymap_sneak = KEY_LSHIFT
|
||||||
#keymap_inventory = KEY_KEY_I
|
#keymap_inventory = KEY_KEY_I
|
||||||
|
# Go down ladder / go down in fly mode / go fast in fast mode
|
||||||
|
#keymap_special1 = KEY_KEY_E
|
||||||
#keymap_chat = KEY_KEY_T
|
#keymap_chat = KEY_KEY_T
|
||||||
#keymap_rangeselect = KEY_KEY_R
|
#keymap_rangeselect = KEY_KEY_R
|
||||||
#keymap_freemove = KEY_KEY_K
|
#keymap_freemove = KEY_KEY_K
|
||||||
|
@ -46,7 +48,6 @@
|
||||||
#keymap_frametime_graph = KEY_F1
|
#keymap_frametime_graph = KEY_F1
|
||||||
#keymap_screenshot = KEY_F12
|
#keymap_screenshot = KEY_F12
|
||||||
# Some (temporary) keys for debugging
|
# Some (temporary) keys for debugging
|
||||||
#keymap_special1 = KEY_KEY_E
|
|
||||||
#keymap_print_debug_stacks = KEY_KEY_P
|
#keymap_print_debug_stacks = KEY_KEY_P
|
||||||
|
|
||||||
# The desired FPS
|
# The desired FPS
|
||||||
|
@ -58,8 +59,8 @@
|
||||||
#viewing_range_nodes_max = 300
|
#viewing_range_nodes_max = 300
|
||||||
#viewing_range_nodes_min = 25
|
#viewing_range_nodes_min = 25
|
||||||
# Initial window size
|
# Initial window size
|
||||||
screenW# = 800
|
#screenW = 800
|
||||||
screenH# = 600
|
#screenH = 600
|
||||||
# Address to connect to (#blank = start local server)
|
# Address to connect to (#blank = start local server)
|
||||||
#address =
|
#address =
|
||||||
# Enable random user input, for testing
|
# Enable random user input, for testing
|
||||||
|
@ -139,11 +140,11 @@ screenH# = 600
|
||||||
# Player and object positions are sent at intervals specified by this
|
# Player and object positions are sent at intervals specified by this
|
||||||
#objectdata_interval = 0.2
|
#objectdata_interval = 0.2
|
||||||
#active_object_send_range_blocks = 3
|
#active_object_send_range_blocks = 3
|
||||||
#active_block_range = 5
|
#active_block_range = 2
|
||||||
#max_simultaneous_block_sends_per_client = 2
|
#max_simultaneous_block_sends_per_client = 2
|
||||||
#max_simultaneous_block_sends_server_total = 8
|
#max_simultaneous_block_sends_server_total = 8
|
||||||
#max_block_send_distance = 8
|
#max_block_send_distance = 7
|
||||||
#max_block_generate_distance = 8
|
#max_block_generate_distance = 5
|
||||||
#time_send_interval = 20
|
#time_send_interval = 20
|
||||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||||
#time_speed = 72
|
#time_speed = 72
|
||||||
|
|
|
@ -342,7 +342,7 @@ void Camera::updateViewingRange(f32 frametime_in)
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
m_draw_control.wanted_min_range = m_viewing_range_min;
|
m_draw_control.wanted_min_range = m_viewing_range_min;
|
||||||
m_draw_control.wanted_max_blocks = (1.5*m_draw_control.blocks_would_have_drawn)+1;
|
m_draw_control.wanted_max_blocks = (2.0*m_draw_control.blocks_would_have_drawn)+1;
|
||||||
if (m_draw_control.wanted_max_blocks < 10)
|
if (m_draw_control.wanted_max_blocks < 10)
|
||||||
m_draw_control.wanted_max_blocks = 10;
|
m_draw_control.wanted_max_blocks = 10;
|
||||||
|
|
||||||
|
@ -364,7 +364,9 @@ void Camera::updateViewingRange(f32 frametime_in)
|
||||||
//dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;
|
//dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;
|
||||||
|
|
||||||
// If needed frametime change is small, just return
|
// If needed frametime change is small, just return
|
||||||
if (fabs(wanted_frametime_change) < m_wanted_frametime*0.4)
|
// This value was 0.4 for many months until 2011-10-18 by c55;
|
||||||
|
// Let's see how this works out.
|
||||||
|
if (fabs(wanted_frametime_change) < m_wanted_frametime*0.33)
|
||||||
{
|
{
|
||||||
//dstream<<"ignoring small wanted_frametime_change"<<std::endl;
|
//dstream<<"ignoring small wanted_frametime_change"<<std::endl;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -156,7 +156,7 @@ void * MeshUpdateThread::Thread()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "mesh make");
|
ScopeProfiler sp(g_profiler, "Client: Mesh making");
|
||||||
|
|
||||||
scene::SMesh *mesh_new = NULL;
|
scene::SMesh *mesh_new = NULL;
|
||||||
mesh_new = makeMapBlockMesh(q->data);
|
mesh_new = makeMapBlockMesh(q->data);
|
||||||
|
@ -246,7 +246,7 @@ void Client::connect(Address address)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||||
m_con.setTimeoutMs(0);
|
m_con.SetTimeoutMs(0);
|
||||||
m_con.Connect(address);
|
m_con.Connect(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,8 +563,8 @@ void Client::step(float dtime)
|
||||||
counter = 0.0;
|
counter = 0.0;
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||||
// connectedAndInitialized() is true, peer exists.
|
// connectedAndInitialized() is true, peer exists.
|
||||||
con::Peer *peer = m_con.GetPeer(PEER_ID_SERVER);
|
float avg_rtt = m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
||||||
infostream<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
|
infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,14 +709,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
con::Peer *peer;
|
|
||||||
{
|
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
|
||||||
// All data is coming from the server
|
|
||||||
// PeerNotFoundException is handled by caller.
|
|
||||||
peer = m_con.GetPeer(PEER_ID_SERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 ser_version = m_server_ser_ver;
|
u8 ser_version = m_server_ser_ver;
|
||||||
|
|
||||||
//infostream<<"Client received command="<<(int)command<<std::endl;
|
//infostream<<"Client received command="<<(int)command<<std::endl;
|
||||||
|
@ -2254,4 +2246,12 @@ ClientEvent Client::getClientEvent()
|
||||||
return m_client_event_queue.pop_front();
|
return m_client_event_queue.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Client::getRTT(void)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
||||||
|
} catch(con::PeerNotFoundException &e){
|
||||||
|
return 1337;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
12
src/client.h
12
src/client.h
|
@ -251,11 +251,11 @@ public:
|
||||||
|
|
||||||
float getAvgRtt()
|
float getAvgRtt()
|
||||||
{
|
{
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
try{
|
||||||
con::Peer *peer = m_con.GetPeerNoEx(PEER_ID_SERVER);
|
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
||||||
if(peer == NULL)
|
} catch(con::PeerNotFoundException){
|
||||||
return 0.0;
|
return 1337;
|
||||||
return peer->avg_rtt;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getChatMessage(std::wstring &message)
|
bool getChatMessage(std::wstring &message)
|
||||||
|
@ -301,6 +301,8 @@ public:
|
||||||
return m_access_denied_reason;
|
return m_access_denied_reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getRTT(void);
|
||||||
|
|
||||||
//j
|
//j
|
||||||
inline ClientEnvironment * getEnv()
|
inline ClientEnvironment * getEnv()
|
||||||
{
|
{
|
||||||
|
|
|
@ -175,6 +175,11 @@ enum ToClientCommand
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//official minetest version has new commands
|
||||||
|
//but we want our server's to be back-compatible with jachoo's version
|
||||||
|
//we should delete this #ifdef on release
|
||||||
|
#ifdef CELERON55_COMPATIBLE
|
||||||
TOCLIENT_DEATHSCREEN = 0x37,
|
TOCLIENT_DEATHSCREEN = 0x37,
|
||||||
/*
|
/*
|
||||||
u16 command
|
u16 command
|
||||||
|
@ -209,6 +214,12 @@ enum ToClientCommand
|
||||||
u16 command
|
u16 command
|
||||||
u16 clan id
|
u16 clan id
|
||||||
*/
|
*/
|
||||||
|
#else //def CELERON55_COMPATIBLE
|
||||||
|
TOCLIENT_DEATHSCREEN = 0x3A,
|
||||||
|
TOCLIENT_PLAYER_CLAN = 0x37,
|
||||||
|
TOCLIENT_CLAN_NAMES = 0x38,
|
||||||
|
TOCLIENT_CLAN_DELETED = 0x39,
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "noise.h"
|
#include "noise.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "main.h" // For g_profiler and g_settings
|
||||||
|
#include "profiler.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
Clouds::Clouds(
|
Clouds::Clouds(
|
||||||
scene::ISceneNode* parent,
|
scene::ISceneNode* parent,
|
||||||
|
@ -76,6 +79,12 @@ void Clouds::render()
|
||||||
if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
|
if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ScopeProfiler sp(g_profiler, "Rendering of clouds, avg", SPT_AVG);
|
||||||
|
|
||||||
|
int num_faces_to_draw = 6;
|
||||||
|
if(g_settings->getBool("enable_2d_clouds"))
|
||||||
|
num_faces_to_draw = 1;
|
||||||
|
|
||||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
driver->setMaterial(m_material);
|
driver->setMaterial(m_material);
|
||||||
|
|
||||||
|
@ -144,7 +153,7 @@ void Clouds::render()
|
||||||
f32 ry = 8*BS;
|
f32 ry = 8*BS;
|
||||||
f32 rz = cloud_size;
|
f32 rz = cloud_size;
|
||||||
|
|
||||||
for(int i=0;i<6;i++)
|
for(int i=0; i<num_faces_to_draw; i++)
|
||||||
{
|
{
|
||||||
switch(i)
|
switch(i)
|
||||||
{
|
{
|
||||||
|
|
1411
src/connection.cpp
1411
src/connection.cpp
File diff suppressed because it is too large
Load Diff
289
src/connection.h
289
src/connection.h
|
@ -319,28 +319,6 @@ struct Channel
|
||||||
{
|
{
|
||||||
Channel();
|
Channel();
|
||||||
~Channel();
|
~Channel();
|
||||||
/*
|
|
||||||
Processes a packet with the basic header stripped out.
|
|
||||||
Parameters:
|
|
||||||
packetdata: Data in packet (with no base headers)
|
|
||||||
con: The connection to which the channel is associated
|
|
||||||
(used for sending back stuff (ACKs))
|
|
||||||
peer_id: peer id of the sender of the packet in question
|
|
||||||
channelnum: channel on which the packet was sent
|
|
||||||
reliable: true if recursing into a reliable packet
|
|
||||||
*/
|
|
||||||
SharedBuffer<u8> ProcessPacket(
|
|
||||||
SharedBuffer<u8> packetdata,
|
|
||||||
Connection *con,
|
|
||||||
u16 peer_id,
|
|
||||||
u8 channelnum,
|
|
||||||
bool reliable=false);
|
|
||||||
|
|
||||||
// Returns next data from a buffer if possible
|
|
||||||
// throws a NoIncomingDataException if no data is available
|
|
||||||
// If found, sets peer_id
|
|
||||||
SharedBuffer<u8> CheckIncomingBuffers(Connection *con,
|
|
||||||
u16 &peer_id);
|
|
||||||
|
|
||||||
u16 next_outgoing_seqnum;
|
u16 next_outgoing_seqnum;
|
||||||
u16 next_incoming_seqnum;
|
u16 next_incoming_seqnum;
|
||||||
|
@ -412,78 +390,237 @@ public:
|
||||||
// with the id we have given to it
|
// with the id we have given to it
|
||||||
bool has_sent_with_id;
|
bool has_sent_with_id;
|
||||||
|
|
||||||
|
float m_sendtime_accu;
|
||||||
|
float m_max_packets_per_second;
|
||||||
|
int m_num_sent;
|
||||||
|
int m_max_num_sent;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
class Connection
|
/*
|
||||||
|
Connection
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OutgoingPacket
|
||||||
|
{
|
||||||
|
u16 peer_id;
|
||||||
|
u8 channelnum;
|
||||||
|
SharedBuffer<u8> data;
|
||||||
|
bool reliable;
|
||||||
|
|
||||||
|
OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
|
||||||
|
bool reliable_):
|
||||||
|
peer_id(peer_id_),
|
||||||
|
channelnum(channelnum_),
|
||||||
|
data(data_),
|
||||||
|
reliable(reliable_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ConnectionEventType{
|
||||||
|
CONNEVENT_NONE,
|
||||||
|
CONNEVENT_DATA_RECEIVED,
|
||||||
|
CONNEVENT_PEER_ADDED,
|
||||||
|
CONNEVENT_PEER_REMOVED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConnectionEvent
|
||||||
|
{
|
||||||
|
enum ConnectionEventType type;
|
||||||
|
u16 peer_id;
|
||||||
|
SharedBuffer<u8> data;
|
||||||
|
bool timeout;
|
||||||
|
Address address;
|
||||||
|
|
||||||
|
ConnectionEvent(): type(CONNEVENT_NONE) {}
|
||||||
|
|
||||||
|
std::string describe()
|
||||||
|
{
|
||||||
|
switch(type){
|
||||||
|
case CONNEVENT_NONE:
|
||||||
|
return "CONNEVENT_NONE";
|
||||||
|
case CONNEVENT_DATA_RECEIVED:
|
||||||
|
return "CONNEVENT_DATA_RECEIVED";
|
||||||
|
case CONNEVENT_PEER_ADDED:
|
||||||
|
return "CONNEVENT_PEER_ADDED";
|
||||||
|
case CONNEVENT_PEER_REMOVED:
|
||||||
|
return "CONNEVENT_PEER_REMOVED";
|
||||||
|
}
|
||||||
|
return "Invalid ConnectionEvent";
|
||||||
|
}
|
||||||
|
|
||||||
|
void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
|
||||||
|
{
|
||||||
|
type = CONNEVENT_DATA_RECEIVED;
|
||||||
|
peer_id = peer_id_;
|
||||||
|
data = data_;
|
||||||
|
}
|
||||||
|
void peerAdded(u16 peer_id_, Address address_)
|
||||||
|
{
|
||||||
|
type = CONNEVENT_PEER_ADDED;
|
||||||
|
peer_id = peer_id_;
|
||||||
|
address = address_;
|
||||||
|
}
|
||||||
|
void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
|
||||||
|
{
|
||||||
|
type = CONNEVENT_PEER_REMOVED;
|
||||||
|
peer_id = peer_id_;
|
||||||
|
timeout = timeout_;
|
||||||
|
address = address_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ConnectionCommandType{
|
||||||
|
CONNCMD_NONE,
|
||||||
|
CONNCMD_SERVE,
|
||||||
|
CONNCMD_CONNECT,
|
||||||
|
CONNCMD_DISCONNECT,
|
||||||
|
CONNCMD_SEND,
|
||||||
|
CONNCMD_SEND_TO_ALL,
|
||||||
|
CONNCMD_DELETE_PEER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConnectionCommand
|
||||||
|
{
|
||||||
|
enum ConnectionCommandType type;
|
||||||
|
u16 port;
|
||||||
|
Address address;
|
||||||
|
u16 peer_id;
|
||||||
|
u8 channelnum;
|
||||||
|
SharedBuffer<u8> data;
|
||||||
|
bool reliable;
|
||||||
|
|
||||||
|
ConnectionCommand(): type(CONNCMD_NONE) {}
|
||||||
|
|
||||||
|
void serve(u16 port_)
|
||||||
|
{
|
||||||
|
type = CONNCMD_SERVE;
|
||||||
|
port = port_;
|
||||||
|
}
|
||||||
|
void connect(Address address_)
|
||||||
|
{
|
||||||
|
type = CONNCMD_CONNECT;
|
||||||
|
address = address_;
|
||||||
|
}
|
||||||
|
void disconnect()
|
||||||
|
{
|
||||||
|
type = CONNCMD_DISCONNECT;
|
||||||
|
}
|
||||||
|
void send(u16 peer_id_, u8 channelnum_,
|
||||||
|
SharedBuffer<u8> data_, bool reliable_)
|
||||||
|
{
|
||||||
|
type = CONNCMD_SEND;
|
||||||
|
peer_id = peer_id_;
|
||||||
|
channelnum = channelnum_;
|
||||||
|
data = data_;
|
||||||
|
reliable = reliable_;
|
||||||
|
}
|
||||||
|
void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
|
||||||
|
{
|
||||||
|
type = CONNCMD_SEND_TO_ALL;
|
||||||
|
channelnum = channelnum_;
|
||||||
|
data = data_;
|
||||||
|
reliable = reliable_;
|
||||||
|
}
|
||||||
|
void deletePeer(u16 peer_id_)
|
||||||
|
{
|
||||||
|
type = CONNCMD_DELETE_PEER;
|
||||||
|
peer_id = peer_id_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Connection: public SimpleThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Connection(
|
Connection(u32 protocol_id, u32 max_packet_size, float timeout);
|
||||||
u32 protocol_id,
|
Connection(u32 protocol_id, u32 max_packet_size, float timeout,
|
||||||
u32 max_packet_size,
|
PeerHandler *peerhandler);
|
||||||
float timeout,
|
|
||||||
PeerHandler *peerhandler
|
|
||||||
);
|
|
||||||
~Connection();
|
~Connection();
|
||||||
void setTimeoutMs(int timeout){ m_socket.setTimeoutMs(timeout); }
|
void * Thread();
|
||||||
// Start being a server
|
|
||||||
|
/* Interface */
|
||||||
|
|
||||||
|
ConnectionEvent getEvent();
|
||||||
|
ConnectionEvent waitEvent(u32 timeout_ms);
|
||||||
|
void putCommand(ConnectionCommand &c);
|
||||||
|
|
||||||
|
void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
|
||||||
void Serve(unsigned short port);
|
void Serve(unsigned short port);
|
||||||
// Connect to a server
|
|
||||||
void Connect(Address address);
|
void Connect(Address address);
|
||||||
bool Connected();
|
bool Connected();
|
||||||
|
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
// Sets peer_id
|
|
||||||
SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
|
|
||||||
|
|
||||||
// The peer_id of sender is stored in peer_id
|
|
||||||
// Return value: I guess this always throws an exception or
|
|
||||||
// actually gets data
|
|
||||||
// May call PeerHandler methods
|
|
||||||
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
|
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
|
||||||
|
|
||||||
// These will automatically package the data as an original or split
|
|
||||||
void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||||
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||||
// Send data as a packet; it will be wrapped in base header and
|
void RunTimeouts(float dtime); // dummy
|
||||||
// optionally to a reliable packet.
|
|
||||||
void SendAsPacket(u16 peer_id, u8 channelnum,
|
|
||||||
SharedBuffer<u8> data, bool reliable);
|
|
||||||
// Sends a raw packet
|
|
||||||
void RawSend(const BufferedPacket &packet);
|
|
||||||
|
|
||||||
// May call PeerHandler methods
|
|
||||||
void RunTimeouts(float dtime);
|
|
||||||
|
|
||||||
// Can throw a PeerNotFoundException
|
|
||||||
Peer* GetPeer(u16 peer_id);
|
|
||||||
// returns NULL if failed
|
|
||||||
Peer* GetPeerNoEx(u16 peer_id);
|
|
||||||
core::list<Peer*> GetPeers();
|
|
||||||
|
|
||||||
// Calls PeerHandler::deletingPeer
|
|
||||||
// Returns false if peer was not found
|
|
||||||
bool deletePeer(u16 peer_id, bool timeout);
|
|
||||||
|
|
||||||
void SetPeerID(u16 id){ m_peer_id = id; }
|
|
||||||
u16 GetPeerID(){ return m_peer_id; }
|
u16 GetPeerID(){ return m_peer_id; }
|
||||||
u32 GetProtocolID(){ return m_protocol_id; }
|
Address GetPeerAddress(u16 peer_id);
|
||||||
|
float GetPeerAvgRTT(u16 peer_id);
|
||||||
|
void DeletePeer(u16 peer_id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void putEvent(ConnectionEvent &e);
|
||||||
|
void processCommand(ConnectionCommand &c);
|
||||||
|
void send(float dtime);
|
||||||
|
void receive();
|
||||||
|
void runTimeouts(float dtime);
|
||||||
|
void serve(u16 port);
|
||||||
|
void connect(Address address);
|
||||||
|
void disconnect();
|
||||||
|
void sendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||||
|
void send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||||
|
void sendAsPacket(u16 peer_id, u8 channelnum,
|
||||||
|
SharedBuffer<u8> data, bool reliable);
|
||||||
|
void rawSendAsPacket(u16 peer_id, u8 channelnum,
|
||||||
|
SharedBuffer<u8> data, bool reliable);
|
||||||
|
void rawSend(const BufferedPacket &packet);
|
||||||
|
Peer* getPeer(u16 peer_id);
|
||||||
|
Peer* getPeerNoEx(u16 peer_id);
|
||||||
|
core::list<Peer*> getPeers();
|
||||||
|
bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst);
|
||||||
|
// Returns next data from a buffer if possible
|
||||||
|
// If found, returns true; if not, false.
|
||||||
|
// If found, sets peer_id and dst
|
||||||
|
bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
|
||||||
|
SharedBuffer<u8> &dst);
|
||||||
|
/*
|
||||||
|
Processes a packet with the basic header stripped out.
|
||||||
|
Parameters:
|
||||||
|
packetdata: Data in packet (with no base headers)
|
||||||
|
peer_id: peer id of the sender of the packet in question
|
||||||
|
channelnum: channel on which the packet was sent
|
||||||
|
reliable: true if recursing into a reliable packet
|
||||||
|
*/
|
||||||
|
SharedBuffer<u8> processPacket(Channel *channel,
|
||||||
|
SharedBuffer<u8> packetdata, u16 peer_id,
|
||||||
|
u8 channelnum, bool reliable);
|
||||||
|
bool deletePeer(u16 peer_id, bool timeout);
|
||||||
|
|
||||||
|
Queue<OutgoingPacket> m_outgoing_queue;
|
||||||
|
MutexedQueue<ConnectionEvent> m_event_queue;
|
||||||
|
MutexedQueue<ConnectionCommand> m_command_queue;
|
||||||
|
|
||||||
|
u32 m_protocol_id;
|
||||||
|
u32 m_max_packet_size;
|
||||||
|
float m_timeout;
|
||||||
|
UDPSocket m_socket;
|
||||||
|
u16 m_peer_id;
|
||||||
|
|
||||||
|
core::map<u16, Peer*> m_peers;
|
||||||
|
JMutex m_peers_mutex;
|
||||||
|
|
||||||
// For debug printing
|
// Backwards compatibility
|
||||||
|
PeerHandler *m_bc_peerhandler;
|
||||||
|
int m_bc_receive_timeout;
|
||||||
|
|
||||||
|
void SetPeerID(u16 id){ m_peer_id = id; }
|
||||||
|
u32 GetProtocolID(){ return m_protocol_id; }
|
||||||
void PrintInfo(std::ostream &out);
|
void PrintInfo(std::ostream &out);
|
||||||
void PrintInfo();
|
void PrintInfo();
|
||||||
|
std::string getDesc();
|
||||||
u16 m_indentation;
|
u16 m_indentation;
|
||||||
|
|
||||||
private:
|
|
||||||
u32 m_protocol_id;
|
|
||||||
float m_timeout;
|
|
||||||
PeerHandler *m_peerhandler;
|
|
||||||
core::map<u16, Peer*> m_peers;
|
|
||||||
u16 m_peer_id;
|
|
||||||
//bool m_waiting_new_peer_id;
|
|
||||||
u32 m_max_packet_size;
|
|
||||||
UDPSocket m_socket;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -208,6 +208,35 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
// This is needed for changing the texture in the future
|
// This is needed for changing the texture in the future
|
||||||
m_node->setReadOnlyMaterials(true);
|
m_node->setReadOnlyMaterials(true);
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update image of node
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||||
|
<<m_inventorystring<<"\" -> item="<<item
|
||||||
|
<<std::endl;
|
||||||
|
if(item)
|
||||||
|
{
|
||||||
|
texture = item->getImage();
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||||
|
<<": error deSerializing inventorystring \""
|
||||||
|
<<m_inventorystring<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set meshbuffer texture
|
||||||
|
buf->getMaterial().setTexture(0, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemCAO::removeFromScene()
|
void ItemCAO::removeFromScene()
|
||||||
|
@ -289,49 +318,6 @@ void ItemCAO::initialize(const std::string &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNodePos();
|
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);
|
|
||||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
|
||||||
<<m_inventorystring<<"\" -> item="<<item
|
|
||||||
<<std::endl;
|
|
||||||
if(item)
|
|
||||||
{
|
|
||||||
texture = item->getImage();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(SerializationError &e)
|
|
||||||
{
|
|
||||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
|
||||||
<<": error deSerializing inventorystring \""
|
|
||||||
<<m_inventorystring<<"\""<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set meshbuffer texture
|
|
||||||
buf->getMaterial().setTexture(0, texture);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1007,11 +993,15 @@ void MobV2CAO::updateNodePos()
|
||||||
void MobV2CAO::step(float dtime, ClientEnvironment *env)
|
void MobV2CAO::step(float dtime, ClientEnvironment *env)
|
||||||
{
|
{
|
||||||
scene::MyBillboardSceneNode *bill = m_node;
|
scene::MyBillboardSceneNode *bill = m_node;
|
||||||
|
if(!bill)
|
||||||
|
return;
|
||||||
|
|
||||||
pos_translator.translate(dtime);
|
pos_translator.translate(dtime);
|
||||||
|
|
||||||
if(m_sprite_type == "humanoid_1"){
|
if(m_sprite_type == "humanoid_1"){
|
||||||
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
||||||
|
if(!camera)
|
||||||
|
return;
|
||||||
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
||||||
cam_to_mob.normalize();
|
cam_to_mob.normalize();
|
||||||
int col = 0;
|
int col = 0;
|
||||||
|
|
|
@ -72,8 +72,8 @@ std::string item_craft_get_image_name(const std::string &subname)
|
||||||
else if(subname == "firefly")
|
else if(subname == "firefly")
|
||||||
return "firefly.png";
|
return "firefly.png";
|
||||||
else if(subname == "apple")
|
else if(subname == "apple")
|
||||||
return "apple.png";
|
return "apple.png^[forcesingle";
|
||||||
else if(subname == "apple_iron")
|
else if(subname == "apple_iron")
|
||||||
return "apple_iron.png";
|
return "apple_iron.png";
|
||||||
else
|
else
|
||||||
return "cloud.png"; // just something
|
return "cloud.png"; // just something
|
||||||
|
|
|
@ -143,7 +143,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
// New-style leaves material
|
// New-style leaves material
|
||||||
video::SMaterial material_leaves1;
|
video::SMaterial material_leaves1;
|
||||||
material_leaves1.setFlag(video::EMF_LIGHTING, false);
|
material_leaves1.setFlag(video::EMF_LIGHTING, false);
|
||||||
//material_leaves1.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
@ -229,25 +228,54 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
v3s16 p(x,y,z);
|
v3s16 p(x,y,z);
|
||||||
|
|
||||||
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
|
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add torches to mesh
|
Add torches to mesh
|
||||||
*/
|
*/
|
||||||
if(n.getContent() == CONTENT_TORCH)
|
if(n.getContent() == CONTENT_TORCH)
|
||||||
{
|
{
|
||||||
|
v3s16 dir = unpackDir(n.param2);
|
||||||
|
|
||||||
|
const char *texturename = "torch.png";
|
||||||
|
if(dir == v3s16(0,-1,0)){
|
||||||
|
texturename = "torch_on_floor.png";
|
||||||
|
} else if(dir == v3s16(0,1,0)){
|
||||||
|
texturename = "torch_on_ceiling.png";
|
||||||
|
// For backwards compatibility
|
||||||
|
} else if(dir == v3s16(0,0,0)){
|
||||||
|
texturename = "torch_on_floor.png";
|
||||||
|
} else {
|
||||||
|
texturename = "torch.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
AtlasPointer ap = g_texturesource->getTexture(texturename);
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
material.MaterialType
|
||||||
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
material.setTexture(0, ap.atlas);
|
||||||
|
|
||||||
video::SColor c(255,255,255,255);
|
video::SColor c(255,255,255,255);
|
||||||
|
|
||||||
// Wall at X+ of node
|
// Wall at X+ of node
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
|
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
|
ap.x0(), ap.y1()),
|
||||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
ap.x1(), ap.y1()),
|
||||||
|
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
|
||||||
|
ap.x1(), ap.y0()),
|
||||||
|
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
|
||||||
|
ap.x0(), ap.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
v3s16 dir = unpackDir(n.param2);
|
|
||||||
|
|
||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
if(dir == v3s16(1,0,0))
|
if(dir == v3s16(1,0,0))
|
||||||
|
@ -266,29 +294,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
|
||||||
video::SMaterial material;
|
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
material.MaterialType
|
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
|
|
||||||
if(dir == v3s16(0,-1,0))
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("torch_on_floor.png"));
|
|
||||||
else if(dir == v3s16(0,1,0))
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("torch_on_ceiling.png"));
|
|
||||||
// For backwards compatibility
|
|
||||||
else if(dir == v3s16(0,0,0))
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("torch_on_floor.png"));
|
|
||||||
else
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("torch.png"));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material, vertices, 4, indices, 6);
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
@ -298,6 +303,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
*/
|
*/
|
||||||
else if(n.getContent() == CONTENT_SIGN_WALL)
|
else if(n.getContent() == CONTENT_SIGN_WALL)
|
||||||
{
|
{
|
||||||
|
AtlasPointer ap = g_texturesource->getTexture("sign_wall.png");
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
material.MaterialType
|
||||||
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
material.setTexture(0, ap.atlas);
|
||||||
|
|
||||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||||
video::SColor c = MapBlock_LightColor(255, l);
|
video::SColor c = MapBlock_LightColor(255, l);
|
||||||
|
|
||||||
|
@ -305,10 +322,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
// Wall at X+ of node
|
// Wall at X+ of node
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
|
||||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
ap.x0(), ap.y1()),
|
||||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
|
||||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
ap.x1(), ap.y1()),
|
||||||
|
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
|
||||||
|
ap.x1(), ap.y0()),
|
||||||
|
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
|
||||||
|
ap.x0(), ap.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
v3s16 dir = unpackDir(n.param2);
|
v3s16 dir = unpackDir(n.param2);
|
||||||
|
@ -331,19 +352,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
|
||||||
video::SMaterial material;
|
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
material.MaterialType
|
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("sign_wall.png"));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material, vertices, 4, indices, 6);
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
@ -353,17 +361,37 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
*/
|
*/
|
||||||
else if(n.getContent() == CONTENT_TELEPORT)
|
else if(n.getContent() == CONTENT_TELEPORT)
|
||||||
{
|
{
|
||||||
|
AtlasPointer ap = g_texturesource->getTexture("teleport.png");
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
|
||||||
|
material.setTexture(0,ap.atlas);
|
||||||
|
|
||||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||||
video::SColor c = MapBlock_LightColor(255, l);
|
video::SColor c = MapBlock_LightColor(255, l);
|
||||||
|
|
||||||
float d = (float)BS/16;
|
float d = (float)BS/16;
|
||||||
// Wall at X+ of node
|
// Wall at X+ of node
|
||||||
video::S3DVertex vertices[4] =
|
/*video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
||||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
||||||
|
};*/
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(BS/2-d,-BS,-BS, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2-d,-BS,BS, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2-d,BS,BS, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(BS/2-d,BS,-BS, 0,0,0, c, 0,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
v3s16 dir = unpackDir(n.param2);
|
v3s16 dir = unpackDir(n.param2);
|
||||||
|
@ -386,19 +414,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
|
||||||
video::SMaterial material;
|
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
material.MaterialType
|
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
|
|
||||||
material.setTexture(0,
|
|
||||||
g_texturesource->getTextureRaw("teleport.png"));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material, vertices, 4, indices, 6);
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
@ -580,10 +595,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
@ -665,10 +676,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
{
|
{
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
@ -723,10 +730,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
@ -760,10 +763,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
{
|
{
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
pa_leaves1.x0(), pa_leaves1.y1()),
|
pa_leaves1.x0(), pa_leaves1.y1()),
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
|
@ -982,10 +981,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
ap.x0(), ap.y1()),
|
ap.x0(), ap.y1()),
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
|
@ -1089,13 +1084,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||||
pa_papyrus.x0(), pa_papyrus.y1()),
|
pa_junglegrass.x0(), pa_junglegrass.y1()),
|
||||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||||
pa_papyrus.x1(), pa_papyrus.y1()),
|
pa_junglegrass.x1(), pa_junglegrass.y1()),
|
||||||
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
|
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
|
||||||
pa_papyrus.x1(), pa_papyrus.y0()),
|
pa_junglegrass.x1(), pa_junglegrass.y0()),
|
||||||
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
|
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
|
||||||
pa_papyrus.x0(), pa_papyrus.y0()),
|
pa_junglegrass.x0(), pa_junglegrass.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if(j == 0)
|
if(j == 0)
|
||||||
|
@ -1132,9 +1127,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
}
|
}
|
||||||
else if(n.getContent() == CONTENT_RAIL)
|
else if(n.getContent() == CONTENT_RAIL)
|
||||||
{
|
{
|
||||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
|
||||||
video::SColor c = MapBlock_LightColor(255, l);
|
|
||||||
|
|
||||||
bool is_rail_x [] = { false, false }; /* x-1, x+1 */
|
bool is_rail_x [] = { false, false }; /* x-1, x+1 */
|
||||||
bool is_rail_z [] = { false, false }; /* z-1, z+1 */
|
bool is_rail_z [] = { false, false }; /* z-1, z+1 */
|
||||||
|
|
||||||
|
@ -1152,18 +1144,25 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
if(n_plus_z.getContent() == CONTENT_RAIL)
|
if(n_plus_z.getContent() == CONTENT_RAIL)
|
||||||
is_rail_z[1] = true;
|
is_rail_z[1] = true;
|
||||||
|
|
||||||
float d = (float)BS/16;
|
int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
|
// Assign textures
|
||||||
|
const char *texturename = "rail.png";
|
||||||
|
if(adjacencies < 2)
|
||||||
|
texturename = "rail.png";
|
||||||
|
else if(adjacencies == 2)
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
|
||||||
0, 1),
|
texturename = "rail.png";
|
||||||
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
else
|
||||||
1, 1),
|
texturename = "rail_curved.png";
|
||||||
video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
}
|
||||||
1, 0),
|
else if(adjacencies == 3)
|
||||||
video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
texturename = "rail_t_junction.png";
|
||||||
0, 0),
|
else if(adjacencies == 4)
|
||||||
};
|
texturename = "rail_crossing.png";
|
||||||
|
|
||||||
|
AtlasPointer ap = g_texturesource->getTexture(texturename);
|
||||||
|
|
||||||
video::SMaterial material_rail;
|
video::SMaterial material_rail;
|
||||||
material_rail.setFlag(video::EMF_LIGHTING, false);
|
material_rail.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
@ -1172,23 +1171,23 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
material_rail.setFlag(video::EMF_FOG_ENABLE, true);
|
material_rail.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
material_rail.MaterialType
|
material_rail.MaterialType
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
material_rail.setTexture(0, ap.atlas);
|
||||||
|
|
||||||
int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
|
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||||
|
video::SColor c = MapBlock_LightColor(255, l);
|
||||||
|
|
||||||
// Assign textures
|
float d = (float)BS/16;
|
||||||
if(adjacencies < 2)
|
video::S3DVertex vertices[4] =
|
||||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
|
|
||||||
else if(adjacencies == 2)
|
|
||||||
{
|
{
|
||||||
if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
|
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
|
ap.x0(), ap.y1()),
|
||||||
else
|
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_curved.png"));
|
ap.x1(), ap.y1()),
|
||||||
}
|
video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||||
else if(adjacencies == 3)
|
ap.x1(), ap.y0()),
|
||||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_t_junction.png"));
|
video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||||
else if(adjacencies == 4)
|
ap.x0(), ap.y0()),
|
||||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_crossing.png"));
|
};
|
||||||
|
|
||||||
// Rotate textures
|
// Rotate textures
|
||||||
int angle = 0;
|
int angle = 0;
|
||||||
|
@ -1235,6 +1234,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
collector.append(material_rail, vertices, 4, indices, 6);
|
collector.append(material_rail, vertices, 4, indices, 6);
|
||||||
}
|
}
|
||||||
else if (n.getContent() == CONTENT_LADDER) {
|
else if (n.getContent() == CONTENT_LADDER) {
|
||||||
|
AtlasPointer ap = g_texturesource->getTexture("ladder.png");
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material_ladder;
|
||||||
|
material_ladder.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
material_ladder.setTexture(0, ap.atlas);
|
||||||
|
|
||||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||||
video::SColor c(255,l,l,l);
|
video::SColor c(255,l,l,l);
|
||||||
|
|
||||||
|
@ -1243,10 +1253,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
// Assume wall is at X+
|
// Assume wall is at X+
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
|
||||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
ap.x0(), ap.y1()),
|
||||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
|
||||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
ap.x1(), ap.y1()),
|
||||||
|
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
|
||||||
|
ap.x1(), ap.y0()),
|
||||||
|
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
|
||||||
|
ap.x0(), ap.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
v3s16 dir = unpackDir(n.param2);
|
v3s16 dir = unpackDir(n.param2);
|
||||||
|
@ -1269,14 +1283,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
video::SMaterial material_ladder;
|
|
||||||
material_ladder.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
material_ladder.setTexture(0, g_texturesource->getTextureRaw("ladder.png"));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material_ladder, vertices, 4, indices, 6);
|
collector.append(material_ladder, vertices, 4, indices, 6);
|
||||||
|
|
|
@ -117,6 +117,7 @@ void content_mapnode_init()
|
||||||
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
f->often_contains_mineral = true;
|
||||||
f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
|
f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
|
||||||
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
if(invisible_stone)
|
if(invisible_stone)
|
||||||
|
@ -219,6 +220,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_JUNGLEGRASS;
|
i = CONTENT_JUNGLEGRASS;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("junglegrass.png");
|
f->setInventoryTexture("junglegrass.png");
|
||||||
|
f->used_texturenames["junglegrass.png"] = true;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
//f->is_ground_content = true;
|
//f->is_ground_content = true;
|
||||||
|
@ -264,6 +266,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_PAPYRUS;
|
i = CONTENT_PAPYRUS;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("papyrus.png");
|
f->setInventoryTexture("papyrus.png");
|
||||||
|
f->used_texturenames["papyrus.png"] = true;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
@ -306,11 +309,13 @@ void content_mapnode_init()
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
f->air_equivalent = true; // grass grows underneath
|
f->air_equivalent = true; // grass grows underneath
|
||||||
f->setInventoryTexture("fence.png");
|
f->setInventoryTexture("fence.png");
|
||||||
|
f->used_texturenames["fence.png"] = true;
|
||||||
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
|
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
|
||||||
|
|
||||||
i = CONTENT_RAIL;
|
i = CONTENT_RAIL;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("rail.png");
|
f->setInventoryTexture("rail.png");
|
||||||
|
f->used_texturenames["rail.png"] = true;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
@ -323,6 +328,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_LADDER;
|
i = CONTENT_LADDER;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("ladder.png");
|
f->setInventoryTexture("ladder.png");
|
||||||
|
f->used_texturenames["ladder.png"] = true;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
@ -465,6 +471,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_LAVA;
|
i = CONTENT_LAVA;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||||
|
f->used_texturenames["lava.png"] = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = false;
|
f->light_propagates = false;
|
||||||
f->light_source = LIGHT_MAX-1;
|
f->light_source = LIGHT_MAX-1;
|
||||||
|
@ -501,6 +508,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_LAVASOURCE;
|
i = CONTENT_LAVASOURCE;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||||
|
f->used_texturenames["ladder.png"] = true;
|
||||||
if(new_style_water)
|
if(new_style_water)
|
||||||
{
|
{
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
@ -554,6 +562,10 @@ void content_mapnode_init()
|
||||||
i = CONTENT_TORCH;
|
i = CONTENT_TORCH;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("torch_on_floor.png");
|
f->setInventoryTexture("torch_on_floor.png");
|
||||||
|
f->used_texturenames["torch_on_floor.png"] = true;
|
||||||
|
f->used_texturenames["torch_on_ceiling.png"] = true;
|
||||||
|
f->used_texturenames["torch_on_floor.png"] = true;
|
||||||
|
f->used_texturenames["torch.png"] = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->sunlight_propagates = true;
|
f->sunlight_propagates = true;
|
||||||
|
@ -568,6 +580,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_SIGN_WALL;
|
i = CONTENT_SIGN_WALL;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("sign_wall.png");
|
f->setInventoryTexture("sign_wall.png");
|
||||||
|
f->used_texturenames["sign_wall.png"] = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->sunlight_propagates = true;
|
f->sunlight_propagates = true;
|
||||||
|
@ -670,6 +683,7 @@ void content_mapnode_init()
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->setAllTextures("sapling.png");
|
f->setAllTextures("sapling.png");
|
||||||
f->setInventoryTexture("sapling.png");
|
f->setInventoryTexture("sapling.png");
|
||||||
|
f->used_texturenames["sapling.png"] = true;
|
||||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->air_equivalent = false;
|
f->air_equivalent = false;
|
||||||
|
@ -692,8 +706,8 @@ void content_mapnode_init()
|
||||||
|
|
||||||
i = CONTENT_TELEPORT;
|
i = CONTENT_TELEPORT;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setAllTextures("teleport.png");
|
//f->setAllTextures("teleport.png");
|
||||||
//f->setInventoryTexture("teleport.png");
|
f->setInventoryTexture("teleport.png");
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->light_source = 3; //?
|
f->light_source = 3; //?
|
||||||
|
@ -710,6 +724,7 @@ void content_mapnode_init()
|
||||||
i = CONTENT_APPLE;
|
i = CONTENT_APPLE;
|
||||||
f = &content_features(i);
|
f = &content_features(i);
|
||||||
f->setInventoryTexture("apple.png");
|
f->setInventoryTexture("apple.png");
|
||||||
|
f->used_texturenames["apple.png"] = true;
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->sunlight_propagates = true;
|
f->sunlight_propagates = true;
|
||||||
|
|
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "profiler.h"
|
||||||
|
|
||||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||||
|
|
||||||
|
@ -137,6 +138,8 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
|
||||||
void ItemSAO::step(float dtime, bool send_recommended)
|
void ItemSAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
assert(m_env);
|
assert(m_env);
|
||||||
|
|
||||||
const float interval = 0.2;
|
const float interval = 0.2;
|
||||||
|
@ -291,6 +294,8 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
|
||||||
void RatSAO::step(float dtime, bool send_recommended)
|
void RatSAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
assert(m_env);
|
assert(m_env);
|
||||||
|
|
||||||
if(m_is_active == false)
|
if(m_is_active == false)
|
||||||
|
@ -480,6 +485,8 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
|
||||||
void Oerkki1SAO::step(float dtime, bool send_recommended)
|
void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
assert(m_env);
|
assert(m_env);
|
||||||
|
|
||||||
if(m_is_active == false)
|
if(m_is_active == false)
|
||||||
|
@ -677,11 +684,25 @@ std::string Oerkki1SAO::getStaticData()
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir)
|
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir,
|
||||||
|
const std::string &playername)
|
||||||
{
|
{
|
||||||
m_speed_f += dir*12*BS;
|
m_speed_f += dir*12*BS;
|
||||||
|
|
||||||
u16 amount = 20;
|
u16 amount = 5;
|
||||||
|
/* See tool names in inventory.h */
|
||||||
|
if(toolname == "WSword")
|
||||||
|
amount = 10;
|
||||||
|
if(toolname == "STSword")
|
||||||
|
amount = 12;
|
||||||
|
if(toolname == "SteelSword")
|
||||||
|
amount = 16;
|
||||||
|
if(toolname == "STAxe")
|
||||||
|
amount = 7;
|
||||||
|
if(toolname == "SteelAxe")
|
||||||
|
amount = 9;
|
||||||
|
if(toolname == "SteelPick")
|
||||||
|
amount = 7;
|
||||||
doDamage(amount);
|
doDamage(amount);
|
||||||
return 65536/100;
|
return 65536/100;
|
||||||
}
|
}
|
||||||
|
@ -752,6 +773,8 @@ ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
|
||||||
void FireflySAO::step(float dtime, bool send_recommended)
|
void FireflySAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
assert(m_env);
|
assert(m_env);
|
||||||
|
|
||||||
if(m_is_active == false)
|
if(m_is_active == false)
|
||||||
|
@ -1065,6 +1088,8 @@ static void explodeSquare(Map *map, v3s16 p0, v3s16 size)
|
||||||
|
|
||||||
void MobV2SAO::step(float dtime, bool send_recommended)
|
void MobV2SAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "MobV2SAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
assert(m_env);
|
assert(m_env);
|
||||||
Map *map = &m_env->getMap();
|
Map *map = &m_env->getMap();
|
||||||
|
|
||||||
|
@ -1239,8 +1264,6 @@ void MobV2SAO::step(float dtime, bool send_recommended)
|
||||||
m_base_position = pos_f;
|
m_base_position = pos_f;
|
||||||
|
|
||||||
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
||||||
verbosestream<<"Mob id="<<m_id<<": arrived to "
|
|
||||||
<<PP(m_next_pos_i)<<std::endl;
|
|
||||||
m_next_pos_exists = false;
|
m_next_pos_exists = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,8 @@ public:
|
||||||
std::string getClientInitializationData();
|
std::string getClientInitializationData();
|
||||||
std::string getStaticData();
|
std::string getStaticData();
|
||||||
InventoryItem* createPickedUpItem(){return NULL;}
|
InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
u16 punch(const std::string &toolname, v3f dir);
|
u16 punch(const std::string &toolname, v3f dir,
|
||||||
|
const std::string &playername);
|
||||||
bool isPeaceful(){return false;}
|
bool isPeaceful(){return false;}
|
||||||
private:
|
private:
|
||||||
void doDamage(u16 d);
|
void doDamage(u16 d);
|
||||||
|
|
|
@ -36,6 +36,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("keymap_jump", "KEY_SPACE");
|
settings->setDefault("keymap_jump", "KEY_SPACE");
|
||||||
settings->setDefault("keymap_sneak", "KEY_LSHIFT");
|
settings->setDefault("keymap_sneak", "KEY_LSHIFT");
|
||||||
settings->setDefault("keymap_inventory", "KEY_KEY_I");
|
settings->setDefault("keymap_inventory", "KEY_KEY_I");
|
||||||
|
settings->setDefault("keymap_special1", "KEY_KEY_E");
|
||||||
settings->setDefault("keymap_chat", "KEY_KEY_T");
|
settings->setDefault("keymap_chat", "KEY_KEY_T");
|
||||||
settings->setDefault("keymap_cmd", "/");
|
settings->setDefault("keymap_cmd", "/");
|
||||||
settings->setDefault("keymap_rangeselect", "KEY_KEY_R");
|
settings->setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||||
|
@ -43,8 +44,9 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||||
settings->setDefault("keymap_frametime_graph", "KEY_F1");
|
settings->setDefault("keymap_frametime_graph", "KEY_F1");
|
||||||
settings->setDefault("keymap_screenshot", "KEY_F12");
|
settings->setDefault("keymap_screenshot", "KEY_F12");
|
||||||
|
settings->setDefault("keymap_toggle_profiler", "KEY_F2");
|
||||||
|
settings->setDefault("keymap_toggle_force_fog_off", "KEY_F3");
|
||||||
// Some (temporary) keys for debugging
|
// Some (temporary) keys for debugging
|
||||||
settings->setDefault("keymap_special1", "KEY_KEY_E");
|
|
||||||
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||||
|
|
||||||
settings->setDefault("wanted_fps", "30");
|
settings->setDefault("wanted_fps", "30");
|
||||||
|
@ -75,6 +77,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("invisible_stone", "false");
|
settings->setDefault("invisible_stone", "false");
|
||||||
settings->setDefault("screenshot_path", ".");
|
settings->setDefault("screenshot_path", ".");
|
||||||
settings->setDefault("view_bobbing_amount", "1.0");
|
settings->setDefault("view_bobbing_amount", "1.0");
|
||||||
|
settings->setDefault("enable_2d_clouds", "false");
|
||||||
|
|
||||||
// Server stuff
|
// Server stuff
|
||||||
// "map-dir" doesn't exist by default.
|
// "map-dir" doesn't exist by default.
|
||||||
|
@ -93,13 +96,13 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||||
settings->setDefault("objectdata_interval", "0.2");
|
settings->setDefault("objectdata_interval", "0.2");
|
||||||
settings->setDefault("active_object_send_range_blocks", "3");
|
settings->setDefault("active_object_send_range_blocks", "3");
|
||||||
settings->setDefault("active_block_range", "5");
|
settings->setDefault("active_block_range", "2");
|
||||||
//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
|
//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||||
// This causes frametime jitter on client side, or does it?
|
// This causes frametime jitter on client side, or does it?
|
||||||
settings->setDefault("max_simultaneous_block_sends_per_client", "2");
|
settings->setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||||
settings->setDefault("max_simultaneous_block_sends_server_total", "8");
|
settings->setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||||
settings->setDefault("max_block_send_distance", "8");
|
settings->setDefault("max_block_send_distance", "7");
|
||||||
settings->setDefault("max_block_generate_distance", "8");
|
settings->setDefault("max_block_generate_distance", "5");
|
||||||
settings->setDefault("time_send_interval", "20");
|
settings->setDefault("time_send_interval", "20");
|
||||||
settings->setDefault("time_speed", "96");
|
settings->setDefault("time_speed", "96");
|
||||||
settings->setDefault("server_unload_unused_data_timeout", "60");
|
settings->setDefault("server_unload_unused_data_timeout", "60");
|
||||||
|
|
|
@ -653,6 +653,92 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerEnvironment::clearAllObjects()
|
||||||
|
{
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Removing all active objects"<<std::endl;
|
||||||
|
core::list<u16> objects_to_remove;
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
ServerActiveObject* obj = i.getNode()->getValue();
|
||||||
|
u16 id = i.getNode()->getKey();
|
||||||
|
v3f objectpos = obj->getBasePosition();
|
||||||
|
// Delete static object if block is loaded
|
||||||
|
if(obj->m_static_exists){
|
||||||
|
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||||
|
if(block){
|
||||||
|
block->m_static_objects.remove(id);
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
obj->m_static_exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If known by some client, don't delete immediately
|
||||||
|
if(obj->m_known_by_count > 0){
|
||||||
|
obj->m_pending_deactivation = true;
|
||||||
|
obj->m_removed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Delete active object
|
||||||
|
delete obj;
|
||||||
|
// Id to be removed from m_active_objects
|
||||||
|
objects_to_remove.push_back(id);
|
||||||
|
}
|
||||||
|
// Remove references from m_active_objects
|
||||||
|
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||||
|
i != objects_to_remove.end(); i++)
|
||||||
|
{
|
||||||
|
m_active_objects.remove(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
core::list<v3s16> loadable_blocks;
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Listing all loadable blocks"<<std::endl;
|
||||||
|
m_map->listAllLoadableBlocks(loadable_blocks);
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Done listing all loadable blocks: "
|
||||||
|
<<loadable_blocks.size()
|
||||||
|
<<", now clearing"<<std::endl;
|
||||||
|
u32 report_interval = loadable_blocks.size() / 10;
|
||||||
|
u32 num_blocks_checked = 0;
|
||||||
|
u32 num_blocks_cleared = 0;
|
||||||
|
u32 num_objs_cleared = 0;
|
||||||
|
for(core::list<v3s16>::Iterator i = loadable_blocks.begin();
|
||||||
|
i != loadable_blocks.end(); i++)
|
||||||
|
{
|
||||||
|
v3s16 p = *i;
|
||||||
|
MapBlock *block = m_map->emergeBlock(p, false);
|
||||||
|
if(!block){
|
||||||
|
errorstream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Failed to emerge block "<<PP(p)<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
u32 num_stored = block->m_static_objects.m_stored.size();
|
||||||
|
u32 num_active = block->m_static_objects.m_active.size();
|
||||||
|
if(num_stored != 0 || num_active != 0){
|
||||||
|
block->m_static_objects.m_stored.clear();
|
||||||
|
block->m_static_objects.m_active.clear();
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
num_objs_cleared += num_stored + num_active;
|
||||||
|
num_blocks_cleared++;
|
||||||
|
}
|
||||||
|
num_blocks_checked++;
|
||||||
|
|
||||||
|
if(num_blocks_checked % report_interval == 0){
|
||||||
|
float percent = 100.0 * (float)num_blocks_checked /
|
||||||
|
loadable_blocks.size();
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Cleared "<<num_objs_cleared<<" objects"
|
||||||
|
<<" in "<<num_blocks_cleared<<" blocks ("
|
||||||
|
<<percent<<"%)"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Finished: Cleared "<<num_objs_cleared<<" objects"
|
||||||
|
<<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
static void getMob_dungeon_master(Settings &properties)
|
static void getMob_dungeon_master(Settings &properties)
|
||||||
{
|
{
|
||||||
properties.set("looks", "dungeon_master");
|
properties.set("looks", "dungeon_master");
|
||||||
|
@ -690,7 +776,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
Handle players
|
Handle players
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
|
||||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
i != m_players.end(); i++)
|
i != m_players.end(); i++)
|
||||||
{
|
{
|
||||||
|
@ -732,7 +818,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
*/
|
*/
|
||||||
if(m_active_blocks_management_interval.step(dtime, 2.0))
|
if(m_active_blocks_management_interval.step(dtime, 2.0))
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg /2s", SPT_AVG);
|
||||||
/*
|
/*
|
||||||
Get player block positions
|
Get player block positions
|
||||||
*/
|
*/
|
||||||
|
@ -809,7 +895,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
*/
|
*/
|
||||||
if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
|
if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg /1s", SPT_AVG);
|
||||||
|
|
||||||
float dtime = 1.0;
|
float dtime = 1.0;
|
||||||
|
|
||||||
|
@ -848,7 +934,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
|
|
||||||
if(m_active_blocks_test_interval.step(dtime, 10.0))
|
if(m_active_blocks_test_interval.step(dtime, 10.0))
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg /10s", SPT_AVG);
|
||||||
//float dtime = 10.0;
|
//float dtime = 10.0;
|
||||||
|
|
||||||
for(core::map<v3s16, bool>::Iterator
|
for(core::map<v3s16, bool>::Iterator
|
||||||
|
@ -893,7 +979,18 @@ void ServerEnvironment::step(float dtime)
|
||||||
if(block==NULL)
|
if(block==NULL)
|
||||||
continue;
|
continue;
|
||||||
active_object_count_wider +=
|
active_object_count_wider +=
|
||||||
block->m_static_objects.m_active.size();
|
block->m_static_objects.m_active.size()
|
||||||
|
+ block->m_static_objects.m_stored.size();
|
||||||
|
|
||||||
|
/*if(block->m_static_objects.m_stored.size() != 0){
|
||||||
|
errorstream<<"ServerEnvironment::step(): "
|
||||||
|
<<PP(block->getPos())<<" contains "
|
||||||
|
<<block->m_static_objects.m_stored.size()
|
||||||
|
<<" stored objects; "
|
||||||
|
<<"when spawning objects, when counting active "
|
||||||
|
<<"objects in wide area. relative position: "
|
||||||
|
<<"("<<x<<","<<y<<","<<z<<")"<<std::endl;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
v3s16 p0;
|
v3s16 p0;
|
||||||
|
@ -1051,8 +1148,10 @@ void ServerEnvironment::step(float dtime)
|
||||||
Step active objects
|
Step active objects
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
|
||||||
//TimeTaker timer("Step active objects");
|
//TimeTaker timer("Step active objects");
|
||||||
|
|
||||||
|
g_profiler->avg("SEnv: num of objects", m_active_objects.size());
|
||||||
|
|
||||||
// This helps the objects to send data at the same time
|
// This helps the objects to send data at the same time
|
||||||
bool send_recommended = false;
|
bool send_recommended = false;
|
||||||
|
@ -1092,7 +1191,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
*/
|
*/
|
||||||
if(m_object_management_interval.step(dtime, 0.5))
|
if(m_object_management_interval.step(dtime, 0.5))
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg", SPT_LOWPASS);
|
ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg /.5s", SPT_AVG);
|
||||||
/*
|
/*
|
||||||
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
||||||
*/
|
*/
|
||||||
|
@ -1347,21 +1446,24 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
bool set_changed)
|
bool set_changed)
|
||||||
{
|
{
|
||||||
assert(object);
|
assert(object);
|
||||||
if(object->getId() == 0)
|
if(object->getId() == 0){
|
||||||
{
|
|
||||||
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
||||||
if(new_id == 0)
|
if(new_id == 0)
|
||||||
{
|
{
|
||||||
infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
<<"no free ids available"<<std::endl;
|
<<"no free ids available"<<std::endl;
|
||||||
delete object;
|
delete object;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
object->setId(new_id);
|
object->setId(new_id);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
|
<<"supplied with id "<<object->getId()<<std::endl;
|
||||||
|
}
|
||||||
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
||||||
{
|
{
|
||||||
infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||||
delete object;
|
delete object;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1370,7 +1472,12 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
||||||
|
|
||||||
m_active_objects.insert(object->getId(), object);
|
m_active_objects.insert(object->getId(), object);
|
||||||
|
|
||||||
|
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
|
<<"Added id="<<object->getId()<<"; there are now "
|
||||||
|
<<m_active_objects.size()<<" active objects."
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
// Add static object to active static list of the block
|
// Add static object to active static list of the block
|
||||||
v3f objectpos = object->getBasePosition();
|
v3f objectpos = object->getBasePosition();
|
||||||
std::string staticdata = object->getStaticData();
|
std::string staticdata = object->getStaticData();
|
||||||
|
@ -1385,11 +1492,12 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
object->m_static_block = blockpos;
|
object->m_static_block = blockpos;
|
||||||
|
|
||||||
if(set_changed)
|
if(set_changed)
|
||||||
block->setChangedFlag();
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
infostream<<"ServerEnv: Could not find a block for "
|
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
<<"storing newly added static active object"<<std::endl;
|
<<"could not find block for storing id="<<object->getId()
|
||||||
|
<<" statically"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return object->getId();
|
return object->getId();
|
||||||
|
@ -1429,11 +1537,12 @@ void ServerEnvironment::removeRemovedObjects()
|
||||||
*/
|
*/
|
||||||
if(obj->m_static_exists && obj->m_removed)
|
if(obj->m_static_exists && obj->m_removed)
|
||||||
{
|
{
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
MapBlock *block = m_map->emergeBlock(obj->m_static_block);
|
||||||
if(block)
|
if(block)
|
||||||
{
|
{
|
||||||
block->m_static_objects.remove(id);
|
block->m_static_objects.remove(id);
|
||||||
block->setChangedFlag();
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
obj->m_static_exists = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1563,40 @@ void ServerEnvironment::removeRemovedObjects()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_hexdump(std::ostream &o, const std::string &data)
|
||||||
|
{
|
||||||
|
const int linelength = 16;
|
||||||
|
for(int l=0; ; l++){
|
||||||
|
int i0 = linelength * l;
|
||||||
|
bool at_end = false;
|
||||||
|
int thislinelength = linelength;
|
||||||
|
if(i0 + thislinelength > (int)data.size()){
|
||||||
|
thislinelength = data.size() - i0;
|
||||||
|
at_end = true;
|
||||||
|
}
|
||||||
|
for(int di=0; di<linelength; di++){
|
||||||
|
int i = i0 + di;
|
||||||
|
char buf[4];
|
||||||
|
if(di<thislinelength)
|
||||||
|
snprintf(buf, 4, "%.2x ", data[i]);
|
||||||
|
else
|
||||||
|
snprintf(buf, 4, " ");
|
||||||
|
o<<buf;
|
||||||
|
}
|
||||||
|
o<<" ";
|
||||||
|
for(int di=0; di<thislinelength; di++){
|
||||||
|
int i = i0 + di;
|
||||||
|
if(data[i] >= 32)
|
||||||
|
o<<data[i];
|
||||||
|
else
|
||||||
|
o<<".";
|
||||||
|
}
|
||||||
|
o<<std::endl;
|
||||||
|
if(at_end)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert stored objects from blocks near the players to active.
|
Convert stored objects from blocks near the players to active.
|
||||||
*/
|
*/
|
||||||
|
@ -1464,6 +1607,21 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
||||||
// Ignore if no stored objects (to not set changed flag)
|
// Ignore if no stored objects (to not set changed flag)
|
||||||
if(block->m_static_objects.m_stored.size() == 0)
|
if(block->m_static_objects.m_stored.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
verbosestream<<"ServerEnvironment::activateObjects(): "
|
||||||
|
<<"activating objects of block "<<PP(block->getPos())
|
||||||
|
<<" ("<<block->m_static_objects.m_stored.size()
|
||||||
|
<<" objects)"<<std::endl;
|
||||||
|
bool large_amount = (block->m_static_objects.m_stored.size() > 49);
|
||||||
|
if(large_amount){
|
||||||
|
errorstream<<"suspiciously large amount of objects detected: "
|
||||||
|
<<block->m_static_objects.m_stored.size()<<" in "
|
||||||
|
<<PP(block->getPos())
|
||||||
|
<<"; removing all of them."<<std::endl;
|
||||||
|
// Clear stored list
|
||||||
|
block->m_static_objects.m_stored.clear();
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// A list for objects that couldn't be converted to static for some
|
// A list for objects that couldn't be converted to static for some
|
||||||
// reason. They will be stored back.
|
// reason. They will be stored back.
|
||||||
core::list<StaticObject> new_stored;
|
core::list<StaticObject> new_stored;
|
||||||
|
@ -1481,12 +1639,20 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
||||||
// If couldn't create object, store static data back.
|
// If couldn't create object, store static data back.
|
||||||
if(obj==NULL)
|
if(obj==NULL)
|
||||||
{
|
{
|
||||||
|
errorstream<<"ServerEnvironment::activateObjects(): "
|
||||||
|
<<"failed to create active object from static object "
|
||||||
|
<<"in block "<<PP(s_obj.pos/BS)
|
||||||
|
<<" type="<<(int)s_obj.type<<" data:"<<std::endl;
|
||||||
|
print_hexdump(verbosestream, s_obj.data);
|
||||||
|
|
||||||
new_stored.push_back(s_obj);
|
new_stored.push_back(s_obj);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
verbosestream<<"ServerEnvironment::activateObjects(): "
|
||||||
|
<<"activated static object pos="<<PP(s_obj.pos/BS)
|
||||||
|
<<" type="<<(int)s_obj.type<<std::endl;
|
||||||
// This will also add the object to the active static list
|
// This will also add the object to the active static list
|
||||||
addActiveObjectRaw(obj, false);
|
addActiveObjectRaw(obj, false);
|
||||||
//u16 id = addActiveObjectRaw(obj, false);
|
|
||||||
}
|
}
|
||||||
// Clear stored list
|
// Clear stored list
|
||||||
block->m_static_objects.m_stored.clear();
|
block->m_static_objects.m_stored.clear();
|
||||||
|
@ -1498,13 +1664,18 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
||||||
StaticObject &s_obj = *i;
|
StaticObject &s_obj = *i;
|
||||||
block->m_static_objects.m_stored.push_back(s_obj);
|
block->m_static_objects.m_stored.push_back(s_obj);
|
||||||
}
|
}
|
||||||
// Block has been modified
|
/*
|
||||||
// NOTE: No it has not really. Save I/O here.
|
Note: Block hasn't really been modified here.
|
||||||
//block->setChangedFlag();
|
The objects have just been activated and moved from the stored
|
||||||
|
static list to the active static list.
|
||||||
|
As such, the block is essentially the same.
|
||||||
|
Thus, do not call block->setChangedFlag().
|
||||||
|
Otherwise there would be a huge amount of unnecessary I/O.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert objects that are not in active blocks to static.
|
Convert objects that are not standing inside active blocks to static.
|
||||||
|
|
||||||
If m_known_by_count != 0, active object is not deleted, but static
|
If m_known_by_count != 0, active object is not deleted, but static
|
||||||
data is still updated.
|
data is still updated.
|
||||||
|
@ -1524,12 +1695,16 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||||
// This shouldn't happen but check it
|
// This shouldn't happen but check it
|
||||||
if(obj == NULL)
|
if(obj == NULL)
|
||||||
{
|
{
|
||||||
infostream<<"NULL object found in ServerEnvironment"
|
errorstream<<"NULL object found in ServerEnvironment"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
assert(0);
|
assert(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If pending deactivation, let removeRemovedObjects() do it
|
||||||
|
if(obj->m_pending_deactivation)
|
||||||
|
continue;
|
||||||
|
|
||||||
u16 id = i.getNode()->getKey();
|
u16 id = i.getNode()->getKey();
|
||||||
v3f objectpos = obj->getBasePosition();
|
v3f objectpos = obj->getBasePosition();
|
||||||
|
|
||||||
|
@ -1540,69 +1715,112 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||||
if(m_active_blocks.contains(blockpos_o))
|
if(m_active_blocks.contains(blockpos_o))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||||
|
<<"deactivating object id="<<id<<" on inactive block "
|
||||||
|
<<PP(blockpos_o)<<std::endl;
|
||||||
|
|
||||||
|
// If known by some client, don't immediately delete.
|
||||||
|
bool pending_delete = (obj->m_known_by_count > 0 && !force_delete);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update the static data
|
Update the static data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Create new static object
|
||||||
|
std::string staticdata_new = obj->getStaticData();
|
||||||
|
StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
|
||||||
|
|
||||||
|
bool stays_in_same_block = false;
|
||||||
|
bool data_changed = true;
|
||||||
|
|
||||||
|
if(obj->m_static_exists){
|
||||||
|
if(obj->m_static_block == blockpos_o)
|
||||||
|
stays_in_same_block = true;
|
||||||
|
|
||||||
|
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||||
|
|
||||||
|
core::map<u16, StaticObject>::Node *n =
|
||||||
|
block->m_static_objects.m_active.find(id);
|
||||||
|
if(n){
|
||||||
|
StaticObject static_old = n->getValue();
|
||||||
|
|
||||||
|
if(static_old.data == staticdata_new &&
|
||||||
|
(static_old.pos - objectpos).getLength() < 2*BS)
|
||||||
|
data_changed = false;
|
||||||
|
} else {
|
||||||
|
errorstream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||||
|
<<"id="<<id<<" m_static_exists=true but "
|
||||||
|
<<"static data doesn't actually exist in "
|
||||||
|
<<PP(obj->m_static_block)<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete old static object
|
// Delete old static object
|
||||||
MapBlock *oldblock = NULL;
|
|
||||||
if(obj->m_static_exists)
|
if(obj->m_static_exists)
|
||||||
{
|
{
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx
|
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||||
(obj->m_static_block);
|
|
||||||
if(block)
|
if(block)
|
||||||
{
|
{
|
||||||
block->m_static_objects.remove(id);
|
block->m_static_objects.remove(id);
|
||||||
oldblock = block;
|
obj->m_static_exists = false;
|
||||||
|
// Only mark block as modified if data changed considerably
|
||||||
|
if(!stays_in_same_block || data_changed)
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create new static object
|
|
||||||
std::string staticdata = obj->getStaticData();
|
|
||||||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
|
||||||
// Add to the block where the object is located in
|
// Add to the block where the object is located in
|
||||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||||
// Get or generate the block
|
// Get or generate the block
|
||||||
MapBlock *block = m_map->emergeBlock(blockpos);
|
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||||
|
|
||||||
/*MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
// Block not found. Is the old block still ok?
|
|
||||||
if(oldblock)
|
|
||||||
block = oldblock;
|
|
||||||
// Load from disk or generate
|
|
||||||
else
|
|
||||||
block = m_map->emergeBlock(blockpos);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if(block)
|
if(block)
|
||||||
{
|
{
|
||||||
block->m_static_objects.insert(0, s_obj);
|
if(block->m_static_objects.m_stored.size() >= 49){
|
||||||
block->setChangedFlag();
|
errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
|
||||||
obj->m_static_exists = true;
|
<<" statically but block "<<PP(blockpos)
|
||||||
obj->m_static_block = block->getPos();
|
<<" already contains "
|
||||||
|
<<block->m_static_objects.m_stored.size()
|
||||||
|
<<" (over 49) objects."
|
||||||
|
<<" Forcing delete."<<std::endl;
|
||||||
|
force_delete = true;
|
||||||
|
} else {
|
||||||
|
u16 new_id = pending_delete ? id : 0;
|
||||||
|
block->m_static_objects.insert(new_id, s_obj);
|
||||||
|
|
||||||
|
// Only mark block as modified if data changed considerably
|
||||||
|
if(!stays_in_same_block || data_changed)
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
|
||||||
|
obj->m_static_exists = true;
|
||||||
|
obj->m_static_block = block->getPos();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
infostream<<"ServerEnv: Could not find or generate "
|
errorstream<<"ServerEnv: Could not find or generate "
|
||||||
<<"a block for storing static object"<<std::endl;
|
<<"a block for storing id="<<obj->getId()
|
||||||
obj->m_static_exists = false;
|
<<" statically"<<std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Delete active object if not known by some client,
|
If known by some client, set pending deactivation.
|
||||||
else set pending deactivation
|
Otherwise delete it immediately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// If known by some client, don't delete.
|
if(pending_delete)
|
||||||
if(obj->m_known_by_count > 0 && force_delete == false)
|
|
||||||
{
|
{
|
||||||
|
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||||
|
<<"object id="<<id<<" is known by clients"
|
||||||
|
<<"; not deleting yet"<<std::endl;
|
||||||
|
|
||||||
obj->m_pending_deactivation = true;
|
obj->m_pending_deactivation = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*infostream<<"Server: Stored static data. Deleting object."
|
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||||
<<std::endl;*/
|
<<"object id="<<id<<" is not known by clients"
|
||||||
|
<<"; deleting"<<std::endl;
|
||||||
// Delete active object
|
// Delete active object
|
||||||
delete obj;
|
delete obj;
|
||||||
// Id to be removed from m_active_objects
|
// Id to be removed from m_active_objects
|
||||||
|
|
|
@ -225,6 +225,11 @@ public:
|
||||||
|
|
||||||
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
||||||
|
|
||||||
|
/* Other stuff */
|
||||||
|
|
||||||
|
// Clear all objects, loading and going through every MapBlock
|
||||||
|
void clearAllObjects();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
65
src/game.cpp
65
src/game.cpp
|
@ -450,10 +450,15 @@ void getPointedNode(Client *client, v3f player_position,
|
||||||
v3f cpf = npf + dir_f;
|
v3f cpf = npf + dir_f;
|
||||||
f32 distance = (cpf - camera_position).getLength();
|
f32 distance = (cpf - camera_position).getLength();
|
||||||
|
|
||||||
v3f vertices[4] =
|
/*v3f vertices[4] =
|
||||||
{
|
{
|
||||||
v3f(BS*0.42,-BS*0.4,-BS*0.4),
|
v3f(BS*0.42,-BS*0.4,-BS*0.4),
|
||||||
v3f(BS*0.49, BS*0.4, BS*0.4),
|
v3f(BS*0.49, BS*0.4, BS*0.4),
|
||||||
|
};*/
|
||||||
|
v3f vertices[4] =
|
||||||
|
{
|
||||||
|
v3f(BS*0.42,-BS*0.8,-BS*0.8),
|
||||||
|
v3f(BS*0.49, BS*0.8, BS*0.8),
|
||||||
};
|
};
|
||||||
|
|
||||||
for(s32 i=0; i<2; i++)
|
for(s32 i=0; i<2; i++)
|
||||||
|
@ -922,7 +927,6 @@ void the_game(
|
||||||
L"",
|
L"",
|
||||||
core::rect<s32>(5, 5+(text_height+5)*1, 795, (5+text_height)*2),
|
core::rect<s32>(5, 5+(text_height+5)*1, 795, (5+text_height)*2),
|
||||||
false, false, guiroot);
|
false, false, guiroot);
|
||||||
|
|
||||||
// At the middle of the screen
|
// At the middle of the screen
|
||||||
// Object infos are shown in this
|
// Object infos are shown in this
|
||||||
gui::IGUIStaticText *guitext_info = guienv->addStaticText(
|
gui::IGUIStaticText *guitext_info = guienv->addStaticText(
|
||||||
|
@ -945,6 +949,15 @@ void the_game(
|
||||||
//guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
|
//guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
|
||||||
core::list<ChatLine> chat_lines;
|
core::list<ChatLine> chat_lines;
|
||||||
|
|
||||||
|
// Profiler text
|
||||||
|
gui::IGUIStaticText *guitext_profiler = guienv->addStaticText(
|
||||||
|
L"<Profiler>",
|
||||||
|
core::rect<s32>(6, 4+(text_height+5)*3, 400,
|
||||||
|
(text_height+5)*3 + text_height*35),
|
||||||
|
false, false);
|
||||||
|
guitext_profiler->setBackgroundColor(video::SColor(80,0,0,0));
|
||||||
|
guitext_profiler->setVisible(false);
|
||||||
|
|
||||||
/*GUIQuickInventory *quick_inventory = new GUIQuickInventory
|
/*GUIQuickInventory *quick_inventory = new GUIQuickInventory
|
||||||
(guienv, NULL, v2s32(10, 70), 5, &local_inventory);*/
|
(guienv, NULL, v2s32(10, 70), 5, &local_inventory);*/
|
||||||
/*GUIQuickInventory *quick_inventory = new GUIQuickInventory
|
/*GUIQuickInventory *quick_inventory = new GUIQuickInventory
|
||||||
|
@ -998,6 +1011,10 @@ void the_game(
|
||||||
|
|
||||||
bool respawn_menu_active = false;
|
bool respawn_menu_active = false;
|
||||||
|
|
||||||
|
bool show_profiler = false;
|
||||||
|
|
||||||
|
bool force_fog_off = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Main loop
|
Main loop
|
||||||
*/
|
*/
|
||||||
|
@ -1129,7 +1146,8 @@ void the_game(
|
||||||
|
|
||||||
object_hit_delay_timer -= dtime;
|
object_hit_delay_timer -= dtime;
|
||||||
|
|
||||||
g_profiler->add("Elapsed time", dtime * 1000);
|
g_profiler->add("Elapsed time", dtime);
|
||||||
|
g_profiler->avg("FPS", 1./dtime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Log frametime for visualization
|
Log frametime for visualization
|
||||||
|
@ -1220,15 +1238,24 @@ void the_game(
|
||||||
*/
|
*/
|
||||||
float profiler_print_interval =
|
float profiler_print_interval =
|
||||||
g_settings->getFloat("profiler_print_interval");
|
g_settings->getFloat("profiler_print_interval");
|
||||||
if(profiler_print_interval != 0)
|
bool print_to_log = true;
|
||||||
|
if(profiler_print_interval == 0){
|
||||||
|
print_to_log = false;
|
||||||
|
profiler_print_interval = 5;
|
||||||
|
}
|
||||||
|
if(m_profiler_interval.step(dtime, profiler_print_interval))
|
||||||
{
|
{
|
||||||
if(m_profiler_interval.step(0.030, profiler_print_interval))
|
if(print_to_log){
|
||||||
{
|
|
||||||
infostream<<"Profiler:"<<std::endl;
|
infostream<<"Profiler:"<<std::endl;
|
||||||
g_profiler->print(infostream);
|
g_profiler->print(infostream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
g_profiler->print(os);
|
||||||
|
guitext_profiler->setText(narrow_to_wide(os.str()).c_str());
|
||||||
|
|
||||||
g_profiler->clear();
|
g_profiler->clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Direct handling of user input
|
Direct handling of user input
|
||||||
|
@ -1357,6 +1384,15 @@ void the_game(
|
||||||
image->drop();
|
image->drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(input->wasKeyDown(getKeySetting("keymap_toggle_profiler")))
|
||||||
|
{
|
||||||
|
show_profiler = !show_profiler;
|
||||||
|
guitext_profiler->setVisible(show_profiler);
|
||||||
|
}
|
||||||
|
else if(input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off")))
|
||||||
|
{
|
||||||
|
force_fog_off = !force_fog_off;
|
||||||
|
}
|
||||||
|
|
||||||
// Item selection with mouse wheel
|
// Item selection with mouse wheel
|
||||||
{
|
{
|
||||||
|
@ -2043,7 +2079,7 @@ void the_game(
|
||||||
Fog
|
Fog
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(g_settings->getBool("enable_fog") == true)
|
if(g_settings->getBool("enable_fog") == true && !force_fog_off)
|
||||||
{
|
{
|
||||||
f32 range;
|
f32 range;
|
||||||
if(farmesh)
|
if(farmesh)
|
||||||
|
@ -2053,10 +2089,11 @@ void the_game(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5;
|
range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5;
|
||||||
|
range *= 0.9;
|
||||||
if(draw_control.range_all)
|
if(draw_control.range_all)
|
||||||
range = 100000*BS;
|
range = 100000*BS;
|
||||||
if(range < 50*BS)
|
/*if(range < 50*BS)
|
||||||
range = range * 0.5 + 25*BS;
|
range = range * 0.5 + 25*BS;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->setFog(
|
driver->setFog(
|
||||||
|
@ -2121,14 +2158,15 @@ void the_game(
|
||||||
"(% .1f, % .1f, % .1f)"
|
"(% .1f, % .1f, % .1f)"
|
||||||
" (% .3f < btime_jitter < % .3f"
|
" (% .3f < btime_jitter < % .3f"
|
||||||
", dtime_jitter = % .1f %%"
|
", dtime_jitter = % .1f %%"
|
||||||
", v_range = %.1f)",
|
", v_range = %.1f, RTT = %.3f)",
|
||||||
player_position.X/BS,
|
player_position.X/BS,
|
||||||
player_position.Y/BS,
|
player_position.Y/BS,
|
||||||
player_position.Z/BS,
|
player_position.Z/BS,
|
||||||
busytime_jitter1_min_sample,
|
busytime_jitter1_min_sample,
|
||||||
busytime_jitter1_max_sample,
|
busytime_jitter1_max_sample,
|
||||||
dtime_jitter1_max_fraction * 100.0,
|
dtime_jitter1_max_fraction * 100.0,
|
||||||
draw_control.wanted_range
|
draw_control.wanted_range,
|
||||||
|
client.getRTT()
|
||||||
);
|
);
|
||||||
|
|
||||||
guitext2->setText(narrow_to_wide(temptext).c_str());
|
guitext2->setText(narrow_to_wide(temptext).c_str());
|
||||||
|
@ -2210,7 +2248,8 @@ void the_game(
|
||||||
|
|
||||||
guitext_chat->setRelativePosition(rect);
|
guitext_chat->setRelativePosition(rect);
|
||||||
|
|
||||||
if(chat_lines.size() == 0)
|
// Don't show chat if empty or profiler is enabled
|
||||||
|
if(chat_lines.size() == 0 || show_profiler)
|
||||||
guitext_chat->setVisible(false);
|
guitext_chat->setVisible(false);
|
||||||
else
|
else
|
||||||
guitext_chat->setVisible(true);
|
guitext_chat->setVisible(true);
|
||||||
|
|
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <IGUIButton.h>
|
#include <IGUIButton.h>
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
#include <IGUIFont.h>
|
#include <IGUIFont.h>
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
void drawInventoryItem(video::IVideoDriver *driver,
|
void drawInventoryItem(video::IVideoDriver *driver,
|
||||||
gui::IGUIFont *font,
|
gui::IGUIFont *font,
|
||||||
|
@ -326,11 +327,11 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||||
if(amount >= 0)
|
if(amount >= 0)
|
||||||
{
|
{
|
||||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||||
//dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
//infostream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||||
ItemSpec s = getItemAtPos(p);
|
ItemSpec s = getItemAtPos(p);
|
||||||
if(s.isValid())
|
if(s.isValid())
|
||||||
{
|
{
|
||||||
dstream<<"Mouse down on "<<s.inventoryname
|
infostream<<"Mouse down on "<<s.inventoryname
|
||||||
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
||||||
if(m_selected_item)
|
if(m_selected_item)
|
||||||
{
|
{
|
||||||
|
@ -345,15 +346,15 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||||
InventoryList *list_to =
|
InventoryList *list_to =
|
||||||
inv_to->getList(s.listname);
|
inv_to->getList(s.listname);
|
||||||
if(list_from == NULL)
|
if(list_from == NULL)
|
||||||
dstream<<"from list doesn't exist"<<std::endl;
|
infostream<<"from list doesn't exist"<<std::endl;
|
||||||
if(list_to == NULL)
|
if(list_to == NULL)
|
||||||
dstream<<"to list doesn't exist"<<std::endl;
|
infostream<<"to list doesn't exist"<<std::endl;
|
||||||
// Indicates whether source slot completely empties
|
// Indicates whether source slot completely empties
|
||||||
bool source_empties = false;
|
bool source_empties = false;
|
||||||
if(list_from && list_to
|
if(list_from && list_to
|
||||||
&& list_from->getItem(m_selected_item->i) != NULL)
|
&& list_from->getItem(m_selected_item->i) != NULL)
|
||||||
{
|
{
|
||||||
dstream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
infostream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
||||||
IMoveAction *a = new IMoveAction();
|
IMoveAction *a = new IMoveAction();
|
||||||
a->count = amount;
|
a->count = amount;
|
||||||
a->from_inv = m_selected_item->inventoryname;
|
a->from_inv = m_selected_item->inventoryname;
|
||||||
|
@ -408,7 +409,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||||
{
|
{
|
||||||
if(!canTakeFocus(event.GUIEvent.Element))
|
if(!canTakeFocus(event.GUIEvent.Element))
|
||||||
{
|
{
|
||||||
dstream<<"GUIInventoryMenu: Not allowing focus change."
|
infostream<<"GUIInventoryMenu: Not allowing focus change."
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
// Returning true disables focus change
|
// Returning true disables focus change
|
||||||
return true;
|
return true;
|
||||||
|
@ -474,7 +475,7 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
while(f.atend() == false)
|
while(f.atend() == false)
|
||||||
{
|
{
|
||||||
std::string type = trim(f.next("["));
|
std::string type = trim(f.next("["));
|
||||||
//dstream<<"type="<<type<<std::endl;
|
//infostream<<"type="<<type<<std::endl;
|
||||||
if(type == "list")
|
if(type == "list")
|
||||||
{
|
{
|
||||||
std::string name = f.next(";");
|
std::string name = f.next(";");
|
||||||
|
@ -485,7 +486,7 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
s32 pos_y = stoi(f.next(";"));
|
s32 pos_y = stoi(f.next(";"));
|
||||||
s32 geom_x = stoi(f.next(","));
|
s32 geom_x = stoi(f.next(","));
|
||||||
s32 geom_y = stoi(f.next(";"));
|
s32 geom_y = stoi(f.next(";"));
|
||||||
dstream<<"list name="<<name<<", subname="<<subname
|
infostream<<"list name="<<name<<", subname="<<subname
|
||||||
<<", pos=("<<pos_x<<","<<pos_y<<")"
|
<<", pos=("<<pos_x<<","<<pos_y<<")"
|
||||||
<<", geom=("<<geom_x<<","<<geom_y<<")"
|
<<", geom=("<<geom_x<<","<<geom_y<<")"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
@ -498,14 +499,14 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
{
|
{
|
||||||
invsize.X = stoi(f.next(","));
|
invsize.X = stoi(f.next(","));
|
||||||
invsize.Y = stoi(f.next(";"));
|
invsize.Y = stoi(f.next(";"));
|
||||||
dstream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
infostream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||||
f.next("]");
|
f.next("]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ignore others
|
// Ignore others
|
||||||
std::string ts = f.next("]");
|
std::string ts = f.next("]");
|
||||||
dstream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
infostream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "content_inventory.h"
|
#include "content_inventory.h"
|
||||||
#include "content_sao.h"
|
#include "content_sao.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InventoryItem
|
InventoryItem
|
||||||
|
@ -117,7 +118,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
|
infostream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
|
||||||
throw SerializationError("Unknown InventoryItem name");
|
throw SerializationError("Unknown InventoryItem name");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,51 +739,56 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string describeC(const struct InventoryContext *c)
|
||||||
|
{
|
||||||
|
if(c->current_player == NULL)
|
||||||
|
return "current_player=NULL";
|
||||||
|
else
|
||||||
|
return std::string("current_player=") + c->current_player->getName();
|
||||||
|
}
|
||||||
|
|
||||||
void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||||
{
|
{
|
||||||
#if 1
|
|
||||||
|
|
||||||
/*dstream<<"from_inv="<<from_inv<<" to_inv="<<to_inv<<std::endl;
|
|
||||||
dstream<<"from_list="<<from_list<<" to_list="<<to_list<<std::endl;
|
|
||||||
dstream<<"from_i="<<from_i<<" to_i="<<to_i<<std::endl;*/
|
|
||||||
|
|
||||||
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
||||||
Inventory *inv_to = mgr->getInventory(c, to_inv);
|
Inventory *inv_to = mgr->getInventory(c, to_inv);
|
||||||
|
|
||||||
if(!inv_from || !inv_to)
|
if(!inv_from){
|
||||||
{
|
infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
|
||||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||||
<<"(inventories not found or ownership error)"<<std::endl;
|
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!inv_to){
|
||||||
|
infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
|
||||||
|
"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||||
|
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryList *list_from = inv_from->getList(from_list);
|
InventoryList *list_from = inv_from->getList(from_list);
|
||||||
InventoryList *list_to = inv_to->getList(to_list);
|
InventoryList *list_to = inv_to->getList(to_list);
|
||||||
|
|
||||||
/*dstream<<"list_from="<<list_from<<" list_to="<<list_to
|
|
||||||
<<std::endl;*/
|
|
||||||
/*if(list_from)
|
|
||||||
dstream<<" list_from->getItem(from_i)="<<list_from->getItem(from_i)
|
|
||||||
<<std::endl;
|
|
||||||
if(list_to)
|
|
||||||
dstream<<" list_to->getItem(to_i)="<<list_to->getItem(to_i)
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If a list doesn't exist or the source item doesn't exist
|
If a list doesn't exist or the source item doesn't exist
|
||||||
*/
|
*/
|
||||||
if(!list_from || !list_to)
|
if(!list_from){
|
||||||
{
|
infostream<<"IMoveAction::apply(): FAIL: source list not found: "
|
||||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||||
<<"(a list doesn't exist)"
|
<<", from_list=\""<<from_list<<"\""<<std::endl;
|
||||||
<<std::endl;
|
return;
|
||||||
|
}
|
||||||
|
if(!list_to){
|
||||||
|
infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
|
||||||
|
<<"context=["<<describeC(c)<<"], to_inv=\""<<to_inv<<"\""
|
||||||
|
<<", to_list=\""<<to_list<<"\""<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(list_from->getItem(from_i) == NULL)
|
if(list_from->getItem(from_i) == NULL)
|
||||||
{
|
{
|
||||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
infostream<<"IMoveAction::apply(): FAIL: source item not found: "
|
||||||
<<"(the source item doesn't exist)"
|
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||||
<<std::endl;
|
<<", from_list=\""<<from_list<<"\""
|
||||||
|
<<" from_i="<<from_i<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -790,8 +796,9 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||||
*/
|
*/
|
||||||
if(inv_from == inv_to && list_from == list_to && from_i == to_i)
|
if(inv_from == inv_to && list_from == list_to && from_i == to_i)
|
||||||
{
|
{
|
||||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
|
||||||
<<"(source and the destination slots are the same)"<<std::endl;
|
<<"are the same: inv=\""<<from_inv<<"\" list=\""<<from_list
|
||||||
|
<<"\" i="<<from_i<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,7 +839,16 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||||
mgr->inventoryModified(c, from_inv);
|
mgr->inventoryModified(c, from_inv);
|
||||||
if(from_inv != to_inv)
|
if(from_inv != to_inv)
|
||||||
mgr->inventoryModified(c, to_inv);
|
mgr->inventoryModified(c, to_inv);
|
||||||
#endif
|
|
||||||
|
infostream<<"IMoveAction::apply(): moved at "
|
||||||
|
<<"["<<describeC(c)<<"]"
|
||||||
|
<<" from inv=\""<<from_inv<<"\""
|
||||||
|
<<" list=\""<<from_list<<"\""
|
||||||
|
<<" i="<<from_i
|
||||||
|
<<" to inv=\""<<to_inv<<"\""
|
||||||
|
<<" list=\""<<to_list<<"\""
|
||||||
|
<<" i="<<to_i
|
||||||
|
<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
16
src/main.cpp
16
src/main.cpp
|
@ -481,6 +481,8 @@ MainGameCallback *g_gamecallback = NULL;
|
||||||
// Connection
|
// Connection
|
||||||
std::ostream *dout_con_ptr = &dummyout;
|
std::ostream *dout_con_ptr = &dummyout;
|
||||||
std::ostream *derr_con_ptr = &verbosestream;
|
std::ostream *derr_con_ptr = &verbosestream;
|
||||||
|
//std::ostream *dout_con_ptr = &infostream;
|
||||||
|
//std::ostream *derr_con_ptr = &errorstream;
|
||||||
|
|
||||||
// Server
|
// Server
|
||||||
std::ostream *dout_server_ptr = &infostream;
|
std::ostream *dout_server_ptr = &infostream;
|
||||||
|
@ -1074,15 +1076,15 @@ void drawMenuBackground(video::IVideoDriver* driver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DstreamLogOutput: public ILogOutput
|
class StderrLogOutput: public ILogOutput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* line: Full line with timestamp, level and thread */
|
/* line: Full line with timestamp, level and thread */
|
||||||
void printLog(const std::string &line)
|
void printLog(const std::string &line)
|
||||||
{
|
{
|
||||||
dstream<<line<<std::endl;
|
std::cerr<<line<<std::endl;
|
||||||
}
|
}
|
||||||
} main_dstream_log_out;
|
} main_stderr_log_out;
|
||||||
|
|
||||||
class DstreamNoStderrLogOutput: public ILogOutput
|
class DstreamNoStderrLogOutput: public ILogOutput
|
||||||
{
|
{
|
||||||
|
@ -1100,7 +1102,7 @@ int main(int argc, char *argv[])
|
||||||
Initialization
|
Initialization
|
||||||
*/
|
*/
|
||||||
|
|
||||||
log_add_output_maxlev(&main_dstream_log_out, LMT_ACTION);
|
log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION);
|
||||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||||
|
|
||||||
log_register_thread("main");
|
log_register_thread("main");
|
||||||
|
@ -1175,7 +1177,7 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(cmd_args.getFlag("info-on-stderr"))
|
if(cmd_args.getFlag("info-on-stderr"))
|
||||||
log_add_output(&main_dstream_log_out, LMT_INFO);
|
log_add_output(&main_stderr_log_out, LMT_INFO);
|
||||||
|
|
||||||
porting::signal_handler_init();
|
porting::signal_handler_init();
|
||||||
bool &kill = *porting::signal_handler_killstatus();
|
bool &kill = *porting::signal_handler_killstatus();
|
||||||
|
@ -1278,6 +1280,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// Initial call with g_texturesource not set.
|
// Initial call with g_texturesource not set.
|
||||||
init_mapnode();
|
init_mapnode();
|
||||||
|
// Must be called before g_texturesource is created
|
||||||
|
// (for texture atlas making)
|
||||||
|
init_mineral();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Run unit tests
|
Run unit tests
|
||||||
|
@ -1475,7 +1480,6 @@ int main(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_mapnode(); // Second call with g_texturesource set
|
init_mapnode(); // Second call with g_texturesource set
|
||||||
init_mineral();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GUI stuff
|
GUI stuff
|
||||||
|
|
287
src/map.cpp
287
src/map.cpp
|
@ -21,7 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "mapsector.h"
|
#include "mapsector.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#ifndef SERVER
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#endif
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
|
@ -34,6 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#endif
|
#endif
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "profiler.h"
|
||||||
|
|
||||||
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SQLite format specification:
|
SQLite format specification:
|
||||||
|
@ -1833,9 +1838,14 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p)
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
|
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
|
||||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
if(block == NULL)
|
if(!block){
|
||||||
|
infostream<<"Map::getNodeMetadata(): Need to emerge "
|
||||||
|
<<PP(blockpos)<<std::endl;
|
||||||
|
block = emergeBlock(blockpos, false);
|
||||||
|
}
|
||||||
|
if(!block)
|
||||||
{
|
{
|
||||||
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
infostream<<"WARNING: Map::getNodeMetadata(): Block not found"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1848,7 +1858,12 @@ void Map::setNodeMetadata(v3s16 p, NodeMetadata *meta)
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
|
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
|
||||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
if(block == NULL)
|
if(!block){
|
||||||
|
infostream<<"Map::setNodeMetadata(): Need to emerge "
|
||||||
|
<<PP(blockpos)<<std::endl;
|
||||||
|
block = emergeBlock(blockpos, false);
|
||||||
|
}
|
||||||
|
if(!block)
|
||||||
{
|
{
|
||||||
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
@ -2624,152 +2639,6 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Do not generate over-limit
|
|
||||||
*/
|
|
||||||
if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
|
|
||||||
throw InvalidPositionException("emergeBlock(): pos. over limit");
|
|
||||||
|
|
||||||
v2s16 p2d(p.X, p.Z);
|
|
||||||
s16 block_y = p.Y;
|
|
||||||
/*
|
|
||||||
This will create or load a sector if not found in memory.
|
|
||||||
If block exists on disk, it will be loaded.
|
|
||||||
*/
|
|
||||||
ServerMapSector *sector;
|
|
||||||
try{
|
|
||||||
sector = createSector(p2d);
|
|
||||||
//sector = emergeSector(p2d, changed_blocks);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
infostream<<"emergeBlock: createSector() failed: "
|
|
||||||
<<e.what()<<std::endl;
|
|
||||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
|
||||||
<<std::endl
|
|
||||||
<<"You could try to delete it."<<std::endl;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
catch(VersionMismatchException &e)
|
|
||||||
{
|
|
||||||
infostream<<"emergeBlock: createSector() failed: "
|
|
||||||
<<e.what()<<std::endl;
|
|
||||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
|
||||||
<<std::endl
|
|
||||||
<<"You could try to delete it."<<std::endl;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Try to get a block from the sector
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool does_not_exist = false;
|
|
||||||
bool lighting_expired = false;
|
|
||||||
MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
|
|
||||||
|
|
||||||
// If not found, try loading from disk
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
block = loadBlock(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle result
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
does_not_exist = true;
|
|
||||||
}
|
|
||||||
else if(block->isDummy() == true)
|
|
||||||
{
|
|
||||||
does_not_exist = true;
|
|
||||||
}
|
|
||||||
else if(block->getLightingExpired())
|
|
||||||
{
|
|
||||||
lighting_expired = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Valid block
|
|
||||||
//infostream<<"emergeBlock(): Returning already valid block"<<std::endl;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If block was not found on disk and not going to generate a
|
|
||||||
new one, make sure there is a dummy block in place.
|
|
||||||
*/
|
|
||||||
if(only_from_disk && (does_not_exist || lighting_expired))
|
|
||||||
{
|
|
||||||
//infostream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
|
|
||||||
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
// Create dummy block
|
|
||||||
block = new MapBlock(this, p, true);
|
|
||||||
|
|
||||||
// Add block to sector
|
|
||||||
sector->insertBlock(block);
|
|
||||||
}
|
|
||||||
// Done.
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
//infostream<<"Not found on disk, generating."<<std::endl;
|
|
||||||
// 0ms
|
|
||||||
//TimeTaker("emergeBlock() generate");
|
|
||||||
|
|
||||||
//infostream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the block doesn't exist, generate the block.
|
|
||||||
*/
|
|
||||||
if(does_not_exist)
|
|
||||||
{
|
|
||||||
block = generateBlock(p, block, sector, changed_blocks,
|
|
||||||
lighting_invalidated_blocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lighting_expired)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks.insert(p, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Initially update sunlight
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
core::map<v3s16, bool> light_sources;
|
|
||||||
bool black_air_left = false;
|
|
||||||
bool bottom_invalid =
|
|
||||||
block->propagateSunlight(light_sources, true,
|
|
||||||
&black_air_left);
|
|
||||||
|
|
||||||
// If sunlight didn't reach everywhere and part of block is
|
|
||||||
// above ground, lighting has to be properly updated
|
|
||||||
//if(black_air_left && some_part_underground)
|
|
||||||
if(black_air_left)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bottom_invalid)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2868,6 +2737,12 @@ void ServerMap::verifyDatabase() {
|
||||||
throw FileNotGoodException("Cannot prepare write statement");
|
throw FileNotGoodException("Cannot prepare write statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
|
||||||
|
if(d != SQLITE_OK) {
|
||||||
|
infostream<<"WARNING: Database list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||||
|
throw FileNotGoodException("Cannot prepare read statement");
|
||||||
|
}
|
||||||
|
|
||||||
infostream<<"Server: Database opened"<<std::endl;
|
infostream<<"Server: Database opened"<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3040,6 +2915,52 @@ void ServerMap::save(bool only_changed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s32 unsignedToSigned(s32 i, s32 max_positive)
|
||||||
|
{
|
||||||
|
if(i < max_positive)
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
return i - 2*max_positive;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modulo of a negative number does not work consistently in C
|
||||||
|
static sqlite3_int64 pythonmodulo(sqlite3_int64 i, sqlite3_int64 mod)
|
||||||
|
{
|
||||||
|
if(i >= 0)
|
||||||
|
return i % mod;
|
||||||
|
return mod - ((-i) % mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 ServerMap::getIntegerAsBlock(sqlite3_int64 i)
|
||||||
|
{
|
||||||
|
s32 x = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
i = (i - x) / 4096;
|
||||||
|
s32 y = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
i = (i - y) / 4096;
|
||||||
|
s32 z = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
return v3s16(x,y,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerMap::listAllLoadableBlocks(core::list<v3s16> &dst)
|
||||||
|
{
|
||||||
|
if(loadFromFolders()){
|
||||||
|
errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
|
||||||
|
<<"all blocks that are stored in flat files"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
verifyDatabase();
|
||||||
|
|
||||||
|
while(sqlite3_step(m_database_list) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
|
||||||
|
v3s16 p = getIntegerAsBlock(block_i);
|
||||||
|
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
|
||||||
|
dst.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerMap::saveMapMeta()
|
void ServerMap::saveMapMeta()
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -3752,22 +3673,35 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
|
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
|
||||||
|
|
||||||
// Take a fair amount as we will be dropping more out later
|
// Take a fair amount as we will be dropping more out later
|
||||||
|
// Umm... these additions are a bit strange but they are needed.
|
||||||
v3s16 p_blocks_min(
|
v3s16 p_blocks_min(
|
||||||
p_nodes_min.X / MAP_BLOCKSIZE - 2,
|
p_nodes_min.X / MAP_BLOCKSIZE - 3,
|
||||||
p_nodes_min.Y / MAP_BLOCKSIZE - 2,
|
p_nodes_min.Y / MAP_BLOCKSIZE - 3,
|
||||||
p_nodes_min.Z / MAP_BLOCKSIZE - 2);
|
p_nodes_min.Z / MAP_BLOCKSIZE - 3);
|
||||||
v3s16 p_blocks_max(
|
v3s16 p_blocks_max(
|
||||||
p_nodes_max.X / MAP_BLOCKSIZE + 1,
|
p_nodes_max.X / MAP_BLOCKSIZE + 1,
|
||||||
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
||||||
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
||||||
|
|
||||||
u32 vertex_count = 0;
|
u32 vertex_count = 0;
|
||||||
|
u32 meshbuffer_count = 0;
|
||||||
|
|
||||||
// For limiting number of mesh updates per frame
|
// For limiting number of mesh updates per frame
|
||||||
u32 mesh_update_count = 0;
|
u32 mesh_update_count = 0;
|
||||||
|
|
||||||
|
// Number of blocks in rendering range
|
||||||
|
u32 blocks_in_range = 0;
|
||||||
|
// Number of blocks in rendering range but don't have a mesh
|
||||||
|
u32 blocks_in_range_without_mesh = 0;
|
||||||
|
// Blocks that had mesh that would have been drawn according to
|
||||||
|
// rendering range (if max blocks limit didn't kick in)
|
||||||
u32 blocks_would_have_drawn = 0;
|
u32 blocks_would_have_drawn = 0;
|
||||||
|
// Blocks that were drawn and had a mesh
|
||||||
u32 blocks_drawn = 0;
|
u32 blocks_drawn = 0;
|
||||||
|
// Blocks which had a corresponding meshbuffer for this pass
|
||||||
|
u32 blocks_had_pass_meshbuf = 0;
|
||||||
|
// Blocks from which stuff was actually drawn
|
||||||
|
u32 blocks_without_stuff = 0;
|
||||||
|
|
||||||
int timecheck_counter = 0;
|
int timecheck_counter = 0;
|
||||||
core::map<v2s16, MapSector*>::Iterator si;
|
core::map<v2s16, MapSector*>::Iterator si;
|
||||||
|
@ -3840,6 +3774,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
/*if(m_control.range_all == false &&
|
/*if(m_control.range_all == false &&
|
||||||
d - 0.5*BS*MAP_BLOCKSIZE > range)
|
d - 0.5*BS*MAP_BLOCKSIZE > range)
|
||||||
continue;*/
|
continue;*/
|
||||||
|
|
||||||
|
blocks_in_range++;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/*
|
/*
|
||||||
|
@ -3858,8 +3794,10 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
|
|
||||||
// Mesh has not been expired and there is no mesh:
|
// Mesh has not been expired and there is no mesh:
|
||||||
// block has no content
|
// block has no content
|
||||||
if(block->mesh == NULL && mesh_expired == false)
|
if(block->mesh == NULL && mesh_expired == false){
|
||||||
|
blocks_in_range_without_mesh++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 faraway = BS*50;
|
f32 faraway = BS*50;
|
||||||
|
@ -3897,9 +3835,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
JMutexAutoLock lock(block->mesh_mutex);
|
JMutexAutoLock lock(block->mesh_mutex);
|
||||||
|
|
||||||
scene::SMesh *mesh = block->mesh;
|
scene::SMesh *mesh = block->mesh;
|
||||||
|
|
||||||
if(mesh == NULL)
|
if(mesh == NULL){
|
||||||
|
blocks_in_range_without_mesh++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
blocks_would_have_drawn++;
|
blocks_would_have_drawn++;
|
||||||
if(blocks_drawn >= m_control.wanted_max_blocks
|
if(blocks_drawn >= m_control.wanted_max_blocks
|
||||||
|
@ -3911,7 +3851,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
sector_blocks_drawn++;
|
sector_blocks_drawn++;
|
||||||
|
|
||||||
u32 c = mesh->getMeshBufferCount();
|
u32 c = mesh->getMeshBufferCount();
|
||||||
|
bool stuff_actually_drawn = false;
|
||||||
for(u32 i=0; i<c; i++)
|
for(u32 i=0; i<c; i++)
|
||||||
{
|
{
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||||
|
@ -3922,16 +3862,25 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
// Render transparent on transparent pass and likewise.
|
// Render transparent on transparent pass and likewise.
|
||||||
if(transparent == is_transparent_pass)
|
if(transparent == is_transparent_pass)
|
||||||
{
|
{
|
||||||
|
if(buf->getVertexCount() == 0)
|
||||||
|
errorstream<<"Block ["<<analyze_block(block)
|
||||||
|
<<"] contains an empty meshbuf"<<std::endl;
|
||||||
/*
|
/*
|
||||||
This *shouldn't* hurt too much because Irrlicht
|
This *shouldn't* hurt too much because Irrlicht
|
||||||
doesn't change opengl textures if the old
|
doesn't change opengl textures if the old
|
||||||
material is set again.
|
material has the same texture.
|
||||||
*/
|
*/
|
||||||
driver->setMaterial(buf->getMaterial());
|
driver->setMaterial(buf->getMaterial());
|
||||||
driver->drawMeshBuffer(buf);
|
driver->drawMeshBuffer(buf);
|
||||||
vertex_count += buf->getVertexCount();
|
vertex_count += buf->getVertexCount();
|
||||||
|
meshbuffer_count++;
|
||||||
|
stuff_actually_drawn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(stuff_actually_drawn)
|
||||||
|
blocks_had_pass_meshbuf++;
|
||||||
|
else
|
||||||
|
blocks_without_stuff++;
|
||||||
}
|
}
|
||||||
} // foreach sectorblocks
|
} // foreach sectorblocks
|
||||||
|
|
||||||
|
@ -3941,6 +3890,30 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string prefix = "CM: ";
|
||||||
|
|
||||||
|
// Log only on solid pass because values are the same
|
||||||
|
if(pass == scene::ESNRP_SOLID){
|
||||||
|
g_profiler->avg(prefix+"blocks in range", blocks_in_range);
|
||||||
|
if(blocks_in_range != 0)
|
||||||
|
g_profiler->avg(prefix+"blocks in range without mesh (frac)",
|
||||||
|
(float)blocks_in_range_without_mesh/blocks_in_range);
|
||||||
|
g_profiler->avg(prefix+"blocks drawn", blocks_drawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pass == scene::ESNRP_SOLID)
|
||||||
|
prefix = "CM: solid: ";
|
||||||
|
else
|
||||||
|
prefix = "CM: transparent: ";
|
||||||
|
|
||||||
|
g_profiler->avg(prefix+"vertices drawn", vertex_count);
|
||||||
|
if(blocks_had_pass_meshbuf != 0)
|
||||||
|
g_profiler->avg(prefix+"meshbuffers per block",
|
||||||
|
(float)meshbuffer_count / (float)blocks_had_pass_meshbuf);
|
||||||
|
if(blocks_drawn != 0)
|
||||||
|
g_profiler->avg(prefix+"empty blocks (frac)",
|
||||||
|
(float)blocks_without_stuff / blocks_drawn);
|
||||||
|
|
||||||
m_control.blocks_drawn = blocks_drawn;
|
m_control.blocks_drawn = blocks_drawn;
|
||||||
m_control.blocks_would_have_drawn = blocks_would_have_drawn;
|
m_control.blocks_would_have_drawn = blocks_would_have_drawn;
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,10 @@ public:
|
||||||
// Returns NULL if not found
|
// Returns NULL if not found
|
||||||
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
||||||
|
|
||||||
|
/* Server overrides */
|
||||||
|
virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true)
|
||||||
|
{ return getBlockNoCreateNoEx(p); }
|
||||||
|
|
||||||
// Returns InvalidPositionException if not found
|
// Returns InvalidPositionException if not found
|
||||||
bool isNodeUnderground(v3s16 p);
|
bool isNodeUnderground(v3s16 p);
|
||||||
|
|
||||||
|
@ -379,6 +383,7 @@ public:
|
||||||
void verifyDatabase();
|
void verifyDatabase();
|
||||||
// Get an integer suitable for a block
|
// Get an integer suitable for a block
|
||||||
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
|
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
|
||||||
|
static v3s16 getIntegerAsBlock(sqlite3_int64 i);
|
||||||
|
|
||||||
// Returns true if the database file does not exist
|
// Returns true if the database file does not exist
|
||||||
bool loadFromFolders();
|
bool loadFromFolders();
|
||||||
|
@ -390,6 +395,8 @@ public:
|
||||||
void save(bool only_changed);
|
void save(bool only_changed);
|
||||||
//void loadAll();
|
//void loadAll();
|
||||||
|
|
||||||
|
void listAllLoadableBlocks(core::list<v3s16> &dst);
|
||||||
|
|
||||||
// Saves map seed and possibly other stuff
|
// Saves map seed and possibly other stuff
|
||||||
void saveMapMeta();
|
void saveMapMeta();
|
||||||
void loadMapMeta();
|
void loadMapMeta();
|
||||||
|
@ -454,6 +461,7 @@ private:
|
||||||
sqlite3 *m_database;
|
sqlite3 *m_database;
|
||||||
sqlite3_stmt *m_database_read;
|
sqlite3_stmt *m_database_read;
|
||||||
sqlite3_stmt *m_database_write;
|
sqlite3_stmt *m_database_write;
|
||||||
|
sqlite3_stmt *m_database_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "main.h" // For g_settings and g_texturesource
|
#include "main.h" // For g_settings and g_texturesource
|
||||||
#include "content_mapblock.h"
|
#include "content_mapblock.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "profiler.h"
|
||||||
|
|
||||||
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||||
{
|
{
|
||||||
|
@ -527,7 +528,7 @@ void updateFastFaceRow(
|
||||||
next_tile);
|
next_tile);
|
||||||
|
|
||||||
if(next_makes_face == makes_face
|
if(next_makes_face == makes_face
|
||||||
&& next_p_corrected == p_corrected
|
&& next_p_corrected == p_corrected + translate_dir
|
||||||
&& next_face_dir_corrected == face_dir_corrected
|
&& next_face_dir_corrected == face_dir_corrected
|
||||||
&& next_lights[0] == lights[0]
|
&& next_lights[0] == lights[0]
|
||||||
&& next_lights[1] == lights[1]
|
&& next_lights[1] == lights[1]
|
||||||
|
@ -537,6 +538,29 @@ void updateFastFaceRow(
|
||||||
{
|
{
|
||||||
next_is_different = false;
|
next_is_different = false;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
/*if(makes_face){
|
||||||
|
g_profiler->add("Meshgen: diff: next_makes_face != makes_face",
|
||||||
|
next_makes_face != makes_face ? 1 : 0);
|
||||||
|
g_profiler->add("Meshgen: diff: n_p_corr != p_corr + t_dir",
|
||||||
|
(next_p_corrected != p_corrected + translate_dir) ? 1 : 0);
|
||||||
|
g_profiler->add("Meshgen: diff: next_f_dir_corr != f_dir_corr",
|
||||||
|
next_face_dir_corrected != face_dir_corrected ? 1 : 0);
|
||||||
|
g_profiler->add("Meshgen: diff: next_lights[] != lights[]",
|
||||||
|
(next_lights[0] != lights[0] ||
|
||||||
|
next_lights[0] != lights[0] ||
|
||||||
|
next_lights[0] != lights[0] ||
|
||||||
|
next_lights[0] != lights[0]) ? 1 : 0);
|
||||||
|
g_profiler->add("Meshgen: diff: !(next_tile == tile)",
|
||||||
|
!(next_tile == tile) ? 1 : 0);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
/*g_profiler->add("Meshgen: Total faces checked", 1);
|
||||||
|
if(makes_face)
|
||||||
|
g_profiler->add("Meshgen: Total makes_face checked", 1);*/
|
||||||
|
} else {
|
||||||
|
/*if(makes_face)
|
||||||
|
g_profiler->add("Meshgen: diff: last position", 1);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
continuous_tiles_count++;
|
continuous_tiles_count++;
|
||||||
|
@ -568,6 +592,8 @@ void updateFastFaceRow(
|
||||||
v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
|
v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
|
||||||
// Center point of face (kind of)
|
// Center point of face (kind of)
|
||||||
v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f;
|
v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f;
|
||||||
|
if(continuous_tiles_count != 1)
|
||||||
|
sp += translate_dir_f;
|
||||||
v3f scale(1,1,1);
|
v3f scale(1,1,1);
|
||||||
|
|
||||||
if(translate_dir.X != 0)
|
if(translate_dir.X != 0)
|
||||||
|
@ -586,6 +612,11 @@ void updateFastFaceRow(
|
||||||
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
||||||
sp, face_dir_corrected, scale,
|
sp, face_dir_corrected, scale,
|
||||||
posRelative_f, dest);
|
posRelative_f, dest);
|
||||||
|
|
||||||
|
g_profiler->avg("Meshgen: faces drawn by tiling", 0);
|
||||||
|
for(int i=1; i<continuous_tiles_count; i++){
|
||||||
|
g_profiler->avg("Meshgen: faces drawn by tiling", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continuous_tiles_count = 0;
|
continuous_tiles_count = 0;
|
||||||
|
@ -707,10 +738,13 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
|
||||||
|
|
||||||
video::SMaterial material;
|
video::SMaterial material;
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
|
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
|
||||||
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
|
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
|
||||||
|
material.MaterialType
|
||||||
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
|
||||||
for(u32 i=0; i<fastfaces_new.size(); i++)
|
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,8 @@ ContentFeatures::~ContentFeatures()
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
|
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
|
||||||
{
|
{
|
||||||
|
used_texturenames[name] = true;
|
||||||
|
|
||||||
if(g_texturesource)
|
if(g_texturesource)
|
||||||
{
|
{
|
||||||
tiles[i].texture = g_texturesource->getTexture(name);
|
tiles[i].texture = g_texturesource->getTexture(name);
|
||||||
|
|
|
@ -124,6 +124,10 @@ struct ContentFeatures
|
||||||
AtlasPointer *special_atlas;
|
AtlasPointer *special_atlas;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// List of all block textures that have been used (value is dummy)
|
||||||
|
// Exists on server too for cleaner code in content_mapnode.cpp
|
||||||
|
core::map<std::string, bool> used_texturenames;
|
||||||
|
|
||||||
// Type of MapNode::param1
|
// Type of MapNode::param1
|
||||||
ContentParamType param_type;
|
ContentParamType param_type;
|
||||||
// True for all ground-like things like stone and mud, false for eg. trees
|
// True for all ground-like things like stone and mud, false for eg. trees
|
||||||
|
@ -151,6 +155,10 @@ struct ContentFeatures
|
||||||
// If true, node is equivalent to air. Torches are, air is. Water is not.
|
// If true, node is equivalent to air. Torches are, air is. Water is not.
|
||||||
// Is used for example to check whether a mud block can have grass on.
|
// Is used for example to check whether a mud block can have grass on.
|
||||||
bool air_equivalent;
|
bool air_equivalent;
|
||||||
|
// Whether this content type often contains mineral.
|
||||||
|
// Used for texture atlas creation.
|
||||||
|
// Currently only enabled for CONTENT_STONE.
|
||||||
|
bool often_contains_mineral;
|
||||||
|
|
||||||
// Inventory item string as which the node appears in inventory when dug.
|
// Inventory item string as which the node appears in inventory when dug.
|
||||||
// Mineral overrides this.
|
// Mineral overrides this.
|
||||||
|
@ -207,6 +215,7 @@ struct ContentFeatures
|
||||||
liquid_type = LIQUID_NONE;
|
liquid_type = LIQUID_NONE;
|
||||||
wall_mounted = false;
|
wall_mounted = false;
|
||||||
air_equivalent = false;
|
air_equivalent = false;
|
||||||
|
often_contains_mineral = false;
|
||||||
dug_item = "";
|
dug_item = "";
|
||||||
initial_metadata = NULL;
|
initial_metadata = NULL;
|
||||||
liquid_alternative_flowing = CONTENT_IGNORE;
|
liquid_alternative_flowing = CONTENT_IGNORE;
|
||||||
|
|
|
@ -41,28 +41,48 @@ public:
|
||||||
void add(const std::string &name, float value)
|
void add(const std::string &name, float value)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
JMutexAutoLock lock(m_mutex);
|
||||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
|
||||||
if(n == NULL)
|
|
||||||
{
|
{
|
||||||
m_data[name] = value;
|
/* No average shall have been used; mark add used as -2 */
|
||||||
|
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||||
|
if(n == NULL)
|
||||||
|
m_avgcounts[name] = -2;
|
||||||
|
else{
|
||||||
|
if(n->getValue() == -1)
|
||||||
|
n->setValue(-2);
|
||||||
|
assert(n->getValue() == -2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
{
|
||||||
n->setValue(n->getValue() + value);
|
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||||
|
if(n == NULL)
|
||||||
|
m_data[name] = value;
|
||||||
|
else
|
||||||
|
n->setValue(n->getValue() + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lowpass(const std::string &name, float value, float factor)
|
void avg(const std::string &name, float value)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
JMutexAutoLock lock(m_mutex);
|
||||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
|
||||||
if(n == NULL)
|
|
||||||
{
|
{
|
||||||
m_data[name] = value;
|
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||||
|
if(n == NULL)
|
||||||
|
m_avgcounts[name] = 1;
|
||||||
|
else{
|
||||||
|
/* No add shall have been used */
|
||||||
|
assert(n->getValue() != -2);
|
||||||
|
if(n->getValue() <= 0)
|
||||||
|
n->setValue(1);
|
||||||
|
else
|
||||||
|
n->setValue(n->getValue() + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
{
|
||||||
n->setValue(n->getValue() * (1.0 - 1.0/factor) + value / factor);
|
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||||
|
if(n == NULL)
|
||||||
|
m_data[name] = value;
|
||||||
|
else
|
||||||
|
n->setValue(n->getValue() + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +95,7 @@ public:
|
||||||
{
|
{
|
||||||
i.getNode()->setValue(0);
|
i.getNode()->setValue(0);
|
||||||
}
|
}
|
||||||
|
m_avgcounts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream &o)
|
void print(std::ostream &o)
|
||||||
|
@ -85,6 +106,12 @@ public:
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
std::string name = i.getNode()->getKey();
|
std::string name = i.getNode()->getKey();
|
||||||
|
int avgcount = 1;
|
||||||
|
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||||
|
if(n){
|
||||||
|
if(n->getValue() >= 1)
|
||||||
|
avgcount = n->getValue();
|
||||||
|
}
|
||||||
o<<" "<<name<<": ";
|
o<<" "<<name<<": ";
|
||||||
s32 clampsize = 40;
|
s32 clampsize = 40;
|
||||||
s32 space = clampsize - name.size();
|
s32 space = clampsize - name.size();
|
||||||
|
@ -95,7 +122,7 @@ public:
|
||||||
else
|
else
|
||||||
o<<" ";
|
o<<" ";
|
||||||
}
|
}
|
||||||
o<<i.getNode()->getValue();
|
o<<(i.getNode()->getValue() / avgcount);
|
||||||
o<<std::endl;
|
o<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,11 +130,12 @@ public:
|
||||||
private:
|
private:
|
||||||
JMutex m_mutex;
|
JMutex m_mutex;
|
||||||
core::map<std::string, float> m_data;
|
core::map<std::string, float> m_data;
|
||||||
|
core::map<std::string, int> m_avgcounts;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ScopeProfilerType{
|
enum ScopeProfilerType{
|
||||||
SPT_ADD,
|
SPT_ADD,
|
||||||
SPT_LOWPASS
|
SPT_AVG
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopeProfiler
|
class ScopeProfiler
|
||||||
|
@ -138,14 +166,15 @@ public:
|
||||||
{
|
{
|
||||||
if(m_timer)
|
if(m_timer)
|
||||||
{
|
{
|
||||||
u32 duration = m_timer->stop(true);
|
float duration_ms = m_timer->stop(true);
|
||||||
|
float duration = duration_ms / 1000.0;
|
||||||
if(m_profiler){
|
if(m_profiler){
|
||||||
switch(m_type){
|
switch(m_type){
|
||||||
case SPT_ADD:
|
case SPT_ADD:
|
||||||
m_profiler->add(m_name, duration);
|
m_profiler->add(m_name, duration);
|
||||||
break;
|
break;
|
||||||
case SPT_LOWPASS:
|
case SPT_AVG:
|
||||||
m_profiler->lowpass(m_name, duration, 20.0);
|
m_profiler->avg(m_name, duration);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
181
src/server.cpp
181
src/server.cpp
|
@ -354,11 +354,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
|
|
||||||
// Increment timers
|
// Increment timers
|
||||||
m_nothing_to_send_pause_timer -= dtime;
|
m_nothing_to_send_pause_timer -= dtime;
|
||||||
|
m_nearest_unsent_reset_timer += dtime;
|
||||||
|
|
||||||
if(m_nothing_to_send_pause_timer >= 0)
|
if(m_nothing_to_send_pause_timer >= 0)
|
||||||
{
|
{
|
||||||
// Keep this reset
|
|
||||||
m_nearest_unsent_reset_timer = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,17 +409,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
/*infostream<<"m_nearest_unsent_reset_timer="
|
/*infostream<<"m_nearest_unsent_reset_timer="
|
||||||
<<m_nearest_unsent_reset_timer<<std::endl;*/
|
<<m_nearest_unsent_reset_timer<<std::endl;*/
|
||||||
|
|
||||||
// This has to be incremented only when the nothing to send pause
|
// Reset periodically to workaround for some bugs or stuff
|
||||||
// is not active
|
if(m_nearest_unsent_reset_timer > 20.0)
|
||||||
m_nearest_unsent_reset_timer += dtime;
|
|
||||||
|
|
||||||
// Reset periodically to avoid possible bugs or other mishaps
|
|
||||||
if(m_nearest_unsent_reset_timer > 10.0)
|
|
||||||
{
|
{
|
||||||
m_nearest_unsent_reset_timer = 0;
|
m_nearest_unsent_reset_timer = 0;
|
||||||
m_nearest_unsent_d = 0;
|
m_nearest_unsent_d = 0;
|
||||||
/*infostream<<"Resetting m_nearest_unsent_d for "
|
//infostream<<"Resetting m_nearest_unsent_d for "
|
||||||
<<server->getPlayerName(peer_id)<<std::endl;*/
|
// <<server->getPlayerName(peer_id)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//s16 last_nearest_unsent_d = m_nearest_unsent_d;
|
//s16 last_nearest_unsent_d = m_nearest_unsent_d;
|
||||||
|
@ -463,22 +458,24 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
|
s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
|
||||||
|
|
||||||
// Don't loop very much at a time
|
// Don't loop very much at a time
|
||||||
if(d_max > d_start+1)
|
s16 max_d_increment_at_time = 2;
|
||||||
d_max = d_start+1;
|
if(d_max > d_start + max_d_increment_at_time)
|
||||||
|
d_max = d_start + max_d_increment_at_time;
|
||||||
/*if(d_max_gen > d_start+2)
|
/*if(d_max_gen > d_start+2)
|
||||||
d_max_gen = d_start+2;*/
|
d_max_gen = d_start+2;*/
|
||||||
|
|
||||||
//infostream<<"Starting from "<<d_start<<std::endl;
|
//infostream<<"Starting from "<<d_start<<std::endl;
|
||||||
|
|
||||||
bool sending_something = false;
|
s32 nearest_emerged_d = -1;
|
||||||
|
s32 nearest_emergefull_d = -1;
|
||||||
bool no_blocks_found_for_sending = true;
|
s32 nearest_sent_d = -1;
|
||||||
|
|
||||||
bool queue_is_full = false;
|
bool queue_is_full = false;
|
||||||
|
|
||||||
s16 d;
|
s16 d;
|
||||||
for(d = d_start; d <= d_max; d++)
|
for(d = d_start; d <= d_max; d++)
|
||||||
{
|
{
|
||||||
|
/*errorstream<<"checking d="<<d<<" for "
|
||||||
|
<<server->getPlayerName(peer_id)<<std::endl;*/
|
||||||
//infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
|
//infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -550,12 +547,12 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
|
if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
|
||||||
generate = false;*/
|
generate = false;*/
|
||||||
|
|
||||||
// Limit the send area vertically to 2/3
|
// Limit the send area vertically to 1/2
|
||||||
if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
|
if(abs(p.Y - center.Y) > d_max / 2)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
/*
|
/*
|
||||||
If block is far away, don't generate it unless it is
|
If block is far away, don't generate it unless it is
|
||||||
near ground level.
|
near ground level.
|
||||||
|
@ -588,7 +585,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//infostream<<"d="<<d<<std::endl;
|
//infostream<<"d="<<d<<std::endl;
|
||||||
|
#if 1
|
||||||
/*
|
/*
|
||||||
Don't generate or send if not in sight
|
Don't generate or send if not in sight
|
||||||
FIXME This only works if the client uses a small enough
|
FIXME This only works if the client uses a small enough
|
||||||
|
@ -600,7 +597,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
Don't send already sent blocks
|
Don't send already sent blocks
|
||||||
*/
|
*/
|
||||||
|
@ -658,7 +655,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
Block is near ground level if night-time mesh
|
Block is near ground level if night-time mesh
|
||||||
differs from day-time mesh.
|
differs from day-time mesh.
|
||||||
*/
|
*/
|
||||||
if(d > 3)
|
if(d >= 4)
|
||||||
{
|
{
|
||||||
if(block->dayNightDiffed() == false)
|
if(block->dayNightDiffed() == false)
|
||||||
continue;
|
continue;
|
||||||
|
@ -676,18 +673,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Record the lowest d from which a block has been
|
|
||||||
found being not sent and possibly to exist
|
|
||||||
*/
|
|
||||||
if(no_blocks_found_for_sending)
|
|
||||||
{
|
|
||||||
if(generate == true)
|
|
||||||
new_nearest_unsent_d = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
no_blocks_found_for_sending = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add inexistent block to emerge queue.
|
Add inexistent block to emerge queue.
|
||||||
*/
|
*/
|
||||||
|
@ -697,7 +682,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
// Allow only one block in emerge queue
|
// Allow only one block in emerge queue
|
||||||
//if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
//if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
||||||
// Allow two blocks in queue per client
|
// Allow two blocks in queue per client
|
||||||
if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
|
//if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
|
||||||
|
if(server->m_emerge_queue.peerItemCount(peer_id) < 25)
|
||||||
{
|
{
|
||||||
//infostream<<"Adding block to emerge queue"<<std::endl;
|
//infostream<<"Adding block to emerge queue"<<std::endl;
|
||||||
|
|
||||||
|
@ -709,55 +695,63 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
|
|
||||||
server->m_emerge_queue.addBlock(peer_id, p, flags);
|
server->m_emerge_queue.addBlock(peer_id, p, flags);
|
||||||
server->m_emergethread.trigger();
|
server->m_emergethread.trigger();
|
||||||
|
|
||||||
|
if(nearest_emerged_d == -1)
|
||||||
|
nearest_emerged_d = d;
|
||||||
|
} else {
|
||||||
|
if(nearest_emergefull_d == -1)
|
||||||
|
nearest_emergefull_d = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get next one.
|
// get next one.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nearest_sent_d == -1)
|
||||||
|
nearest_sent_d = d;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add block to send queue
|
Add block to send queue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*errorstream<<"sending from d="<<d<<" to "
|
||||||
|
<<server->getPlayerName(peer_id)<<std::endl;*/
|
||||||
|
|
||||||
PrioritySortedBlockTransfer q((float)d, p, peer_id);
|
PrioritySortedBlockTransfer q((float)d, p, peer_id);
|
||||||
|
|
||||||
dest.push_back(q);
|
dest.push_back(q);
|
||||||
|
|
||||||
num_blocks_selected += 1;
|
num_blocks_selected += 1;
|
||||||
sending_something = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue_full_break:
|
queue_full_break:
|
||||||
|
|
||||||
//infostream<<"Stopped at "<<d<<std::endl;
|
//infostream<<"Stopped at "<<d<<std::endl;
|
||||||
|
|
||||||
if(no_blocks_found_for_sending)
|
// If nothing was found for sending and nothing was queued for
|
||||||
{
|
// emerging, continue next time browsing from here
|
||||||
if(queue_is_full == false)
|
if(nearest_emerged_d != -1){
|
||||||
new_nearest_unsent_d = d;
|
new_nearest_unsent_d = nearest_emerged_d;
|
||||||
|
} else if(nearest_emergefull_d != -1){
|
||||||
|
new_nearest_unsent_d = nearest_emergefull_d;
|
||||||
|
} else {
|
||||||
|
if(d > g_settings->getS16("max_block_send_distance")){
|
||||||
|
new_nearest_unsent_d = 0;
|
||||||
|
m_nothing_to_send_pause_timer = 2.0;
|
||||||
|
/*infostream<<"GetNextBlocks(): d wrapped around for "
|
||||||
|
<<server->getPlayerName(peer_id)
|
||||||
|
<<"; setting to 0 and pausing"<<std::endl;*/
|
||||||
|
} else {
|
||||||
|
if(nearest_sent_d != -1)
|
||||||
|
new_nearest_unsent_d = nearest_sent_d;
|
||||||
|
else
|
||||||
|
new_nearest_unsent_d = d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(new_nearest_unsent_d != -1)
|
if(new_nearest_unsent_d != -1)
|
||||||
m_nearest_unsent_d = new_nearest_unsent_d;
|
m_nearest_unsent_d = new_nearest_unsent_d;
|
||||||
|
|
||||||
if(sending_something == false)
|
|
||||||
{
|
|
||||||
m_nothing_to_send_counter++;
|
|
||||||
if((s16)m_nothing_to_send_counter >=
|
|
||||||
g_settings->getS16("max_block_send_distance"))
|
|
||||||
{
|
|
||||||
// Pause time in seconds
|
|
||||||
m_nothing_to_send_pause_timer = 1.0;
|
|
||||||
/*infostream<<"nothing to send to "
|
|
||||||
<<server->getPlayerName(peer_id)
|
|
||||||
<<" (d="<<d<<")"<<std::endl;*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_nothing_to_send_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*timer_result = timer.stop(true);
|
/*timer_result = timer.stop(true);
|
||||||
if(timer_result != 0)
|
if(timer_result != 0)
|
||||||
infostream<<"GetNextBlocks duration: "<<timer_result<<" (!=0)"<<std::endl;*/
|
infostream<<"GetNextBlocks duration: "<<timer_result<<" (!=0)"<<std::endl;*/
|
||||||
|
@ -1080,7 +1074,7 @@ void Server::start(unsigned short port)
|
||||||
m_thread.stop();
|
m_thread.stop();
|
||||||
|
|
||||||
// Initialize connection
|
// Initialize connection
|
||||||
m_con.setTimeoutMs(30);
|
m_con.SetTimeoutMs(30);
|
||||||
m_con.Serve(port);
|
m_con.Serve(port);
|
||||||
|
|
||||||
// Start thread
|
// Start thread
|
||||||
|
@ -1214,7 +1208,7 @@ void Server::AsyncRunStep()
|
||||||
JMutexAutoLock lock(m_env_mutex);
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
// Step environment
|
// Step environment
|
||||||
ScopeProfiler sp(g_profiler, "SEnv step");
|
ScopeProfiler sp(g_profiler, "SEnv step");
|
||||||
ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_LOWPASS);
|
ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
|
||||||
m_env.step(dtime);
|
m_env.step(dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,7 +1464,7 @@ void Server::AsyncRunStep()
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
JMutexAutoLock conlock(m_con_mutex);
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "Server: sending object messages");
|
//ScopeProfiler sp(g_profiler, "Server: sending object messages");
|
||||||
|
|
||||||
// Key = object id
|
// Key = object id
|
||||||
// Value = data sent by object
|
// Value = data sent by object
|
||||||
|
@ -1710,7 +1704,7 @@ void Server::AsyncRunStep()
|
||||||
JMutexAutoLock lock1(m_env_mutex);
|
JMutexAutoLock lock1(m_env_mutex);
|
||||||
JMutexAutoLock lock2(m_con_mutex);
|
JMutexAutoLock lock2(m_con_mutex);
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "Server: sending player positions");
|
//ScopeProfiler sp(g_profiler, "Server: sending player positions");
|
||||||
|
|
||||||
SendObjectData(counter);
|
SendObjectData(counter);
|
||||||
|
|
||||||
|
@ -1829,9 +1823,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
JMutexAutoLock conlock(m_con_mutex);
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
|
||||||
con::Peer *peer;
|
|
||||||
try{
|
try{
|
||||||
peer = m_con.GetPeer(peer_id);
|
Address address = m_con.GetPeerAddress(peer_id);
|
||||||
|
|
||||||
|
// drop player if is ip is banned
|
||||||
|
if(m_banmanager.isIpBanned(address.serializeString())){
|
||||||
|
SendAccessDenied(m_con, peer_id,
|
||||||
|
L"Your ip is banned. Banned name was "
|
||||||
|
+narrow_to_wide(m_banmanager.getBanName(
|
||||||
|
address.serializeString())));
|
||||||
|
m_con.DeletePeer(peer_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(con::PeerNotFoundException &e)
|
catch(con::PeerNotFoundException &e)
|
||||||
{
|
{
|
||||||
|
@ -1840,17 +1843,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop player if is ip is banned
|
u8 peer_ser_ver = getClient(peer_id)->serialization_version;
|
||||||
if(m_banmanager.isIpBanned(peer->address.serializeString())){
|
|
||||||
SendAccessDenied(m_con, peer_id,
|
|
||||||
L"Your ip is banned. Banned name was "
|
|
||||||
+narrow_to_wide(m_banmanager.getBanName(
|
|
||||||
peer->address.serializeString())));
|
|
||||||
m_con.deletePeer(peer_id, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 peer_ser_ver = getClient(peer->id)->serialization_version;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1871,7 +1864,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
infostream<<"Server: Got TOSERVER_INIT from "
|
infostream<<"Server: Got TOSERVER_INIT from "
|
||||||
<<peer->id<<std::endl;
|
<<peer_id<<std::endl;
|
||||||
|
|
||||||
// First byte after command is maximum supported
|
// First byte after command is maximum supported
|
||||||
// serialization version
|
// serialization version
|
||||||
|
@ -1884,7 +1877,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
deployed = SER_FMT_VER_INVALID;
|
deployed = SER_FMT_VER_INVALID;
|
||||||
|
|
||||||
//peer->serialization_version = deployed;
|
//peer->serialization_version = deployed;
|
||||||
getClient(peer->id)->pending_serialization_version = deployed;
|
getClient(peer_id)->pending_serialization_version = deployed;
|
||||||
|
|
||||||
if(deployed == SER_FMT_VER_INVALID)
|
if(deployed == SER_FMT_VER_INVALID)
|
||||||
{
|
{
|
||||||
|
@ -1906,7 +1899,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
|
net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
getClient(peer->id)->net_proto_version = net_proto_version;
|
getClient(peer_id)->net_proto_version = net_proto_version;
|
||||||
|
|
||||||
if(net_proto_version == 0)
|
if(net_proto_version == 0)
|
||||||
{
|
{
|
||||||
|
@ -2051,11 +2044,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
if(command == TOSERVER_INIT2)
|
if(command == TOSERVER_INIT2)
|
||||||
{
|
{
|
||||||
infostream<<"Server: Got TOSERVER_INIT2 from "
|
infostream<<"Server: Got TOSERVER_INIT2 from "
|
||||||
<<peer->id<<std::endl;
|
<<peer_id<<std::endl;
|
||||||
|
|
||||||
|
|
||||||
getClient(peer->id)->serialization_version
|
getClient(peer_id)->serialization_version
|
||||||
= getClient(peer->id)->pending_serialization_version;
|
= getClient(peer_id)->pending_serialization_version;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send some initialization data
|
Send some initialization data
|
||||||
|
@ -2065,8 +2058,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
SendPlayerInfos();
|
SendPlayerInfos();
|
||||||
|
|
||||||
// Send inventory to player
|
// Send inventory to player
|
||||||
UpdateCrafting(peer->id);
|
UpdateCrafting(peer_id);
|
||||||
SendInventory(peer->id);
|
SendInventory(peer_id);
|
||||||
|
|
||||||
// Send player items to all players
|
// Send player items to all players
|
||||||
SendPlayerItems();
|
SendPlayerItems();
|
||||||
|
@ -2082,7 +2075,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
{
|
{
|
||||||
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
|
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
|
||||||
m_env.getTimeOfDay());
|
m_env.getTimeOfDay());
|
||||||
m_con.Send(peer->id, 0, data, true);
|
m_con.Send(peer_id, 0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send information about server to player in chat
|
// Send information about server to player in chat
|
||||||
|
@ -2103,7 +2096,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnings about protocol version can be issued here
|
// Warnings about protocol version can be issued here
|
||||||
if(getClient(peer->id)->net_proto_version < PROTOCOL_VERSION)
|
if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
|
||||||
{
|
{
|
||||||
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
|
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
|
||||||
}
|
}
|
||||||
|
@ -2445,7 +2438,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
else if(action == 2)
|
else if(action == 2)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
RemoteClient *client = getClient(peer->id);
|
RemoteClient *client = getClient(peer_id);
|
||||||
JMutexAutoLock digmutex(client->m_dig_mutex);
|
JMutexAutoLock digmutex(client->m_dig_mutex);
|
||||||
client->m_dig_tool_item = -1;
|
client->m_dig_tool_item = -1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2728,7 +2721,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset build time counter
|
// Reset build time counter
|
||||||
getClient(peer->id)->m_time_from_building = 0.0;
|
getClient(peer_id)->m_time_from_building = 0.0;
|
||||||
|
|
||||||
// Create node data
|
// Create node data
|
||||||
MaterialItem *mitem = (MaterialItem*)item;
|
MaterialItem *mitem = (MaterialItem*)item;
|
||||||
|
@ -3539,11 +3532,10 @@ core::list<PlayerInfo> Server::getPlayerInfo()
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
con::Peer *peer = m_con.GetPeer(player->peer_id);
|
// Copy info from connection to info struct
|
||||||
// Copy info from peer to info struct
|
info.id = player->peer_id;
|
||||||
info.id = peer->id;
|
info.address = m_con.GetPeerAddress(player->peer_id);
|
||||||
info.address = peer->address;
|
info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
|
||||||
info.avg_rtt = peer->avg_rtt;
|
|
||||||
}
|
}
|
||||||
catch(con::PeerNotFoundException &e)
|
catch(con::PeerNotFoundException &e)
|
||||||
{
|
{
|
||||||
|
@ -4426,6 +4418,11 @@ void Server::notifyPlayer(const char *name, const std::wstring msg)
|
||||||
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
|
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::notifyPlayers(const std::wstring msg)
|
||||||
|
{
|
||||||
|
BroadcastChatMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
v3f findSpawnPos(ServerMap &map)
|
v3f findSpawnPos(ServerMap &map)
|
||||||
{
|
{
|
||||||
//return v3f(50,50,50)*BS;
|
//return v3f(50,50,50)*BS;
|
||||||
|
|
|
@ -476,13 +476,14 @@ public:
|
||||||
return m_banmanager.getBanDescription(ip_or_name);
|
return m_banmanager.getBanDescription(ip_or_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
con::Peer* getPeerNoEx(u16 peer_id)
|
Address getPeerAddress(u16 peer_id)
|
||||||
{
|
{
|
||||||
return m_con.GetPeerNoEx(peer_id);
|
return m_con.GetPeerAddress(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Envlock and conlock should be locked when calling this
|
// Envlock and conlock should be locked when calling this
|
||||||
void notifyPlayer(const char *name, const std::wstring msg);
|
void notifyPlayer(const char *name, const std::wstring msg);
|
||||||
|
void notifyPlayers(const std::wstring msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -251,19 +251,18 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
con::Peer *peer = ctx->server->getPeerNoEx(player->peer_id);
|
try{
|
||||||
if(peer == NULL)
|
Address address = ctx->server->getPeerAddress(player->peer_id);
|
||||||
{
|
std::string ip_string = address.serializeString();
|
||||||
dstream<<__FUNCTION_NAME<<": peer was not found"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string ip_string = peer->address.serializeString();
|
|
||||||
ctx->server->setIpBanned(ip_string, player->getName());
|
ctx->server->setIpBanned(ip_string, player->getName());
|
||||||
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
|
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
|
||||||
<<narrow_to_wide(player->getName());
|
<<narrow_to_wide(player->getName());
|
||||||
|
|
||||||
actionstream<<ctx->player->getName()<<" bans "
|
actionstream<<ctx->player->getName()<<" bans "
|
||||||
<<player->getName()<<" / "<<ip_string<<std::endl;
|
<<player->getName()<<" / "<<ip_string<<std::endl;
|
||||||
|
} catch(con::PeerNotFoundException){
|
||||||
|
dstream<<__FUNCTION_NAME<<": peer was not found"<<std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -277,6 +276,36 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmd_clearobjects(std::wostringstream &os,
|
||||||
|
ServerCommandContext *ctx)
|
||||||
|
{
|
||||||
|
if((ctx->privs & PRIV_SERVER) ==0)
|
||||||
|
{
|
||||||
|
os<<L"-!- You don't have permission to do that";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actionstream<<ctx->player->getName()
|
||||||
|
<<" clears all objects"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::wstring msg;
|
||||||
|
msg += L"Clearing all objects. This may take long.";
|
||||||
|
msg += L" You may experience a timeout. (by ";
|
||||||
|
msg += narrow_to_wide(ctx->player->getName());
|
||||||
|
msg += L")";
|
||||||
|
ctx->server->notifyPlayers(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->env->clearAllObjects();
|
||||||
|
|
||||||
|
actionstream<<"object clearing done"<<std::endl;
|
||||||
|
|
||||||
|
os<<L"*** cleared all objects";
|
||||||
|
ctx->flags |= SEND_TO_OTHERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//j
|
//j
|
||||||
void cmd_clanNew(std::wostringstream &os,
|
void cmd_clanNew(std::wostringstream &os,
|
||||||
ServerCommandContext *ctx)
|
ServerCommandContext *ctx)
|
||||||
|
@ -454,41 +483,25 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||||
os<<L" ban unban";
|
os<<L" ban unban";
|
||||||
}
|
}
|
||||||
else if(ctx->parms[0] == L"status")
|
else if(ctx->parms[0] == L"status")
|
||||||
{
|
|
||||||
cmd_status(os, ctx);
|
cmd_status(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"privs")
|
else if(ctx->parms[0] == L"privs")
|
||||||
{
|
|
||||||
cmd_privs(os, ctx);
|
cmd_privs(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
|
else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
|
||||||
{
|
|
||||||
cmd_grantrevoke(os, ctx);
|
cmd_grantrevoke(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"time")
|
else if(ctx->parms[0] == L"time")
|
||||||
{
|
|
||||||
cmd_time(os, ctx);
|
cmd_time(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"shutdown")
|
else if(ctx->parms[0] == L"shutdown")
|
||||||
{
|
|
||||||
cmd_shutdown(os, ctx);
|
cmd_shutdown(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"setting")
|
else if(ctx->parms[0] == L"setting")
|
||||||
{
|
|
||||||
cmd_setting(os, ctx);
|
cmd_setting(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"teleport")
|
else if(ctx->parms[0] == L"teleport")
|
||||||
{
|
|
||||||
cmd_teleport(os, ctx);
|
cmd_teleport(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
||||||
{
|
|
||||||
cmd_banunban(os, ctx);
|
cmd_banunban(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"me")
|
else if(ctx->parms[0] == L"me")
|
||||||
{
|
|
||||||
cmd_me(os, ctx);
|
cmd_me(os, ctx);
|
||||||
}
|
else if(ctx->parms[0] == L"clearobjects")
|
||||||
|
cmd_clearobjects(os, ctx);
|
||||||
else if(ctx->parms[0] == L"clan-new")
|
else if(ctx->parms[0] == L"clan-new")
|
||||||
{
|
{
|
||||||
cmd_clanNew(os, ctx);
|
cmd_clanNew(os, ctx);
|
||||||
|
@ -506,9 +519,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||||
cmd_clanKick(os, ctx);
|
cmd_clanKick(os, ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
os<<L"-!- Invalid command: " + ctx->parms[0];
|
os<<L"-!- Invalid command: " + ctx->parms[0];
|
||||||
}
|
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,15 +117,15 @@ u32 getTimeMs()
|
||||||
return porting::getTimeMs();
|
return porting::getTimeMs();
|
||||||
}
|
}
|
||||||
|
|
||||||
class DstreamLogOutput: public ILogOutput
|
class StderrLogOutput: public ILogOutput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* line: Full line with timestamp, level and thread */
|
/* line: Full line with timestamp, level and thread */
|
||||||
void printLog(const std::string &line)
|
void printLog(const std::string &line)
|
||||||
{
|
{
|
||||||
dstream<<line<<std::endl;
|
std::cerr<<line<<std::endl;
|
||||||
}
|
}
|
||||||
} main_dstream_log_out;
|
} main_stderr_log_out;
|
||||||
|
|
||||||
class DstreamNoStderrLogOutput: public ILogOutput
|
class DstreamNoStderrLogOutput: public ILogOutput
|
||||||
{
|
{
|
||||||
|
@ -143,7 +143,7 @@ int main(int argc, char *argv[])
|
||||||
Initialization
|
Initialization
|
||||||
*/
|
*/
|
||||||
|
|
||||||
log_add_output_maxlev(&main_dstream_log_out, LMT_ACTION);
|
log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION);
|
||||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||||
|
|
||||||
log_register_thread("main");
|
log_register_thread("main");
|
||||||
|
@ -245,7 +245,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd_args.getFlag("info-on-stderr"))
|
if(cmd_args.getFlag("info-on-stderr"))
|
||||||
log_add_output(&main_dstream_log_out, LMT_INFO);
|
log_add_output(&main_stderr_log_out, LMT_INFO);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Basic initialization
|
Basic initialization
|
||||||
|
|
|
@ -97,7 +97,7 @@ void Address::Resolve(const char *name)
|
||||||
freeaddrinfo(resolved);
|
freeaddrinfo(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Address::serializeString()
|
std::string Address::serializeString() const
|
||||||
{
|
{
|
||||||
unsigned int a, b, c, d;
|
unsigned int a, b, c, d;
|
||||||
a = (m_address & 0xFF000000)>>24;
|
a = (m_address & 0xFF000000)>>24;
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
void setPort(unsigned short port);
|
void setPort(unsigned short port);
|
||||||
void print(std::ostream *s) const;
|
void print(std::ostream *s) const;
|
||||||
void print() const;
|
void print() const;
|
||||||
std::string serializeString();
|
std::string serializeString() const;
|
||||||
private:
|
private:
|
||||||
unsigned int m_address;
|
unsigned int m_address;
|
||||||
unsigned short m_port;
|
unsigned short m_port;
|
||||||
|
|
48
src/test.cpp
48
src/test.cpp
|
@ -819,7 +819,10 @@ struct TestConnection
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test some real connections
|
Test some real connections
|
||||||
|
|
||||||
|
NOTE: This mostly tests the legacy interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u32 proto_id = 0xad26846a;
|
u32 proto_id = 0xad26846a;
|
||||||
|
|
||||||
Handler hand_server("server");
|
Handler hand_server("server");
|
||||||
|
@ -843,11 +846,30 @@ struct TestConnection
|
||||||
|
|
||||||
sleep_ms(50);
|
sleep_ms(50);
|
||||||
|
|
||||||
|
// Client should not have added client yet
|
||||||
|
assert(hand_client.count == 0);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
u16 peer_id;
|
||||||
|
u8 data[100];
|
||||||
|
infostream<<"** running client.Receive()"<<std::endl;
|
||||||
|
u32 size = client.Receive(peer_id, data, 100);
|
||||||
|
infostream<<"** Client received: peer_id="<<peer_id
|
||||||
|
<<", size="<<size
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
catch(con::NoIncomingDataException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Client should have added server now
|
// Client should have added server now
|
||||||
assert(hand_client.count == 1);
|
assert(hand_client.count == 1);
|
||||||
assert(hand_client.last_id == 1);
|
assert(hand_client.last_id == 1);
|
||||||
// But server should not have added client
|
// Server should not have added client yet
|
||||||
assert(hand_server.count == 0);
|
assert(hand_server.count == 0);
|
||||||
|
|
||||||
|
sleep_ms(50);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -930,7 +952,7 @@ struct TestConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 peer_id_client = 2;
|
u16 peer_id_client = 2;
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Send consequent packets in different order
|
Send consequent packets in different order
|
||||||
|
@ -941,13 +963,13 @@ struct TestConnection
|
||||||
SharedBuffer<u8> data2 = SharedBufferFromString("Hello2");
|
SharedBuffer<u8> data2 = SharedBufferFromString("Hello2");
|
||||||
|
|
||||||
Address client_address =
|
Address client_address =
|
||||||
server.GetPeer(peer_id_client)->address;
|
server.GetPeerAddress(peer_id_client);
|
||||||
|
|
||||||
infostream<<"*** Sending packets in wrong order (2,1,2)"
|
infostream<<"*** Sending packets in wrong order (2,1,2)"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
||||||
u8 chn = 0;
|
u8 chn = 0;
|
||||||
con::Channel *ch = &server.GetPeer(peer_id_client)->channels[chn];
|
con::Channel *ch = &server.getPeer(peer_id_client)->channels[chn];
|
||||||
u16 sn = ch->next_outgoing_seqnum;
|
u16 sn = ch->next_outgoing_seqnum;
|
||||||
ch->next_outgoing_seqnum = sn+1;
|
ch->next_outgoing_seqnum = sn+1;
|
||||||
server.Send(peer_id_client, chn, data2, true);
|
server.Send(peer_id_client, chn, data2, true);
|
||||||
|
@ -1004,6 +1026,7 @@ struct TestConnection
|
||||||
}
|
}
|
||||||
assert(got_exception);
|
assert(got_exception);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
const int datasize = 30000;
|
const int datasize = 30000;
|
||||||
SharedBuffer<u8> data1(datasize);
|
SharedBuffer<u8> data1(datasize);
|
||||||
|
@ -1022,12 +1045,25 @@ struct TestConnection
|
||||||
|
|
||||||
server.Send(peer_id_client, 0, data1, true);
|
server.Send(peer_id_client, 0, data1, true);
|
||||||
|
|
||||||
sleep_ms(50);
|
sleep_ms(3000);
|
||||||
|
|
||||||
u8 recvdata[datasize + 1000];
|
u8 recvdata[datasize + 1000];
|
||||||
infostream<<"** running client.Receive()"<<std::endl;
|
infostream<<"** running client.Receive()"<<std::endl;
|
||||||
u16 peer_id = 132;
|
u16 peer_id = 132;
|
||||||
u16 size = client.Receive(peer_id, recvdata, datasize + 1000);
|
u16 size = 0;
|
||||||
|
bool received = false;
|
||||||
|
u32 timems0 = porting::getTimeMs();
|
||||||
|
for(;;){
|
||||||
|
if(porting::getTimeMs() - timems0 > 5000)
|
||||||
|
break;
|
||||||
|
try{
|
||||||
|
size = client.Receive(peer_id, recvdata, datasize + 1000);
|
||||||
|
received = true;
|
||||||
|
}catch(con::NoIncomingDataException &e){
|
||||||
|
}
|
||||||
|
sleep_ms(10);
|
||||||
|
}
|
||||||
|
assert(received);
|
||||||
infostream<<"** Client received: peer_id="<<peer_id
|
infostream<<"** Client received: peer_id="<<peer_id
|
||||||
<<", size="<<size
|
<<", size="<<size
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
136
src/tile.cpp
136
src/tile.cpp
|
@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "mapnode.h" // For texture atlas making
|
||||||
|
#include "mineral.h" // For texture atlas making
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A cache from texture name to texture path
|
A cache from texture name to texture path
|
||||||
|
@ -507,52 +509,62 @@ void TextureSource::buildMainAtlas()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A list of stuff to include in the texture atlas.
|
Grab list of stuff to include in the texture atlas from the
|
||||||
|
main content features
|
||||||
It is a single-dimensional texture atlas due to the need to tile
|
|
||||||
textures.
|
|
||||||
|
|
||||||
It should contain as much of the stuff shown in game as possible,
|
|
||||||
to minimize texture changes.
|
|
||||||
|
|
||||||
It fills up quickly, so do not add anything that isn't contained
|
|
||||||
in most MapBlocks. E.g. mese isn't suitable but stone is.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
core::array<std::string> sourcelist;
|
core::map<std::string, bool> sourcelist;
|
||||||
|
|
||||||
sourcelist.push_back("stone.png");
|
for(u16 j=0; j<MAX_CONTENT+1; j++)
|
||||||
sourcelist.push_back("mud.png");
|
{
|
||||||
sourcelist.push_back("sand.png");
|
if(j == CONTENT_IGNORE || j == CONTENT_AIR)
|
||||||
sourcelist.push_back("grass.png");
|
continue;
|
||||||
sourcelist.push_back("grass_footsteps.png");
|
ContentFeatures *f = &content_features(j);
|
||||||
sourcelist.push_back("tree.png");
|
for(core::map<std::string, bool>::Iterator
|
||||||
sourcelist.push_back("tree_top.png");
|
i = f->used_texturenames.getIterator();
|
||||||
sourcelist.push_back("water.png");
|
i.atEnd() == false; i++)
|
||||||
sourcelist.push_back("leaves.png");
|
{
|
||||||
sourcelist.push_back("glass.png");
|
std::string name = i.getNode()->getKey();
|
||||||
sourcelist.push_back("mud.png^grass_side.png");
|
sourcelist[name] = true;
|
||||||
sourcelist.push_back("cobble.png");
|
|
||||||
sourcelist.push_back("mossycobble.png");
|
if(f->often_contains_mineral){
|
||||||
sourcelist.push_back("gravel.png");
|
for(int k=1; k<MINERAL_COUNT; k++){
|
||||||
sourcelist.push_back("jungletree.png");
|
std::string mineraltexture = mineral_block_texture(k);
|
||||||
|
std::string fulltexture = name + "^" + mineraltexture;
|
||||||
sourcelist.push_back("stone.png^mineral_coal.png");
|
sourcelist[fulltexture] = true;
|
||||||
sourcelist.push_back("stone.png^mineral_iron.png");
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infostream<<"Creating texture atlas out of textures: ";
|
||||||
|
for(core::map<std::string, bool>::Iterator
|
||||||
|
i = sourcelist.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
std::string name = i.getNode()->getKey();
|
||||||
|
infostream<<"\""<<name<<"\" ";
|
||||||
|
}
|
||||||
|
infostream<<std::endl;
|
||||||
|
|
||||||
// Padding to disallow texture bleeding
|
// Padding to disallow texture bleeding
|
||||||
s32 padding = 16;
|
s32 padding = 16;
|
||||||
|
|
||||||
|
s32 column_width = 256;
|
||||||
|
s32 column_padding = 16;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First pass: generate almost everything
|
First pass: generate almost everything
|
||||||
*/
|
*/
|
||||||
core::position2d<s32> pos_in_atlas(0,0);
|
core::position2d<s32> pos_in_atlas(0,0);
|
||||||
|
|
||||||
pos_in_atlas.Y += padding;
|
pos_in_atlas.Y = padding;
|
||||||
|
|
||||||
for(u32 i=0; i<sourcelist.size(); i++)
|
for(core::map<std::string, bool>::Iterator
|
||||||
|
i = sourcelist.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
std::string name = sourcelist[i];
|
std::string name = i.getNode()->getKey();
|
||||||
|
|
||||||
/*video::IImage *img = driver->createImageFromFile(
|
/*video::IImage *img = driver->createImageFromFile(
|
||||||
getTexturePath(name.c_str()).c_str());
|
getTexturePath(name.c_str()).c_str());
|
||||||
|
@ -586,20 +598,26 @@ void TextureSource::buildMainAtlas()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop making atlas if atlas is full
|
// Wrap columns and stop making atlas if atlas is full
|
||||||
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
|
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
|
||||||
{
|
{
|
||||||
infostream<<"TextureSource::buildMainAtlas(): "
|
if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - padding){
|
||||||
<<"Atlas is full, not adding more textures."
|
errorstream<<"TextureSource::buildMainAtlas(): "
|
||||||
<<std::endl;
|
<<"Atlas is full, not adding more textures."
|
||||||
break;
|
<<std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos_in_atlas.Y = padding;
|
||||||
|
pos_in_atlas.X += column_width + column_padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
|
infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
|
||||||
<<"\" to texture atlas"<<std::endl;
|
<<"\" to texture atlas"<<std::endl;
|
||||||
|
|
||||||
// Tile it a few times in the X direction
|
// Tile it a few times in the X direction
|
||||||
u16 xwise_tiling = 16;
|
u16 xwise_tiling = column_width / dim.Width;
|
||||||
|
if(xwise_tiling > 16) // Limit to 16 (more gives no benefit)
|
||||||
|
xwise_tiling = 16;
|
||||||
for(u32 j=0; j<xwise_tiling; j++)
|
for(u32 j=0; j<xwise_tiling; j++)
|
||||||
{
|
{
|
||||||
// Copy the copy to the atlas
|
// Copy the copy to the atlas
|
||||||
|
@ -627,7 +645,7 @@ void TextureSource::buildMainAtlas()
|
||||||
dst_y = -y0 + pos_in_atlas.Y-1;
|
dst_y = -y0 + pos_in_atlas.Y-1;
|
||||||
src_y = pos_in_atlas.Y;
|
src_y = pos_in_atlas.Y;
|
||||||
}
|
}
|
||||||
s32 x = x0 + pos_in_atlas.X * dim.Width;
|
s32 x = x0 + pos_in_atlas.X;
|
||||||
video::SColor c = atlas_img->getPixel(x, src_y);
|
video::SColor c = atlas_img->getPixel(x, src_y);
|
||||||
atlas_img->setPixel(x,dst_y,c);
|
atlas_img->setPixel(x,dst_y,c);
|
||||||
}
|
}
|
||||||
|
@ -668,9 +686,11 @@ void TextureSource::buildMainAtlas()
|
||||||
/*
|
/*
|
||||||
Second pass: set texture pointer in generated AtlasPointers
|
Second pass: set texture pointer in generated AtlasPointers
|
||||||
*/
|
*/
|
||||||
for(u32 i=0; i<sourcelist.size(); i++)
|
for(core::map<std::string, bool>::Iterator
|
||||||
|
i = sourcelist.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
std::string name = sourcelist[i];
|
std::string name = i.getNode()->getKey();
|
||||||
if(m_name_to_id.find(name) == NULL)
|
if(m_name_to_id.find(name) == NULL)
|
||||||
continue;
|
continue;
|
||||||
u32 id = m_name_to_id[name];
|
u32 id = m_name_to_id[name];
|
||||||
|
@ -681,8 +701,12 @@ void TextureSource::buildMainAtlas()
|
||||||
/*
|
/*
|
||||||
Write image to file so that it can be inspected
|
Write image to file so that it can be inspected
|
||||||
*/
|
*/
|
||||||
/*driver->writeImageToFile(atlas_img,
|
/*std::string atlaspath = porting::path_userdata
|
||||||
getTexturePath("main_atlas.png").c_str());*/
|
+ DIR_DELIM + "generated_texture_atlas.png";
|
||||||
|
infostream<<"Removing and writing texture atlas for inspection to "
|
||||||
|
<<atlaspath<<std::endl;
|
||||||
|
fs::RecursiveDelete(atlaspath);
|
||||||
|
driver->writeImageToFile(atlas_img, atlaspath.c_str());*/
|
||||||
}
|
}
|
||||||
|
|
||||||
video::IImage* generate_image_from_scratch(std::string name,
|
video::IImage* generate_image_from_scratch(std::string name,
|
||||||
|
@ -1092,22 +1116,23 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
// Blit
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
image->drop();
|
||||||
|
|
||||||
for(u32 y=0; y<dim.Height; y++)
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
for(u32 x=0; x<dim.Width; x++)
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
{
|
{
|
||||||
video::SColor c = image->getPixel(x,y);
|
video::SColor c = baseimg->getPixel(x,y);
|
||||||
u32 r = c.getRed();
|
u32 r = c.getRed();
|
||||||
u32 g = c.getGreen();
|
u32 g = c.getGreen();
|
||||||
u32 b = c.getBlue();
|
u32 b = c.getBlue();
|
||||||
if(!(r == r1 && g == g1 && b == b1))
|
if(!(r == r1 && g == g1 && b == b1))
|
||||||
continue;
|
continue;
|
||||||
c.setAlpha(0);
|
c.setAlpha(0);
|
||||||
image->setPixel(x,y,c);
|
baseimg->setPixel(x,y,c);
|
||||||
}
|
}
|
||||||
// Blit
|
|
||||||
image->copyTo(baseimg);
|
|
||||||
|
|
||||||
image->drop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1149,11 +1174,16 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
{
|
{
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
// Blit
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
image->drop();
|
||||||
|
|
||||||
for(u32 y=0; y<dim.Height; y++)
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
for(u32 x=0; x<dim.Width; x++)
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
{
|
{
|
||||||
video::SColor c = image->getPixel(x,y);
|
video::SColor c = baseimg->getPixel(x,y);
|
||||||
u32 r = c.getRed();
|
u32 r = c.getRed();
|
||||||
u32 g = c.getGreen();
|
u32 g = c.getGreen();
|
||||||
u32 b = c.getBlue();
|
u32 b = c.getBlue();
|
||||||
|
@ -1161,12 +1191,8 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
!(r == r2 && g == g2 && b == b2))
|
!(r == r2 && g == g2 && b == b2))
|
||||||
continue;
|
continue;
|
||||||
c.setAlpha(0);
|
c.setAlpha(0);
|
||||||
image->setPixel(x,y,c);
|
baseimg->setPixel(x,y,c);
|
||||||
}
|
}
|
||||||
// Blit
|
|
||||||
image->copyTo(baseimg);
|
|
||||||
|
|
||||||
image->drop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -283,9 +283,9 @@ struct TileSpec
|
||||||
TileSpec():
|
TileSpec():
|
||||||
texture(0),
|
texture(0),
|
||||||
alpha(255),
|
alpha(255),
|
||||||
material_type(MATERIAL_ALPHA_NONE),
|
//material_type(MATERIAL_ALPHA_NONE),
|
||||||
// Use this so that leaves don't need a separate material
|
// Use this so that leaves don't need a separate material
|
||||||
//material_type(MATERIAL_ALPHA_SIMPLE),
|
material_type(MATERIAL_ALPHA_SIMPLE),
|
||||||
material_flags(
|
material_flags(
|
||||||
//0 // <- DEBUG, Use the one below
|
//0 // <- DEBUG, Use the one below
|
||||||
MATERIAL_FLAG_BACKFACE_CULLING
|
MATERIAL_FLAG_BACKFACE_CULLING
|
||||||
|
|
|
@ -236,7 +236,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||||
|
|
||||||
// If block is (nearly) touching the camera, don't
|
// If block is (nearly) touching the camera, don't
|
||||||
// bother validating further (that is, render it anyway)
|
// bother validating further (that is, render it anyway)
|
||||||
if(d > block_max_radius * 1.5)
|
if(d > block_max_radius)
|
||||||
{
|
{
|
||||||
// Cosine of the angle between the camera direction
|
// Cosine of the angle between the camera direction
|
||||||
// and the block direction (camera_dir is an unit vector)
|
// and the block direction (camera_dir is an unit vector)
|
||||||
|
|
Loading…
Reference in New Issue