mobv2
parent
080002f8ed
commit
43a28f04fa
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 603 B |
|
@ -107,7 +107,6 @@ set(common_SRCS
|
||||||
defaultsettings.cpp
|
defaultsettings.cpp
|
||||||
mapnode.cpp
|
mapnode.cpp
|
||||||
voxel.cpp
|
voxel.cpp
|
||||||
mapblockobject.cpp
|
|
||||||
inventory.cpp
|
inventory.cpp
|
||||||
debug.cpp
|
debug.cpp
|
||||||
serialization.cpp
|
serialization.cpp
|
||||||
|
@ -137,6 +136,7 @@ endif()
|
||||||
# Client sources
|
# Client sources
|
||||||
set(minetest_SRCS
|
set(minetest_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
|
MyBillboardSceneNode.cpp
|
||||||
content_mapblock.cpp
|
content_mapblock.cpp
|
||||||
content_cao.cpp
|
content_cao.cpp
|
||||||
mapblock_mesh.cpp
|
mapblock_mesh.cpp
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||||
|
// This file is part of the "Irrlicht Engine".
|
||||||
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||||
|
|
||||||
|
#include "MyBillboardSceneNode.h"
|
||||||
|
#include "IVideoDriver.h"
|
||||||
|
#include "ISceneManager.h"
|
||||||
|
#include "ICameraSceneNode.h"
|
||||||
|
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene
|
||||||
|
{
|
||||||
|
|
||||||
|
//! constructor
|
||||||
|
MyBillboardSceneNode::MyBillboardSceneNode(ISceneNode* parent,
|
||||||
|
ISceneManager* mgr, s32 id,
|
||||||
|
const core::vector3df& position, const core::dimension2d<f32>& size)
|
||||||
|
: IBillboardSceneNode(parent, mgr, id, position)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
setDebugName("MyBillboardSceneNode");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setSize(size);
|
||||||
|
|
||||||
|
indices[0] = 0;
|
||||||
|
indices[1] = 2;
|
||||||
|
indices[2] = 1;
|
||||||
|
indices[3] = 0;
|
||||||
|
indices[4] = 3;
|
||||||
|
indices[5] = 2;
|
||||||
|
|
||||||
|
video::SColor colorTop = video::SColor(0xFFFFFFFF);
|
||||||
|
video::SColor colorBottom = video::SColor(0xFFFFFFFF);
|
||||||
|
|
||||||
|
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||||
|
vertices[0].Color = colorBottom;
|
||||||
|
|
||||||
|
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||||
|
vertices[1].Color = colorTop;
|
||||||
|
|
||||||
|
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||||
|
vertices[2].Color = colorTop;
|
||||||
|
|
||||||
|
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||||
|
vertices[3].Color = colorBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! pre render event
|
||||||
|
void MyBillboardSceneNode::OnRegisterSceneNode()
|
||||||
|
{
|
||||||
|
if (IsVisible)
|
||||||
|
SceneManager->registerNodeForRendering(this);
|
||||||
|
|
||||||
|
ISceneNode::OnRegisterSceneNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! render
|
||||||
|
void MyBillboardSceneNode::render()
|
||||||
|
{
|
||||||
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||||
|
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||||
|
|
||||||
|
if (!camera || !driver)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// make billboard look to camera
|
||||||
|
|
||||||
|
core::vector3df pos = getAbsolutePosition();
|
||||||
|
|
||||||
|
core::vector3df campos = camera->getAbsolutePosition();
|
||||||
|
core::vector3df target = camera->getTarget();
|
||||||
|
core::vector3df up = camera->getUpVector();
|
||||||
|
core::vector3df view = target - campos;
|
||||||
|
view.normalize();
|
||||||
|
|
||||||
|
core::vector3df horizontal = up.crossProduct(view);
|
||||||
|
if ( horizontal.getLength() == 0 )
|
||||||
|
{
|
||||||
|
horizontal.set(up.Y,up.X,up.Z);
|
||||||
|
}
|
||||||
|
horizontal.normalize();
|
||||||
|
horizontal *= 0.5f * Size.Width;
|
||||||
|
|
||||||
|
core::vector3df vertical = horizontal.crossProduct(view);
|
||||||
|
vertical.normalize();
|
||||||
|
vertical *= 0.5f * Size.Height;
|
||||||
|
|
||||||
|
view *= -1.0f;
|
||||||
|
|
||||||
|
for (s32 i=0; i<4; ++i)
|
||||||
|
vertices[i].Normal = view;
|
||||||
|
|
||||||
|
vertices[0].Pos = pos + horizontal + vertical;
|
||||||
|
vertices[1].Pos = pos + horizontal - vertical;
|
||||||
|
vertices[2].Pos = pos - horizontal - vertical;
|
||||||
|
vertices[3].Pos = pos - horizontal + vertical;
|
||||||
|
|
||||||
|
// draw
|
||||||
|
|
||||||
|
if ( DebugDataVisible & scene::EDS_BBOX )
|
||||||
|
{
|
||||||
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
|
video::SMaterial m;
|
||||||
|
m.Lighting = false;
|
||||||
|
driver->setMaterial(m);
|
||||||
|
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||||
|
}
|
||||||
|
|
||||||
|
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||||
|
|
||||||
|
driver->setMaterial(Material);
|
||||||
|
|
||||||
|
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! returns the axis aligned bounding box of this node
|
||||||
|
const core::aabbox3d<f32>& MyBillboardSceneNode::getBoundingBox() const
|
||||||
|
{
|
||||||
|
return BBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! sets the size of the billboard
|
||||||
|
void MyBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||||
|
{
|
||||||
|
Size = size;
|
||||||
|
|
||||||
|
if (Size.Width == 0.0f)
|
||||||
|
Size.Width = 1.0f;
|
||||||
|
|
||||||
|
if (Size.Height == 0.0f )
|
||||||
|
Size.Height = 1.0f;
|
||||||
|
|
||||||
|
f32 avg = (size.Width + size.Height)/6;
|
||||||
|
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||||
|
BBox.MaxEdge.set(avg,avg,avg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
video::SMaterial& MyBillboardSceneNode::getMaterial(u32 i)
|
||||||
|
{
|
||||||
|
return Material;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! returns amount of materials used by this scene node.
|
||||||
|
u32 MyBillboardSceneNode::getMaterialCount() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! gets the size of the billboard
|
||||||
|
const core::dimension2d<f32>& MyBillboardSceneNode::getSize() const
|
||||||
|
{
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Set the color of all vertices of the billboard
|
||||||
|
//! \param overallColor: the color to set
|
||||||
|
void MyBillboardSceneNode::setColor(const video::SColor & overallColor)
|
||||||
|
{
|
||||||
|
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||||
|
vertices[vertex].Color = overallColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Set the color of the top and bottom vertices of the billboard
|
||||||
|
//! \param topColor: the color to set the top vertices
|
||||||
|
//! \param bottomColor: the color to set the bottom vertices
|
||||||
|
void MyBillboardSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor)
|
||||||
|
{
|
||||||
|
vertices[0].Color = bottomColor;
|
||||||
|
vertices[1].Color = topColor;
|
||||||
|
vertices[2].Color = topColor;
|
||||||
|
vertices[3].Color = bottomColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Gets the color of the top and bottom vertices of the billboard
|
||||||
|
//! \param[out] topColor: stores the color of the top vertices
|
||||||
|
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||||
|
void MyBillboardSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const
|
||||||
|
{
|
||||||
|
bottomColor = vertices[0].Color;
|
||||||
|
topColor = vertices[1].Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyBillboardSceneNode::setTCoords(u32 i, core::vector2d<f32> c)
|
||||||
|
{
|
||||||
|
vertices[i].TCoords = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace scene
|
||||||
|
} // end namespace irr
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||||
|
// This file is part of the "Irrlicht Engine".
|
||||||
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||||
|
|
||||||
|
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||||
|
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||||
|
|
||||||
|
#include "IBillboardSceneNode.h"
|
||||||
|
#include "S3DVertex.h"
|
||||||
|
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene
|
||||||
|
{
|
||||||
|
|
||||||
|
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||||
|
//! which always looks to the camera.
|
||||||
|
class MyBillboardSceneNode : virtual public IBillboardSceneNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! constructor
|
||||||
|
MyBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||||
|
const core::vector3df& position, const core::dimension2d<f32>& size);
|
||||||
|
|
||||||
|
//! pre render event
|
||||||
|
virtual void OnRegisterSceneNode();
|
||||||
|
|
||||||
|
//! render
|
||||||
|
virtual void render();
|
||||||
|
|
||||||
|
//! returns the axis aligned bounding box of this node
|
||||||
|
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||||
|
|
||||||
|
//! sets the size of the billboard
|
||||||
|
virtual void setSize(const core::dimension2d<f32>& size);
|
||||||
|
|
||||||
|
//! gets the size of the billboard
|
||||||
|
virtual const core::dimension2d<f32>& getSize() const;
|
||||||
|
|
||||||
|
virtual video::SMaterial& getMaterial(u32 i);
|
||||||
|
|
||||||
|
//! returns amount of materials used by this scene node.
|
||||||
|
virtual u32 getMaterialCount() const;
|
||||||
|
|
||||||
|
//! Set the color of all vertices of the billboard
|
||||||
|
//! \param overallColor: the color to set
|
||||||
|
virtual void setColor(const video::SColor & overallColor);
|
||||||
|
|
||||||
|
//! Set the color of the top and bottom vertices of the billboard
|
||||||
|
//! \param topColor: the color to set the top vertices
|
||||||
|
//! \param bottomColor: the color to set the bottom vertices
|
||||||
|
virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor);
|
||||||
|
|
||||||
|
//! Gets the color of the top and bottom vertices of the billboard
|
||||||
|
//! \param[out] topColor: stores the color of the top vertices
|
||||||
|
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||||
|
virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const;
|
||||||
|
|
||||||
|
virtual void setTCoords(u32 i, core::vector2d<f32> c);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
core::dimension2d<f32> Size;
|
||||||
|
core::aabbox3d<f32> BBox;
|
||||||
|
video::SMaterial Material;
|
||||||
|
|
||||||
|
video::S3DVertex vertices[4];
|
||||||
|
u16 indices[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace scene
|
||||||
|
} // end namespace irr
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
255
src/client.cpp
255
src/client.cpp
|
@ -522,24 +522,6 @@ void Client::step(float dtime)
|
||||||
// Step environment
|
// Step environment
|
||||||
m_env.step(dtime);
|
m_env.step(dtime);
|
||||||
|
|
||||||
/*
|
|
||||||
Handle active blocks
|
|
||||||
NOTE: These old objects are DEPRECATED. TODO: Remove
|
|
||||||
*/
|
|
||||||
for(core::map<v3s16, bool>::Iterator
|
|
||||||
i = m_active_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
v3s16 p = i.getNode()->getKey();
|
|
||||||
|
|
||||||
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
|
||||||
if(block == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Step MapBlockObjects
|
|
||||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get events
|
Get events
|
||||||
*/
|
*/
|
||||||
|
@ -1191,16 +1173,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
}
|
}
|
||||||
//DEBUG
|
//DEBUG
|
||||||
else if(command == TOCLIENT_OBJECTDATA)
|
else if(command == TOCLIENT_OBJECTDATA)
|
||||||
//else if(0)
|
|
||||||
{
|
{
|
||||||
// Strip command word and create a stringstream
|
// Strip command word and create a stringstream
|
||||||
std::string datastring((char*)&data[2], datasize-2);
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
std::istringstream is(datastring, std::ios_base::binary);
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
|
||||||
{ //envlock
|
|
||||||
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
|
|
||||||
u8 buf[12];
|
u8 buf[12];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1250,106 +1227,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read block objects
|
Read block objects
|
||||||
NOTE: Deprecated stuff here, TODO: Remove
|
NOTE: Deprecated stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Read active block count
|
// Read active block count
|
||||||
is.read((char*)buf, 2);
|
u16 blockcount = readU16(is);
|
||||||
u16 blockcount = readU16(buf);
|
if(blockcount != 0){
|
||||||
|
dstream<<"WARNING: TOCLIENT_OBJECTDATA: blockcount != 0 "
|
||||||
// Initialize delete queue with all active blocks
|
"not supported"<<std::endl;
|
||||||
core::map<v3s16, bool> abs_to_delete;
|
return;
|
||||||
for(core::map<v3s16, bool>::Iterator
|
|
||||||
i = m_active_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
v3s16 p = i.getNode()->getKey();
|
|
||||||
/*dstream<<"adding "
|
|
||||||
<<"("<<p.x<<","<<p.y<<","<<p.z<<") "
|
|
||||||
<<" to abs_to_delete"
|
|
||||||
<<std::endl;*/
|
|
||||||
abs_to_delete.insert(p, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*dstream<<"Initial delete queue size: "<<abs_to_delete.size()
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
for(u16 i=0; i<blockcount; i++)
|
|
||||||
{
|
|
||||||
// Read blockpos
|
|
||||||
is.read((char*)buf, 6);
|
|
||||||
v3s16 p = readV3S16(buf);
|
|
||||||
// Get block from somewhere
|
|
||||||
MapBlock *block = NULL;
|
|
||||||
try{
|
|
||||||
block = m_env.getMap().getBlockNoCreate(p);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
//TODO: Create a dummy block?
|
|
||||||
}
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: "
|
|
||||||
<<"Could not get block at blockpos "
|
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
|
|
||||||
<<"in TOCLIENT_OBJECTDATA. Ignoring "
|
|
||||||
<<"following block object data."
|
|
||||||
<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*dstream<<"Client updating objects for block "
|
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
// Insert to active block list
|
|
||||||
m_active_blocks.insert(p, true);
|
|
||||||
|
|
||||||
// Remove from deletion queue
|
|
||||||
if(abs_to_delete.find(p) != NULL)
|
|
||||||
abs_to_delete.remove(p);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update objects of block
|
|
||||||
|
|
||||||
NOTE: Be sure this is done in the main thread.
|
|
||||||
*/
|
|
||||||
block->updateObjects(is, m_server_ser_ver,
|
|
||||||
m_device->getSceneManager(), m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*dstream<<"Final delete queue size: "<<abs_to_delete.size()
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
// Delete objects of blocks in delete queue
|
|
||||||
for(core::map<v3s16, bool>::Iterator
|
|
||||||
i = abs_to_delete.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
v3s16 p = i.getNode()->getKey();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MapBlock *block = m_env.getMap().getBlockNoCreate(p);
|
|
||||||
|
|
||||||
// Clear objects
|
|
||||||
block->clearObjects();
|
|
||||||
// Remove from active blocks list
|
|
||||||
m_active_blocks.remove(p);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
dstream<<"WARNAING: Client: "
|
|
||||||
<<"Couldn't clear objects of active->inactive"
|
|
||||||
<<" block "
|
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
|
||||||
<<" because block was not found"
|
|
||||||
<<std::endl;
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} //envlock
|
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_TIME_OF_DAY)
|
else if(command == TOCLIENT_TIME_OF_DAY)
|
||||||
{
|
{
|
||||||
|
@ -1636,32 +1523,6 @@ void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
|
||||||
Send(0, data, true);
|
Send(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item)
|
|
||||||
{
|
|
||||||
if(connectedAndInitialized() == false){
|
|
||||||
dout_client<<DTIME<<"Client::clickObject() "
|
|
||||||
"cancelled (not connected)"
|
|
||||||
<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
[0] u16 command=TOSERVER_CLICK_OBJECT
|
|
||||||
[2] u8 button (0=left, 1=right)
|
|
||||||
[3] v3s16 block
|
|
||||||
[9] s16 id
|
|
||||||
[11] u16 item
|
|
||||||
*/
|
|
||||||
u8 datasize = 2 + 1 + 6 + 2 + 2;
|
|
||||||
SharedBuffer<u8> data(datasize);
|
|
||||||
writeU16(&data[0], TOSERVER_CLICK_OBJECT);
|
|
||||||
writeU8(&data[2], button);
|
|
||||||
writeV3S16(&data[3], blockpos);
|
|
||||||
writeS16(&data[9], id);
|
|
||||||
writeU16(&data[11], item);
|
|
||||||
Send(0, data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::clickActiveObject(u8 button, u16 id, u16 item)
|
void Client::clickActiveObject(u8 button, u16 id, u16 item)
|
||||||
{
|
{
|
||||||
if(connectedAndInitialized() == false){
|
if(connectedAndInitialized() == false){
|
||||||
|
@ -1687,45 +1548,6 @@ void Client::clickActiveObject(u8 button, u16 id, u16 item)
|
||||||
Send(0, data, true);
|
Send(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::sendSignText(v3s16 blockpos, s16 id, std::string text)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
u16 command
|
|
||||||
v3s16 blockpos
|
|
||||||
s16 id
|
|
||||||
u16 textlen
|
|
||||||
textdata
|
|
||||||
*/
|
|
||||||
std::ostringstream os(std::ios_base::binary);
|
|
||||||
u8 buf[12];
|
|
||||||
|
|
||||||
// Write command
|
|
||||||
writeU16(buf, TOSERVER_SIGNTEXT);
|
|
||||||
os.write((char*)buf, 2);
|
|
||||||
|
|
||||||
// Write blockpos
|
|
||||||
writeV3S16(buf, blockpos);
|
|
||||||
os.write((char*)buf, 6);
|
|
||||||
|
|
||||||
// Write id
|
|
||||||
writeS16(buf, id);
|
|
||||||
os.write((char*)buf, 2);
|
|
||||||
|
|
||||||
u16 textlen = text.size();
|
|
||||||
// Write text length
|
|
||||||
writeS16(buf, textlen);
|
|
||||||
os.write((char*)buf, 2);
|
|
||||||
|
|
||||||
// Write text
|
|
||||||
os.write((char*)text.c_str(), textlen);
|
|
||||||
|
|
||||||
// Make data buffer
|
|
||||||
std::string s = os.str();
|
|
||||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
|
||||||
// Send as reliable
|
|
||||||
Send(0, data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::sendSignNodeText(v3s16 p, std::string text)
|
void Client::sendSignNodeText(v3s16 p, std::string text)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -2083,71 +1905,6 @@ void Client::inventoryAction(InventoryAction *a)
|
||||||
sendInventoryAction(a);
|
sendInventoryAction(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlockObject * Client::getSelectedObject(
|
|
||||||
f32 max_d,
|
|
||||||
v3f from_pos_f_on_map,
|
|
||||||
core::line3d<f32> shootline_on_map
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
|
|
||||||
core::array<DistanceSortedObject> objects;
|
|
||||||
|
|
||||||
for(core::map<v3s16, bool>::Iterator
|
|
||||||
i = m_active_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
v3s16 p = i.getNode()->getKey();
|
|
||||||
|
|
||||||
MapBlock *block = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
block = m_env.getMap().getBlockNoCreate(p);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate from_pos relative to block
|
|
||||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
|
||||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
|
||||||
v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map;
|
|
||||||
|
|
||||||
block->getObjects(from_pos_f_on_block, max_d, objects);
|
|
||||||
//block->getPseudoObjects(from_pos_f_on_block, max_d, objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
//dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
|
|
||||||
|
|
||||||
// Sort them.
|
|
||||||
// After this, the closest object is the first in the array.
|
|
||||||
objects.sort();
|
|
||||||
|
|
||||||
for(u32 i=0; i<objects.size(); i++)
|
|
||||||
{
|
|
||||||
MapBlockObject *obj = objects[i].obj;
|
|
||||||
MapBlock *block = obj->getBlock();
|
|
||||||
|
|
||||||
// Calculate shootline relative to block
|
|
||||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
|
||||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
|
||||||
core::line3d<f32> shootline_on_block(
|
|
||||||
shootline_on_map.start - block_pos_f_on_map,
|
|
||||||
shootline_on_map.end - block_pos_f_on_map
|
|
||||||
);
|
|
||||||
|
|
||||||
if(obj->isSelected(shootline_on_block))
|
|
||||||
{
|
|
||||||
//dstream<<"Returning selected object"<<std::endl;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//dstream<<"No object selected; returning NULL."<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientActiveObject * Client::getSelectedActiveObject(
|
ClientActiveObject * Client::getSelectedActiveObject(
|
||||||
f32 max_d,
|
f32 max_d,
|
||||||
v3f from_pos_f_on_map,
|
v3f from_pos_f_on_map,
|
||||||
|
|
10
src/client.h
10
src/client.h
|
@ -183,10 +183,8 @@ public:
|
||||||
|
|
||||||
void groundAction(u8 action, v3s16 nodepos_undersurface,
|
void groundAction(u8 action, v3s16 nodepos_undersurface,
|
||||||
v3s16 nodepos_oversurface, u16 item);
|
v3s16 nodepos_oversurface, u16 item);
|
||||||
void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item);
|
|
||||||
void clickActiveObject(u8 button, u16 id, u16 item);
|
void clickActiveObject(u8 button, u16 id, u16 item);
|
||||||
|
|
||||||
void sendSignText(v3s16 blockpos, s16 id, std::string text);
|
|
||||||
void sendSignNodeText(v3s16 p, std::string text);
|
void sendSignNodeText(v3s16 p, std::string text);
|
||||||
void sendInventoryAction(InventoryAction *a);
|
void sendInventoryAction(InventoryAction *a);
|
||||||
void sendChatMessage(const std::wstring &message);
|
void sendChatMessage(const std::wstring &message);
|
||||||
|
@ -225,14 +223,6 @@ public:
|
||||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||||
void inventoryAction(InventoryAction *a);
|
void inventoryAction(InventoryAction *a);
|
||||||
|
|
||||||
// Gets closest object pointed by the shootline
|
|
||||||
// Returns NULL if not found
|
|
||||||
MapBlockObject * getSelectedObject(
|
|
||||||
f32 max_d,
|
|
||||||
v3f from_pos_f_on_map,
|
|
||||||
core::line3d<f32> shootline_on_map
|
|
||||||
);
|
|
||||||
|
|
||||||
// Gets closest object pointed by the shootline
|
// Gets closest object pointed by the shootline
|
||||||
// Returns NULL if not found
|
// Returns NULL if not found
|
||||||
ClientActiveObject * getSelectedActiveObject(
|
ClientActiveObject * getSelectedActiveObject(
|
||||||
|
|
|
@ -45,7 +45,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type)
|
||||||
{
|
{
|
||||||
// If factory is not found, just return.
|
// If factory is not found, just return.
|
||||||
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
||||||
<<type<<std::endl;
|
<<(int)type<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
||||||
virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
|
virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
|
||||||
virtual v3f getPosition(){return v3f(0,0,0);}
|
virtual v3f getPosition(){return v3f(0,0,0);}
|
||||||
|
virtual bool doShowSelectionBox(){return true;}
|
||||||
|
|
||||||
// Step object in time
|
// Step object in time
|
||||||
virtual void step(float dtime, ClientEnvironment *env){}
|
virtual void step(float dtime, ClientEnvironment *env){}
|
||||||
|
|
|
@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "content_cao.h"
|
#include "content_cao.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include <ICameraSceneNode.h>
|
||||||
|
|
||||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||||
|
|
||||||
|
@ -683,7 +685,7 @@ void Oerkki1CAO::processMessage(const std::string &data)
|
||||||
}
|
}
|
||||||
else if(cmd == 1)
|
else if(cmd == 1)
|
||||||
{
|
{
|
||||||
u16 damage = readU8(is);
|
//u16 damage = readU8(is);
|
||||||
m_damage_visual_timer = 1.0;
|
m_damage_visual_timer = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -850,3 +852,377 @@ void FireflyCAO::initialize(const std::string &data)
|
||||||
|
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
MobV2CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
MobV2CAO proto_MobV2CAO;
|
||||||
|
|
||||||
|
MobV2CAO::MobV2CAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_walking(false),
|
||||||
|
m_walking_unset_timer(0),
|
||||||
|
m_walk_timer(0),
|
||||||
|
m_walk_frame(0),
|
||||||
|
m_damage_visual_timer(0),
|
||||||
|
m_last_light(0),
|
||||||
|
m_shooting(0),
|
||||||
|
m_shooting_unset_timer(0),
|
||||||
|
m_bright_shooting(false),
|
||||||
|
m_player_hit_timer(0)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_properties = new Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
MobV2CAO::~MobV2CAO()
|
||||||
|
{
|
||||||
|
delete m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* MobV2CAO::create()
|
||||||
|
{
|
||||||
|
return new MobV2CAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string texture_name = m_properties->get("texture_name");
|
||||||
|
//dstream<<"MobV2CAO::addToScene using texture_name="<<texture_name<<std::endl;
|
||||||
|
std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
|
||||||
|
texture_string += texture_name;
|
||||||
|
|
||||||
|
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
|
||||||
|
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||||
|
bill->setMaterialTexture(0, g_texturesource->getTextureRaw(texture_string));
|
||||||
|
bill->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||||
|
bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||||
|
bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
bill->setColor(video::SColor(255,0,0,0));
|
||||||
|
bill->setVisible(false); /* Set visible when brightness is known */
|
||||||
|
bill->setSize(m_sprite_size);
|
||||||
|
if(m_sprite_type == "humanoid_1"){
|
||||||
|
const float txp = 1./192;
|
||||||
|
const float txs = txp*32;
|
||||||
|
const float typ = 1./240;
|
||||||
|
const float tys = typ*48;
|
||||||
|
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||||
|
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||||
|
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||||
|
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||||
|
} else if(m_sprite_type == "simple"){
|
||||||
|
const float txs = 1.0;
|
||||||
|
const float tys = 1.0 / m_simple_anim_frames;
|
||||||
|
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||||
|
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||||
|
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||||
|
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||||
|
} else {
|
||||||
|
dstream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = bill;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->drop();
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_lock_full_brightness)
|
||||||
|
light_at_pos = 15;
|
||||||
|
|
||||||
|
m_last_light = light_at_pos;
|
||||||
|
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_damage_visual_timer > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_shooting && m_bright_shooting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*if(light_at_pos <= 2){
|
||||||
|
m_node->setVisible(false);
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
m_node->setVisible(true);
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
m_node->setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 MobV2CAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,0,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(pos_translator.vect_show + m_sprite_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
scene::MyBillboardSceneNode *bill = m_node;
|
||||||
|
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
|
||||||
|
if(m_sprite_type == "humanoid_1"){
|
||||||
|
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
||||||
|
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
||||||
|
cam_to_mob.normalize();
|
||||||
|
int col = 0;
|
||||||
|
if(cam_to_mob.Y > 0.7)
|
||||||
|
col = 5;
|
||||||
|
else if(cam_to_mob.Y < -0.7)
|
||||||
|
col = 4;
|
||||||
|
else{
|
||||||
|
float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / M_PI * 180.;
|
||||||
|
float dir = mob_dir - m_yaw;
|
||||||
|
dir = wrapDegrees_180(dir);
|
||||||
|
//dstream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||||
|
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||||
|
col = 2;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||||
|
col = 3;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||||
|
col = 0;
|
||||||
|
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||||
|
col = 1;
|
||||||
|
else
|
||||||
|
col = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
if(m_shooting){
|
||||||
|
row = 3;
|
||||||
|
} else if(m_walking){
|
||||||
|
m_walk_timer += dtime;
|
||||||
|
if(m_walk_timer >= 0.5){
|
||||||
|
m_walk_frame = (m_walk_frame + 1) % 2;
|
||||||
|
m_walk_timer = 0;
|
||||||
|
}
|
||||||
|
if(m_walk_frame == 0)
|
||||||
|
row = 1;
|
||||||
|
else
|
||||||
|
row = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float txp = 1./192;
|
||||||
|
const float txs = txp*32;
|
||||||
|
const float typ = 1./240;
|
||||||
|
const float tys = typ*48;
|
||||||
|
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||||
|
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||||
|
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||||
|
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||||
|
} else if(m_sprite_type == "simple"){
|
||||||
|
m_walk_timer += dtime;
|
||||||
|
if(m_walk_timer >= m_simple_anim_frametime){
|
||||||
|
m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
|
||||||
|
m_walk_timer = 0;
|
||||||
|
}
|
||||||
|
int col = 0;
|
||||||
|
int row = m_walk_frame;
|
||||||
|
const float txs = 1.0;
|
||||||
|
const float tys = 1.0 / m_simple_anim_frames;
|
||||||
|
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||||
|
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||||
|
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||||
|
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||||
|
} else {
|
||||||
|
dstream<<"MobV2CAO::step(): Unknown sprite type \""
|
||||||
|
<<m_sprite_type<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
/* Damage local player */
|
||||||
|
if(m_player_hit_damage && m_player_hit_timer <= 0.0){
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||||
|
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||||
|
|
||||||
|
if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
|
||||||
|
objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
|
||||||
|
{
|
||||||
|
env->damageLocalPlayer(m_player_hit_damage);
|
||||||
|
m_player_hit_timer = m_player_hit_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run timers */
|
||||||
|
|
||||||
|
m_player_hit_timer -= dtime;
|
||||||
|
|
||||||
|
if(m_damage_visual_timer >= 0){
|
||||||
|
m_damage_visual_timer -= dtime;
|
||||||
|
if(m_damage_visual_timer <= 0){
|
||||||
|
dstream<<"id="<<m_id<<" damage visual ended"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_walking_unset_timer += dtime;
|
||||||
|
if(m_walking_unset_timer >= 1.0){
|
||||||
|
m_walking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shooting_unset_timer -= dtime;
|
||||||
|
if(m_shooting_unset_timer <= 0.0){
|
||||||
|
if(m_bright_shooting){
|
||||||
|
u8 li = decode_light(m_last_light);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
bill->setColor(color);
|
||||||
|
m_bright_shooting = false;
|
||||||
|
}
|
||||||
|
m_shooting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"MobV2CAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
|
||||||
|
// Move
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
|
||||||
|
m_walking = true;
|
||||||
|
m_walking_unset_timer = 0;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
// Damage
|
||||||
|
else if(cmd == 1)
|
||||||
|
{
|
||||||
|
//u16 damage = readU16(is);
|
||||||
|
|
||||||
|
u8 li = decode_light(m_last_light);
|
||||||
|
if(li >= 100)
|
||||||
|
li = 30;
|
||||||
|
else
|
||||||
|
li = 255;
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
m_node->setColor(color);
|
||||||
|
|
||||||
|
m_damage_visual_timer = 0.2;
|
||||||
|
}
|
||||||
|
// Trigger shooting
|
||||||
|
else if(cmd == 2)
|
||||||
|
{
|
||||||
|
// length
|
||||||
|
m_shooting_unset_timer = readF1000(is);
|
||||||
|
// bright?
|
||||||
|
m_bright_shooting = readU8(is);
|
||||||
|
if(m_bright_shooting){
|
||||||
|
u8 li = 255;
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
m_node->setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shooting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2CAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"MobV2CAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0){
|
||||||
|
dstream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream tmp_os(std::ios::binary);
|
||||||
|
decompressZlib(is, tmp_os);
|
||||||
|
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
|
||||||
|
m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
|
||||||
|
|
||||||
|
/*dstream<<"INFO: MobV2CAO::initialize(): got properties:"<<std::endl;
|
||||||
|
m_properties->writeLines(dstream);*/
|
||||||
|
|
||||||
|
m_properties->setDefault("texture_name", "stone.png");
|
||||||
|
m_properties->setDefault("yaw", "0");
|
||||||
|
m_properties->setDefault("pos", "(0,0,0)");
|
||||||
|
m_properties->setDefault("sprite_size", "(1,1)");
|
||||||
|
m_properties->setDefault("sprite_pos", "(0,0,0)");
|
||||||
|
m_properties->setDefault("selection_size", "(0.4,0.4)");
|
||||||
|
m_properties->setDefault("selection_y", "-0.4");
|
||||||
|
m_properties->setDefault("sprite_type", "humanoid_1");
|
||||||
|
m_properties->setDefault("simple_anim_frames", "1");
|
||||||
|
m_properties->setDefault("simple_anim_frametime", "0.5");
|
||||||
|
m_properties->setDefault("lock_full_brightness", "false");
|
||||||
|
m_properties->setDefault("player_hit_damage", "0");
|
||||||
|
m_properties->setDefault("player_hit_distance", "1.5");
|
||||||
|
m_properties->setDefault("player_hit_interval", "1.5");
|
||||||
|
|
||||||
|
m_yaw = m_properties->getFloat("yaw");
|
||||||
|
m_position = m_properties->getV3F("pos");
|
||||||
|
m_sprite_size = m_properties->getV2F("sprite_size") * BS;
|
||||||
|
m_sprite_pos = m_properties->getV3F("sprite_pos") * BS;
|
||||||
|
v2f selection_size = m_properties->getV2F("selection_size") * BS;
|
||||||
|
float selection_y = m_properties->getFloat("selection_y") * BS;
|
||||||
|
m_selection_box = core::aabbox3d<f32>(
|
||||||
|
-selection_size.X, selection_y, -selection_size.X,
|
||||||
|
selection_size.X, selection_y+selection_size.Y,
|
||||||
|
selection_size.X);
|
||||||
|
m_sprite_type = m_properties->get("sprite_type");
|
||||||
|
m_simple_anim_frames = m_properties->getS32("simple_anim_frames");
|
||||||
|
m_simple_anim_frametime = m_properties->getFloat("simple_anim_frametime");
|
||||||
|
m_lock_full_brightness = m_properties->getBool("lock_full_brightness");
|
||||||
|
m_player_hit_damage = m_properties->getS32("player_hit_damage");
|
||||||
|
m_player_hit_distance = m_properties->getFloat("player_hit_distance");
|
||||||
|
m_player_hit_interval = m_properties->getFloat("player_hit_interval");
|
||||||
|
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
#include "content_object.h"
|
#include "content_object.h"
|
||||||
#include "utility.h" // For IntervalLimiter
|
#include "utility.h" // For IntervalLimiter
|
||||||
|
class Settings;
|
||||||
|
#include "MyBillboardSceneNode.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SmoothTranslator
|
SmoothTranslator
|
||||||
|
@ -74,11 +76,16 @@ struct SmoothTranslator
|
||||||
if(anim_time > 0.001)
|
if(anim_time > 0.001)
|
||||||
moveratio = anim_time_counter / anim_time;
|
moveratio = anim_time_counter / anim_time;
|
||||||
// Move a bit less than should, to avoid oscillation
|
// Move a bit less than should, to avoid oscillation
|
||||||
moveratio = moveratio * 0.8;
|
moveratio = moveratio * 0.5;
|
||||||
if(moveratio > 1.5)
|
if(moveratio > 1.5)
|
||||||
moveratio = 1.5;
|
moveratio = 1.5;
|
||||||
vect_show = vect_old + vect_move * moveratio;
|
vect_show = vect_old + vect_move * moveratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_moving()
|
||||||
|
{
|
||||||
|
return ((anim_time_counter / anim_time) < 1.4);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,6 +293,72 @@ private:
|
||||||
SmoothTranslator pos_translator;
|
SmoothTranslator pos_translator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
MobV2CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MobV2CAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MobV2CAO();
|
||||||
|
virtual ~MobV2CAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_MOBV2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
//{return m_position;}
|
||||||
|
bool doShowSelectionBox(){return false;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntervalLimiter m_attack_interval;
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::MyBillboardSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
bool m_walking;
|
||||||
|
float m_walking_unset_timer;
|
||||||
|
float m_walk_timer;
|
||||||
|
int m_walk_frame;
|
||||||
|
float m_damage_visual_timer;
|
||||||
|
u8 m_last_light;
|
||||||
|
bool m_shooting;
|
||||||
|
float m_shooting_unset_timer;
|
||||||
|
v2f m_sprite_size;
|
||||||
|
v3f m_sprite_pos;
|
||||||
|
bool m_bright_shooting;
|
||||||
|
std::string m_sprite_type;
|
||||||
|
int m_simple_anim_frames;
|
||||||
|
float m_simple_anim_frametime;
|
||||||
|
bool m_lock_full_brightness;
|
||||||
|
int m_player_hit_damage;
|
||||||
|
float m_player_hit_distance;
|
||||||
|
float m_player_hit_interval;
|
||||||
|
float m_player_hit_timer;
|
||||||
|
|
||||||
|
Settings *m_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||||
|
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "content_sao.h"
|
#include "content_sao.h"
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||||
|
|
||||||
|
/* Some helper functions */
|
||||||
|
|
||||||
|
// Y is copied, X and Z change is limited
|
||||||
|
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||||
|
{
|
||||||
|
v3f d_wanted = target_speed - speed;
|
||||||
|
d_wanted.Y = 0;
|
||||||
|
f32 dl_wanted = d_wanted.getLength();
|
||||||
|
f32 dl = dl_wanted;
|
||||||
|
if(dl > max_increase)
|
||||||
|
dl = max_increase;
|
||||||
|
|
||||||
|
v3f d = d_wanted.normalize() * dl;
|
||||||
|
|
||||||
|
speed.X += d.X;
|
||||||
|
speed.Z += d.Z;
|
||||||
|
speed.Y = target_speed.Y;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TestSAO
|
TestSAO
|
||||||
*/
|
*/
|
||||||
|
@ -422,23 +442,6 @@ InventoryItem* RatSAO::createPickedUpItem()
|
||||||
Oerkki1SAO
|
Oerkki1SAO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Y is copied, X and Z change is limited
|
|
||||||
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
|
||||||
{
|
|
||||||
v3f d_wanted = target_speed - speed;
|
|
||||||
d_wanted.Y = 0;
|
|
||||||
f32 dl_wanted = d_wanted.getLength();
|
|
||||||
f32 dl = dl_wanted;
|
|
||||||
if(dl > max_increase)
|
|
||||||
dl = max_increase;
|
|
||||||
|
|
||||||
v3f d = d_wanted.normalize() * dl;
|
|
||||||
|
|
||||||
speed.X += d.X;
|
|
||||||
speed.Z += d.Z;
|
|
||||||
speed.Y = target_speed.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
@ -617,7 +620,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||||
m_touching_ground = moveresult.touching_ground;
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
// Do collision damage
|
// Do collision damage
|
||||||
float tolerance = BS*12;
|
float tolerance = BS*30;
|
||||||
float factor = BS*0.5;
|
float factor = BS*0.5;
|
||||||
v3f speed_diff = old_speed - m_speed_f;
|
v3f speed_diff = old_speed - m_speed_f;
|
||||||
// Increase effect in X and Z
|
// Increase effect in X and Z
|
||||||
|
@ -886,3 +889,477 @@ InventoryItem* FireflySAO::createPickedUpItem()
|
||||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
MobV2SAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL);
|
||||||
|
|
||||||
|
MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
Settings *init_properties):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_move_type("ground_nodes"),
|
||||||
|
m_speed(0,0,0),
|
||||||
|
m_last_sent_position(0,0,0),
|
||||||
|
m_oldpos(0,0,0),
|
||||||
|
m_yaw(0),
|
||||||
|
m_counter1(0),
|
||||||
|
m_counter2(0),
|
||||||
|
m_age(0),
|
||||||
|
m_touching_ground(false),
|
||||||
|
m_hp(10),
|
||||||
|
m_walk_around(false),
|
||||||
|
m_walk_around_timer(0),
|
||||||
|
m_next_pos_exists(false),
|
||||||
|
m_shoot_reload_timer(0),
|
||||||
|
m_shooting(false),
|
||||||
|
m_shooting_timer(0),
|
||||||
|
m_falling(false)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_properties = new Settings();
|
||||||
|
if(init_properties)
|
||||||
|
m_properties->update(*init_properties);
|
||||||
|
|
||||||
|
m_properties->setV3F("pos", pos);
|
||||||
|
|
||||||
|
setPropertyDefaults();
|
||||||
|
readProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
MobV2SAO::~MobV2SAO()
|
||||||
|
{
|
||||||
|
delete m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
Settings properties;
|
||||||
|
properties.parseConfigLines(is, "MobArgsEnd");
|
||||||
|
MobV2SAO *o = new MobV2SAO(env, id, pos, &properties);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MobV2SAO::getStaticData()
|
||||||
|
{
|
||||||
|
updateProperties();
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
m_properties->writeLines(os);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MobV2SAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
|
||||||
|
updateProperties();
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
|
||||||
|
Settings client_properties;
|
||||||
|
|
||||||
|
/*client_properties.set("version", "0");
|
||||||
|
client_properties.updateValue(*m_properties, "pos");
|
||||||
|
client_properties.updateValue(*m_properties, "yaw");
|
||||||
|
client_properties.updateValue(*m_properties, "hp");*/
|
||||||
|
|
||||||
|
// Just send everything for simplicity
|
||||||
|
client_properties.update(*m_properties);
|
||||||
|
|
||||||
|
std::ostringstream os2(std::ios::binary);
|
||||||
|
client_properties.writeLines(os2);
|
||||||
|
compressZlib(os2.str(), os);
|
||||||
|
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkFreePosition(Map *map, v3s16 p0, v3s16 size)
|
||||||
|
{
|
||||||
|
for(int dx=0; dx<size.X; dx++)
|
||||||
|
for(int dy=0; dy<size.Y; dy++)
|
||||||
|
for(int dz=0; dz<size.Z; dz++){
|
||||||
|
v3s16 dp(dx, dy, dz);
|
||||||
|
v3s16 p = p0 + dp;
|
||||||
|
MapNode n = map->getNodeNoEx(p);
|
||||||
|
if(n.getContent() != CONTENT_AIR)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkWalkablePosition(Map *map, v3s16 p0)
|
||||||
|
{
|
||||||
|
v3s16 p = p0 + v3s16(0,-1,0);
|
||||||
|
MapNode n = map->getNodeNoEx(p);
|
||||||
|
if(n.getContent() != CONTENT_AIR)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size)
|
||||||
|
{
|
||||||
|
if(!checkFreePosition(map, p0, size))
|
||||||
|
return false;
|
||||||
|
if(!checkWalkablePosition(map, p0))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_random_u32_array(u32 a[], u32 len)
|
||||||
|
{
|
||||||
|
u32 i, n;
|
||||||
|
for(i=0; i<len; i++)
|
||||||
|
a[i] = i;
|
||||||
|
n = len;
|
||||||
|
while(n > 1){
|
||||||
|
u32 k = myrand() % n;
|
||||||
|
n--;
|
||||||
|
u32 temp = a[n];
|
||||||
|
a[n] = a[k];
|
||||||
|
a[k] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
|
static void explodeSquare(Map *map, v3s16 p0, v3s16 size)
|
||||||
|
{
|
||||||
|
core::map<v3s16, MapBlock*> modified_blocks;
|
||||||
|
|
||||||
|
for(int dx=0; dx<size.X; dx++)
|
||||||
|
for(int dy=0; dy<size.Y; dy++)
|
||||||
|
for(int dz=0; dz<size.Z; dz++){
|
||||||
|
v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2);
|
||||||
|
v3s16 p = p0 + dp;
|
||||||
|
MapNode n = map->getNodeNoEx(p);
|
||||||
|
if(n.getContent() == CONTENT_IGNORE)
|
||||||
|
continue;
|
||||||
|
//map->removeNodeWithEvent(p);
|
||||||
|
map->removeNodeAndUpdate(p, modified_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a MEET_OTHER event
|
||||||
|
MapEditEvent event;
|
||||||
|
event.type = MEET_OTHER;
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = modified_blocks.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
v3s16 p = i.getNode()->getKey();
|
||||||
|
event.modified_blocks.insert(p, true);
|
||||||
|
}
|
||||||
|
map->dispatchEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
assert(m_env);
|
||||||
|
Map *map = &m_env->getMap();
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
|
||||||
|
if(m_die_age >= 0.0 && m_age >= m_die_age){
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_falling)
|
||||||
|
{
|
||||||
|
m_shooting_timer -= dtime;
|
||||||
|
if(m_shooting_timer <= 0.0 && m_shooting){
|
||||||
|
m_shooting = false;
|
||||||
|
|
||||||
|
std::string shoot_type = m_properties->get("shoot_type");
|
||||||
|
v3f shoot_pos(0,0,0);
|
||||||
|
shoot_pos.Y += m_properties->getFloat("shoot_y") * BS;
|
||||||
|
if(shoot_type == "fireball"){
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
v3f speed = dir * BS * 10.0;
|
||||||
|
v3f pos = m_base_position + shoot_pos;
|
||||||
|
dstream<<__FUNCTION_NAME<<": Shooting fireball from "<<PP(pos)
|
||||||
|
<<" at speed "<<PP(speed)<<std::endl;
|
||||||
|
Settings properties;
|
||||||
|
properties.setV3F("speed", speed);
|
||||||
|
properties.setFloat("die_age", 5.0);
|
||||||
|
properties.set("move_type", "constant_speed");
|
||||||
|
properties.set("texture_name", "fireball.png");
|
||||||
|
properties.setV3F("sprite_pos", v3f(0.0, 0.0, 0.0));
|
||||||
|
properties.setV2F("sprite_size", v2f(1.0, 1.0));
|
||||||
|
properties.set("sprite_type", "simple");
|
||||||
|
properties.set("simple_anim_frames", "3");
|
||||||
|
properties.set("simple_anim_frametime", "0.1");
|
||||||
|
properties.setFloat("hp", 1000);
|
||||||
|
properties.set("lock_full_brightness", "true");
|
||||||
|
properties.set("player_hit_damage", "9");
|
||||||
|
properties.set("player_hit_distance", "2");
|
||||||
|
properties.set("player_hit_interval", "1");
|
||||||
|
ServerActiveObject *obj = new MobV2SAO(m_env, 0,
|
||||||
|
pos, &properties);
|
||||||
|
//m_env->addActiveObjectAsStatic(obj);
|
||||||
|
m_env->addActiveObject(obj);
|
||||||
|
} else {
|
||||||
|
dstream<<__FUNCTION_NAME<<": Unknown shoot_type="<<shoot_type
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shoot_reload_timer += dtime;
|
||||||
|
|
||||||
|
if(m_shoot_reload_timer >= 5.0 && !m_next_pos_exists)
|
||||||
|
{
|
||||||
|
m_shoot_reload_timer = 0.0;
|
||||||
|
m_shooting = true;
|
||||||
|
m_shooting_timer = 1.5;
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (2 = shooting)
|
||||||
|
writeU8(os, 2);
|
||||||
|
// time
|
||||||
|
writeF1000(os, m_shooting_timer + 0.1);
|
||||||
|
// bright?
|
||||||
|
writeU8(os, true);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_move_type == "ground_nodes")
|
||||||
|
{
|
||||||
|
if(!m_shooting){
|
||||||
|
m_walk_around_timer -= dtime;
|
||||||
|
if(m_walk_around_timer <= 0.0){
|
||||||
|
m_walk_around = !m_walk_around;
|
||||||
|
if(m_walk_around)
|
||||||
|
m_walk_around_timer = 0.1*myrand_range(10,50);
|
||||||
|
else
|
||||||
|
m_walk_around_timer = 0.1*myrand_range(30,70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move */
|
||||||
|
if(m_next_pos_exists){
|
||||||
|
v3f pos_f = m_base_position;
|
||||||
|
v3f next_pos_f = intToFloat(m_next_pos_i, BS);
|
||||||
|
|
||||||
|
v3f v = next_pos_f - pos_f;
|
||||||
|
m_yaw = atan2(v.Z, v.X) / M_PI * 180;
|
||||||
|
|
||||||
|
v3f diff = next_pos_f - pos_f;
|
||||||
|
v3f dir = diff;
|
||||||
|
dir.normalize();
|
||||||
|
float speed = BS * 0.5;
|
||||||
|
if(m_falling)
|
||||||
|
speed = BS * 3.0;
|
||||||
|
dir *= dtime * speed;
|
||||||
|
bool arrived = false;
|
||||||
|
if(dir.getLength() > diff.getLength()){
|
||||||
|
dir = diff;
|
||||||
|
arrived = true;
|
||||||
|
}
|
||||||
|
pos_f += dir;
|
||||||
|
m_base_position = pos_f;
|
||||||
|
|
||||||
|
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
||||||
|
//dstream<<"id="<<m_id<<": arrived to "<<PP(m_next_pos_i)<<std::endl;
|
||||||
|
m_next_pos_exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||||
|
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||||
|
v3s16 pos_size_off(0,0,0);
|
||||||
|
if(m_size.X >= 2.5){
|
||||||
|
pos_size_off.X = -1;
|
||||||
|
pos_size_off.Y = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_next_pos_exists){
|
||||||
|
/* Check whether to drop down */
|
||||||
|
if(checkFreePosition(map,
|
||||||
|
pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){
|
||||||
|
m_next_pos_i = pos_i + v3s16(0,-1,0);
|
||||||
|
m_next_pos_exists = true;
|
||||||
|
m_falling = true;
|
||||||
|
} else {
|
||||||
|
m_falling = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_walk_around)
|
||||||
|
{
|
||||||
|
if(!m_next_pos_exists){
|
||||||
|
/* Find some position where to go next */
|
||||||
|
v3s16 dps[3*3*3];
|
||||||
|
int num_dps = 0;
|
||||||
|
for(int dx=-1; dx<=1; dx++)
|
||||||
|
for(int dy=-1; dy<=1; dy++)
|
||||||
|
for(int dz=-1; dz<=1; dz++){
|
||||||
|
if(dx == 0 && dy == 0)
|
||||||
|
continue;
|
||||||
|
if(dx != 0 && dz != 0 && dy != 0)
|
||||||
|
continue;
|
||||||
|
dps[num_dps++] = v3s16(dx,dy,dz);
|
||||||
|
}
|
||||||
|
u32 order[3*3*3];
|
||||||
|
get_random_u32_array(order, num_dps);
|
||||||
|
/*dstream<<"At pos "<<PP(pos_i)<<"; Random array: ";
|
||||||
|
for(int i=0; i<num_dps; i++){
|
||||||
|
dstream<<order[i]<<" ";
|
||||||
|
}
|
||||||
|
dstream<<std::endl;*/
|
||||||
|
for(int i=0; i<num_dps; i++){
|
||||||
|
v3s16 p = dps[order[i]] + pos_i;
|
||||||
|
bool is_free = checkFreeAndWalkablePosition(map,
|
||||||
|
p + pos_size_off, size_blocks);
|
||||||
|
//dstream<<PP(p)<<" is_free="<<is_free<<std::endl;
|
||||||
|
if(!is_free)
|
||||||
|
continue;
|
||||||
|
m_next_pos_i = p;
|
||||||
|
m_next_pos_exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_move_type == "constant_speed")
|
||||||
|
{
|
||||||
|
m_base_position += m_speed * dtime;
|
||||||
|
|
||||||
|
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||||
|
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||||
|
v3s16 pos_size_off(0,0,0);
|
||||||
|
if(m_size.X >= 2.5){
|
||||||
|
pos_size_off.X = -1;
|
||||||
|
pos_size_off.Y = -1;
|
||||||
|
}
|
||||||
|
bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
|
||||||
|
if(!free){
|
||||||
|
explodeSquare(map, pos_i, v3s16(3,3,3));
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\""
|
||||||
|
<<m_move_type<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = m_base_position;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 MobV2SAO::punch(const std::string &toolname, v3f dir)
|
||||||
|
{
|
||||||
|
u16 amount = 2;
|
||||||
|
dstream<<"id="<<m_id<<": punch with \""<<toolname<<"\""<<std::endl;
|
||||||
|
/* See tool names in inventory.h */
|
||||||
|
if(toolname == "WSword")
|
||||||
|
amount = 4;
|
||||||
|
if(toolname == "STSword")
|
||||||
|
amount = 7;
|
||||||
|
if(toolname == "SteelSword")
|
||||||
|
amount = 10;
|
||||||
|
if(toolname == "STAxe")
|
||||||
|
amount = 3;
|
||||||
|
if(toolname == "SteelAxe")
|
||||||
|
amount = 4;
|
||||||
|
if(toolname == "SteelPick")
|
||||||
|
amount = 3;
|
||||||
|
doDamage(amount);
|
||||||
|
return 65536/100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::setPropertyDefaults()
|
||||||
|
{
|
||||||
|
m_properties->setDefault("move_type", "ground_nodes");
|
||||||
|
m_properties->setDefault("speed", "(0,0,0)");
|
||||||
|
m_properties->setDefault("age", "0");
|
||||||
|
m_properties->setDefault("yaw", "0");
|
||||||
|
m_properties->setDefault("pos", "(0,0,0)");
|
||||||
|
m_properties->setDefault("hp", "0");
|
||||||
|
m_properties->setDefault("die_age", "-1");
|
||||||
|
m_properties->setDefault("size", "(1,2)");
|
||||||
|
m_properties->setDefault("shoot_type", "fireball");
|
||||||
|
m_properties->setDefault("shoot_y", "0");
|
||||||
|
}
|
||||||
|
void MobV2SAO::readProperties()
|
||||||
|
{
|
||||||
|
m_move_type = m_properties->get("move_type");
|
||||||
|
m_speed = m_properties->getV3F("speed");
|
||||||
|
m_age = m_properties->getFloat("age");
|
||||||
|
m_yaw = m_properties->getFloat("yaw");
|
||||||
|
m_base_position = m_properties->getV3F("pos");
|
||||||
|
m_hp = m_properties->getS32("hp");
|
||||||
|
m_die_age = m_properties->getFloat("die_age");
|
||||||
|
m_size = m_properties->getV2F("size");
|
||||||
|
}
|
||||||
|
void MobV2SAO::updateProperties()
|
||||||
|
{
|
||||||
|
m_properties->set("move_type", m_move_type);
|
||||||
|
m_properties->setV3F("speed", m_speed);
|
||||||
|
m_properties->setFloat("age", m_age);
|
||||||
|
m_properties->setFloat("yaw", m_yaw);
|
||||||
|
m_properties->setV3F("pos", m_base_position);
|
||||||
|
m_properties->setS32("hp", m_hp);
|
||||||
|
m_properties->setFloat("die_age", m_die_age);
|
||||||
|
m_properties->setV2F("size", m_size);
|
||||||
|
|
||||||
|
m_properties->setS32("version", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::doDamage(u16 d)
|
||||||
|
{
|
||||||
|
dstream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl;
|
||||||
|
|
||||||
|
if(d < m_hp)
|
||||||
|
{
|
||||||
|
m_hp -= d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_hp = 0;
|
||||||
|
m_removed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (1 = damage)
|
||||||
|
writeU8(os, 1);
|
||||||
|
// amount
|
||||||
|
writeU16(os, d);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -139,5 +139,52 @@ private:
|
||||||
bool m_touching_ground;
|
bool m_touching_ground;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
|
||||||
|
class MobV2SAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
Settings *init_properties);
|
||||||
|
virtual ~MobV2SAO();
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_MOBV2;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
std::string getStaticData();
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
|
u16 punch(const std::string &toolname, v3f dir);
|
||||||
|
private:
|
||||||
|
void setPropertyDefaults();
|
||||||
|
void readProperties();
|
||||||
|
void updateProperties();
|
||||||
|
void doDamage(u16 d);
|
||||||
|
|
||||||
|
std::string m_move_type;
|
||||||
|
v3f m_speed;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
v3f m_oldpos;
|
||||||
|
float m_yaw;
|
||||||
|
float m_counter1;
|
||||||
|
float m_counter2;
|
||||||
|
float m_age;
|
||||||
|
bool m_touching_ground;
|
||||||
|
int m_hp;
|
||||||
|
bool m_walk_around;
|
||||||
|
float m_walk_around_timer;
|
||||||
|
bool m_next_pos_exists;
|
||||||
|
v3s16 m_next_pos_i;
|
||||||
|
float m_shoot_reload_timer;
|
||||||
|
bool m_shooting;
|
||||||
|
float m_shooting_timer;
|
||||||
|
float m_die_age;
|
||||||
|
v2f m_size;
|
||||||
|
bool m_falling;
|
||||||
|
|
||||||
|
Settings *m_properties;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,8 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("fixed_map_seed", "");
|
settings->setDefault("fixed_map_seed", "");
|
||||||
|
|
||||||
settings->setDefault("objectdata_interval", "0.2");
|
settings->setDefault("objectdata_interval", "0.2");
|
||||||
settings->setDefault("active_object_range", "2");
|
settings->setDefault("active_object_send_range_blocks", "3");
|
||||||
|
settings->setDefault("active_block_range", "5");
|
||||||
//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");
|
||||||
|
|
|
@ -643,6 +643,24 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void getMob_dungeon_master(Settings &properties)
|
||||||
|
{
|
||||||
|
properties.set("texture_name", "dungeon_master.png");
|
||||||
|
properties.setV3F("sprite_pos", v3f(0.0, 0.85, 0.0));
|
||||||
|
properties.setV2F("sprite_size", v2f(2.0, 3.0));
|
||||||
|
properties.setFloat("selection_y", -0.4);
|
||||||
|
properties.setV2F("selection_size", v2f(0.4, 2.6));
|
||||||
|
properties.setFloat("yaw", 1.57);
|
||||||
|
properties.setFloat("hp", 20);
|
||||||
|
properties.setBool("bright_shooting", true);
|
||||||
|
properties.set("shoot_type", "fireball");
|
||||||
|
properties.set("shoot_y", "0.7");
|
||||||
|
properties.set("sprite_type", "humanoid_1");
|
||||||
|
properties.set("player_hit_damage", "1");
|
||||||
|
properties.set("player_hit_distance", "1.0");
|
||||||
|
properties.set("player_hit_interval", "0.5");
|
||||||
|
}
|
||||||
|
|
||||||
void ServerEnvironment::step(float dtime)
|
void ServerEnvironment::step(float dtime)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -725,7 +743,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
Update list of active blocks, collecting changes
|
Update list of active blocks, collecting changes
|
||||||
*/
|
*/
|
||||||
const s16 active_block_range = 5;
|
const s16 active_block_range = g_settings->getS16("active_block_range");
|
||||||
core::map<v3s16, bool> blocks_removed;
|
core::map<v3s16, bool> blocks_removed;
|
||||||
core::map<v3s16, bool> blocks_added;
|
core::map<v3s16, bool> blocks_added;
|
||||||
m_active_blocks.update(players_blockpos, active_block_range,
|
m_active_blocks.update(players_blockpos, active_block_range,
|
||||||
|
@ -926,14 +944,52 @@ void ServerEnvironment::step(float dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Make trees from saplings!
|
Fun things spawn in caves and dungeons
|
||||||
|
*/
|
||||||
|
if(n.getContent() == CONTENT_STONE ||
|
||||||
|
n.getContent() == CONTENT_MOSSYCOBBLE)
|
||||||
|
{
|
||||||
|
if(myrand()%200 == 0 && active_object_count_wider == 0)
|
||||||
|
{
|
||||||
|
v3s16 p1 = p + v3s16(0,1,0);
|
||||||
|
MapNode n1a = m_map->getNodeNoEx(p1+v3s16(0,0,0));
|
||||||
|
if(n1a.getLightBlend(getDayNightRatio()) <= 3){
|
||||||
|
MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,1,0));
|
||||||
|
if(n1a.getContent() == CONTENT_AIR &&
|
||||||
|
n1b.getContent() == CONTENT_AIR)
|
||||||
|
{
|
||||||
|
v3f pos = intToFloat(p1, BS);
|
||||||
|
int i = myrand()%5;
|
||||||
|
if(i == 0 || i == 1){
|
||||||
|
Settings properties;
|
||||||
|
getMob_dungeon_master(properties);
|
||||||
|
ServerActiveObject *obj = new MobV2SAO(
|
||||||
|
this, 0, pos, &properties);
|
||||||
|
addActiveObject(obj);
|
||||||
|
} else if(i == 2 || i == 3){
|
||||||
|
for(int j=0; j<3; j++){
|
||||||
|
ServerActiveObject *obj = new RatSAO(
|
||||||
|
this, 0, pos);
|
||||||
|
addActiveObject(obj);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ServerActiveObject *obj = new Oerkki1SAO(
|
||||||
|
this, 0, pos);
|
||||||
|
addActiveObject(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Make trees from saplings!
|
||||||
*/
|
*/
|
||||||
if(n.getContent() == CONTENT_SAPLING)
|
if(n.getContent() == CONTENT_SAPLING)
|
||||||
{
|
{
|
||||||
if(myrand()%50 == 0)
|
if(myrand()%50 == 0)
|
||||||
{
|
{
|
||||||
core::map<v3s16, MapBlock*> modified_blocks;
|
core::map<v3s16, MapBlock*> modified_blocks;
|
||||||
v3s16 tree_p = p;
|
v3s16 tree_p = p;
|
||||||
ManualMapVoxelManipulator vmanip(m_map);
|
ManualMapVoxelManipulator vmanip(m_map);
|
||||||
v3s16 tree_blockp = getNodeBlockPos(tree_p);
|
v3s16 tree_blockp = getNodeBlockPos(tree_p);
|
||||||
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
|
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
|
||||||
|
@ -944,8 +1000,8 @@ void ServerEnvironment::step(float dtime)
|
||||||
// update lighting
|
// update lighting
|
||||||
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
i = modified_blocks.getIterator();
|
i = modified_blocks.getIterator();
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
||||||
}
|
}
|
||||||
|
@ -955,16 +1011,15 @@ void ServerEnvironment::step(float dtime)
|
||||||
MapEditEvent event;
|
MapEditEvent event;
|
||||||
event.type = MEET_OTHER;
|
event.type = MEET_OTHER;
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
i = modified_blocks.getIterator();
|
i = modified_blocks.getIterator();
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
v3s16 p = i.getNode()->getKey();
|
v3s16 p = i.getNode()->getKey();
|
||||||
event.modified_blocks.insert(p, true);
|
event.modified_blocks.insert(p, true);
|
||||||
}
|
}
|
||||||
m_map->dispatchEvent(&event);
|
m_map->dispatchEvent(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -978,7 +1033,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
// 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;
|
||||||
m_send_recommended_timer += dtime;
|
m_send_recommended_timer += dtime;
|
||||||
if(m_send_recommended_timer > 0.15)
|
if(m_send_recommended_timer > 0.10)
|
||||||
{
|
{
|
||||||
m_send_recommended_timer = 0;
|
m_send_recommended_timer = 0;
|
||||||
send_recommended = true;
|
send_recommended = true;
|
||||||
|
@ -1020,7 +1075,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
TEST CODE
|
TEST CODE
|
||||||
*/
|
*/
|
||||||
#if 1
|
#if 0
|
||||||
m_random_spawn_timer -= dtime;
|
m_random_spawn_timer -= dtime;
|
||||||
if(m_random_spawn_timer < 0)
|
if(m_random_spawn_timer < 0)
|
||||||
{
|
{
|
||||||
|
@ -1042,7 +1097,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
pos = player->getPosition();
|
pos = player->getPosition();
|
||||||
pos += v3f(
|
pos += v3f(
|
||||||
myrand_range(-3,3)*BS,
|
myrand_range(-3,3)*BS,
|
||||||
0,
|
5,
|
||||||
myrand_range(-3,3)*BS
|
myrand_range(-3,3)*BS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1054,7 +1109,14 @@ void ServerEnvironment::step(float dtime)
|
||||||
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
||||||
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
||||||
//ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
|
//ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
|
||||||
ServerActiveObject *obj = new FireflySAO(this, 0, pos);
|
//ServerActiveObject *obj = new FireflySAO(this, 0, pos);
|
||||||
|
|
||||||
|
dstream<<DTIME<<"INFO: Server: Spawning MobV2SAO at "
|
||||||
|
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
|
||||||
|
|
||||||
|
Settings properties;
|
||||||
|
getMob_dungeon_master(properties);
|
||||||
|
ServerActiveObject *obj = new MobV2SAO(this, 0, pos, &properties);
|
||||||
addActiveObject(obj);
|
addActiveObject(obj);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1110,6 +1172,47 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
|
||||||
|
{
|
||||||
|
assert(obj);
|
||||||
|
|
||||||
|
v3f objectpos = obj->getBasePosition();
|
||||||
|
|
||||||
|
// The block in which the object resides in
|
||||||
|
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update the static data
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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
|
||||||
|
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||||
|
// Get or generate the block
|
||||||
|
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||||
|
|
||||||
|
bool succeeded = false;
|
||||||
|
|
||||||
|
if(block)
|
||||||
|
{
|
||||||
|
block->m_static_objects.insert(0, s_obj);
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD);
|
||||||
|
succeeded = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::addActiveObjectAsStatic: "
|
||||||
|
<<"Could not find or generate "
|
||||||
|
<<"a block for storing static object"<<std::endl;
|
||||||
|
succeeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete obj;
|
||||||
|
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Finds out what new objects have been added to
|
Finds out what new objects have been added to
|
||||||
inside a radius around a position
|
inside a radius around a position
|
||||||
|
@ -1894,9 +1997,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||||
|
|
||||||
obj->setId(id);
|
obj->setId(id);
|
||||||
|
|
||||||
addActiveObject(obj);
|
|
||||||
|
|
||||||
obj->initialize(init_data);
|
obj->initialize(init_data);
|
||||||
|
|
||||||
|
addActiveObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientEnvironment::removeActiveObject(u16 id)
|
void ClientEnvironment::removeActiveObject(u16 id)
|
||||||
|
|
|
@ -175,6 +175,14 @@ public:
|
||||||
*/
|
*/
|
||||||
u16 addActiveObject(ServerActiveObject *object);
|
u16 addActiveObject(ServerActiveObject *object);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add an active object as a static object to the corresponding
|
||||||
|
MapBlock.
|
||||||
|
Caller allocates memory, ServerEnvironment frees memory.
|
||||||
|
Return value: true if succeeded, false if failed.
|
||||||
|
*/
|
||||||
|
bool addActiveObjectAsStatic(ServerActiveObject *object);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find out what new objects have been added to
|
Find out what new objects have been added to
|
||||||
inside a radius around a position
|
inside a radius around a position
|
||||||
|
|
185
src/game.cpp
185
src/game.cpp
|
@ -89,27 +89,6 @@ u16 g_selected_item = 0;
|
||||||
Text input system
|
Text input system
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct TextDestSign : public TextDest
|
|
||||||
{
|
|
||||||
TextDestSign(v3s16 blockpos, s16 id, Client *client)
|
|
||||||
{
|
|
||||||
m_blockpos = blockpos;
|
|
||||||
m_id = id;
|
|
||||||
m_client = client;
|
|
||||||
}
|
|
||||||
void gotText(std::wstring text)
|
|
||||||
{
|
|
||||||
std::string ntext = wide_to_narrow(text);
|
|
||||||
dstream<<"Changing text of a sign object: "
|
|
||||||
<<ntext<<std::endl;
|
|
||||||
m_client->sendSignText(m_blockpos, m_id, ntext);
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 m_blockpos;
|
|
||||||
s16 m_id;
|
|
||||||
Client *m_client;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextDestChat : public TextDest
|
struct TextDestChat : public TextDest
|
||||||
{
|
{
|
||||||
TextDestChat(Client *client)
|
TextDestChat(Client *client)
|
||||||
|
@ -298,7 +277,7 @@ void getPointedNode(Client *client, v3f player_position,
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(player_position, BS);
|
v3s16 pos_i = floatToInt(player_position, BS);
|
||||||
|
|
||||||
/*std::cout<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
/*dstream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
s16 a = d;
|
s16 a = d;
|
||||||
|
@ -705,7 +684,7 @@ void the_game(
|
||||||
SharedPtr<Server> server;
|
SharedPtr<Server> server;
|
||||||
if(address == ""){
|
if(address == ""){
|
||||||
draw_load_screen(L"Creating server...", driver, font);
|
draw_load_screen(L"Creating server...", driver, font);
|
||||||
std::cout<<DTIME<<"Creating server"<<std::endl;
|
dstream<<DTIME<<"Creating server"<<std::endl;
|
||||||
server = new Server(map_dir, configpath);
|
server = new Server(map_dir, configpath);
|
||||||
server->start(port);
|
server->start(port);
|
||||||
}
|
}
|
||||||
|
@ -715,7 +694,7 @@ void the_game(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
draw_load_screen(L"Creating client...", driver, font);
|
draw_load_screen(L"Creating client...", driver, font);
|
||||||
std::cout<<DTIME<<"Creating client"<<std::endl;
|
dstream<<DTIME<<"Creating client"<<std::endl;
|
||||||
MapDrawControl draw_control;
|
MapDrawControl draw_control;
|
||||||
Client client(device, playername.c_str(), password, draw_control);
|
Client client(device, playername.c_str(), password, draw_control);
|
||||||
|
|
||||||
|
@ -730,7 +709,7 @@ void the_game(
|
||||||
}
|
}
|
||||||
catch(ResolveError &e)
|
catch(ResolveError &e)
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Couldn't resolve address"<<std::endl;
|
dstream<<DTIME<<"Couldn't resolve address"<<std::endl;
|
||||||
//return 0;
|
//return 0;
|
||||||
error_message = L"Couldn't resolve address";
|
error_message = L"Couldn't resolve address";
|
||||||
//gui_loadingtext->remove();
|
//gui_loadingtext->remove();
|
||||||
|
@ -799,12 +778,12 @@ void the_game(
|
||||||
{
|
{
|
||||||
error_message = L"Access denied. Reason: "
|
error_message = L"Access denied. Reason: "
|
||||||
+client.accessDeniedReason();
|
+client.accessDeniedReason();
|
||||||
std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl;
|
dstream<<DTIME<<wide_to_narrow(error_message)<<std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_message = L"Connection timed out.";
|
error_message = L"Connection timed out.";
|
||||||
std::cout<<DTIME<<"Timed out."<<std::endl;
|
dstream<<DTIME<<"Timed out."<<std::endl;
|
||||||
}
|
}
|
||||||
//gui_loadingtext->remove();
|
//gui_loadingtext->remove();
|
||||||
return;
|
return;
|
||||||
|
@ -924,8 +903,16 @@ void the_game(
|
||||||
|
|
||||||
core::list<float> frametime_log;
|
core::list<float> frametime_log;
|
||||||
|
|
||||||
|
float nodig_delay_counter = 0.0;
|
||||||
|
float dig_time = 0.0;
|
||||||
|
u16 dig_index = 0;
|
||||||
|
v3s16 nodepos_old(-32768,-32768,-32768);
|
||||||
|
|
||||||
float damage_flash_timer = 0;
|
float damage_flash_timer = 0;
|
||||||
s16 farmesh_range = 20*MAP_BLOCKSIZE;
|
s16 farmesh_range = 20*MAP_BLOCKSIZE;
|
||||||
|
|
||||||
|
const float object_hit_delay = 0.5;
|
||||||
|
float object_hit_delay_timer = 0.0;
|
||||||
|
|
||||||
bool invert_mouse = g_settings->getBool("invert_mouse");
|
bool invert_mouse = g_settings->getBool("invert_mouse");
|
||||||
|
|
||||||
|
@ -952,7 +939,7 @@ void the_game(
|
||||||
{
|
{
|
||||||
error_message = L"Access denied. Reason: "
|
error_message = L"Access denied. Reason: "
|
||||||
+client.accessDeniedReason();
|
+client.accessDeniedReason();
|
||||||
std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl;
|
dstream<<DTIME<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,7 +1005,7 @@ void the_game(
|
||||||
busytime = busytime_u32 / 1000.0;
|
busytime = busytime_u32 / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout<<"busytime_u32="<<busytime_u32<<std::endl;
|
//dstream<<"busytime_u32="<<busytime_u32<<std::endl;
|
||||||
|
|
||||||
// Necessary for device->getTimer()->getTime()
|
// Necessary for device->getTimer()->getTime()
|
||||||
device->run();
|
device->run();
|
||||||
|
@ -1053,6 +1040,10 @@ void the_game(
|
||||||
dtime = 0;
|
dtime = 0;
|
||||||
lasttime = time;
|
lasttime = time;
|
||||||
|
|
||||||
|
/* Run timers */
|
||||||
|
|
||||||
|
object_hit_delay_timer -= dtime;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Log frametime for visualization
|
Log frametime for visualization
|
||||||
*/
|
*/
|
||||||
|
@ -1067,8 +1058,8 @@ void the_game(
|
||||||
Visualize frametime in terminal
|
Visualize frametime in terminal
|
||||||
*/
|
*/
|
||||||
/*for(u32 i=0; i<dtime*400; i++)
|
/*for(u32 i=0; i<dtime*400; i++)
|
||||||
std::cout<<"X";
|
dstream<<"X";
|
||||||
std::cout<<std::endl;*/
|
dstream<<std::endl;*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Time average and jitter calculation
|
Time average and jitter calculation
|
||||||
|
@ -1133,7 +1124,7 @@ void the_game(
|
||||||
if(counter < 0)
|
if(counter < 0)
|
||||||
{
|
{
|
||||||
counter = 30.0;
|
counter = 30.0;
|
||||||
client.printDebugInfo(std::cout);
|
client.printDebugInfo(dstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1350,7 @@ void the_game(
|
||||||
}
|
}
|
||||||
|
|
||||||
if(first_loop_after_window_activation){
|
if(first_loop_after_window_activation){
|
||||||
//std::cout<<"window active, first loop"<<std::endl;
|
//dstream<<"window active, first loop"<<std::endl;
|
||||||
first_loop_after_window_activation = false;
|
first_loop_after_window_activation = false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -1367,7 +1358,7 @@ void the_game(
|
||||||
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
||||||
if(invert_mouse)
|
if(invert_mouse)
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
//std::cout<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
//dstream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
||||||
|
|
||||||
/*const float keyspeed = 500;
|
/*const float keyspeed = 500;
|
||||||
if(input->isKeyDown(irr::KEY_UP))
|
if(input->isKeyDown(irr::KEY_UP))
|
||||||
|
@ -1391,7 +1382,7 @@ void the_game(
|
||||||
if(device->getCursorControl()->isVisible() == false)
|
if(device->getCursorControl()->isVisible() == false)
|
||||||
device->getCursorControl()->setVisible(true);
|
device->getCursorControl()->setVisible(true);
|
||||||
|
|
||||||
//std::cout<<"window inactive"<<std::endl;
|
//dstream<<"window inactive"<<std::endl;
|
||||||
first_loop_after_window_activation = true;
|
first_loop_after_window_activation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,71 +1491,23 @@ void the_game(
|
||||||
core::line3d<f32> shootline(camera_position,
|
core::line3d<f32> shootline(camera_position,
|
||||||
camera_position + camera_direction * BS * (d+1));
|
camera_position + camera_direction * BS * (d+1));
|
||||||
|
|
||||||
MapBlockObject *selected_object = client.getSelectedObject
|
|
||||||
(d*BS, camera_position, shootline);
|
|
||||||
|
|
||||||
ClientActiveObject *selected_active_object
|
ClientActiveObject *selected_active_object
|
||||||
= client.getSelectedActiveObject
|
= client.getSelectedActiveObject
|
||||||
(d*BS, camera_position, shootline);
|
(d*BS, camera_position, shootline);
|
||||||
|
|
||||||
|
bool left_punch = false;
|
||||||
|
bool left_punch_muted = false;
|
||||||
|
|
||||||
if(selected_object != NULL)
|
if(selected_active_object != NULL)
|
||||||
{
|
{
|
||||||
//dstream<<"Client returned selected_object != NULL"<<std::endl;
|
/* Clear possible cracking animation */
|
||||||
|
if(nodepos_old != v3s16(-32768,-32768,-32768))
|
||||||
core::aabbox3d<f32> box_on_map
|
|
||||||
= selected_object->getSelectionBoxOnMap();
|
|
||||||
|
|
||||||
hilightboxes.push_back(box_on_map);
|
|
||||||
|
|
||||||
infotext = narrow_to_wide(selected_object->infoText());
|
|
||||||
|
|
||||||
if(input->getLeftClicked())
|
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Left-clicked object"<<std::endl;
|
client.clearTempMod(nodepos_old);
|
||||||
client.clickObject(0, selected_object->getBlock()->getPos(),
|
dig_time = 0.0;
|
||||||
selected_object->getId(), g_selected_item);
|
nodepos_old = v3s16(-32768,-32768,-32768);
|
||||||
}
|
}
|
||||||
else if(input->getRightClicked())
|
|
||||||
{
|
|
||||||
std::cout<<DTIME<<"Right-clicked object"<<std::endl;
|
|
||||||
/*
|
|
||||||
Check if we want to modify the object ourselves
|
|
||||||
*/
|
|
||||||
if(selected_object->getTypeId() == MAPBLOCKOBJECT_TYPE_SIGN)
|
|
||||||
{
|
|
||||||
dstream<<"Sign object right-clicked"<<std::endl;
|
|
||||||
|
|
||||||
if(random_input == false)
|
|
||||||
{
|
|
||||||
// Get a new text for it
|
|
||||||
|
|
||||||
TextDest *dest = new TextDestSign(
|
|
||||||
selected_object->getBlock()->getPos(),
|
|
||||||
selected_object->getId(),
|
|
||||||
&client);
|
|
||||||
|
|
||||||
SignObject *sign_object = (SignObject*)selected_object;
|
|
||||||
|
|
||||||
std::wstring wtext =
|
|
||||||
narrow_to_wide(sign_object->getText());
|
|
||||||
|
|
||||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
|
||||||
&g_menumgr, dest,
|
|
||||||
wtext))->drop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Otherwise pass the event to the server as-is
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client.clickObject(1, selected_object->getBlock()->getPos(),
|
|
||||||
selected_object->getId(), g_selected_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(selected_active_object != NULL)
|
|
||||||
{
|
|
||||||
//dstream<<"Client returned selected_active_object != NULL"<<std::endl;
|
//dstream<<"Client returned selected_active_object != NULL"<<std::endl;
|
||||||
|
|
||||||
core::aabbox3d<f32> *selection_box
|
core::aabbox3d<f32> *selection_box
|
||||||
|
@ -1579,21 +1522,31 @@ void the_game(
|
||||||
selection_box->MinEdge + pos,
|
selection_box->MinEdge + pos,
|
||||||
selection_box->MaxEdge + pos
|
selection_box->MaxEdge + pos
|
||||||
);
|
);
|
||||||
|
|
||||||
hilightboxes.push_back(box_on_map);
|
if(selected_active_object->doShowSelectionBox())
|
||||||
|
hilightboxes.push_back(box_on_map);
|
||||||
|
|
||||||
//infotext = narrow_to_wide("A ClientActiveObject");
|
//infotext = narrow_to_wide("A ClientActiveObject");
|
||||||
infotext = narrow_to_wide(selected_active_object->infoText());
|
infotext = narrow_to_wide(selected_active_object->infoText());
|
||||||
|
|
||||||
if(input->getLeftClicked())
|
//if(input->getLeftClicked())
|
||||||
|
if(input->getLeftState())
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Left-clicked object"<<std::endl;
|
if(object_hit_delay_timer <= 0.0){
|
||||||
client.clickActiveObject(0,
|
dstream<<DTIME<<"Left-clicked object"<<std::endl;
|
||||||
selected_active_object->getId(), g_selected_item);
|
client.clickActiveObject(0,
|
||||||
|
selected_active_object->getId(), g_selected_item);
|
||||||
|
object_hit_delay_timer = object_hit_delay;
|
||||||
|
left_punch = true;
|
||||||
|
} else {
|
||||||
|
dstream<<DTIME<<"Left-clicked object faster than allowed"
|
||||||
|
<<std::endl;
|
||||||
|
left_punch_muted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(input->getRightClicked())
|
else if(input->getRightClicked())
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Right-clicked object"<<std::endl;
|
dstream<<DTIME<<"Right-clicked object"<<std::endl;
|
||||||
client.clickActiveObject(1,
|
client.clickActiveObject(1,
|
||||||
selected_active_object->getId(), g_selected_item);
|
selected_active_object->getId(), g_selected_item);
|
||||||
}
|
}
|
||||||
|
@ -1616,15 +1569,14 @@ void the_game(
|
||||||
nodepos, neighbourpos,
|
nodepos, neighbourpos,
|
||||||
nodehilightbox, d);
|
nodehilightbox, d);
|
||||||
|
|
||||||
static float nodig_delay_counter = 0.0;
|
if(!nodefound){
|
||||||
|
if(nodepos_old != v3s16(-32768,-32768,-32768))
|
||||||
if(nodefound)
|
{
|
||||||
{
|
client.clearTempMod(nodepos_old);
|
||||||
static v3s16 nodepos_old(-32768,-32768,-32768);
|
dig_time = 0.0;
|
||||||
|
nodepos_old = v3s16(-32768,-32768,-32768);
|
||||||
static float dig_time = 0.0;
|
}
|
||||||
static u16 dig_index = 0;
|
} else {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Visualize selection
|
Visualize selection
|
||||||
*/
|
*/
|
||||||
|
@ -1661,13 +1613,14 @@ void the_game(
|
||||||
{
|
{
|
||||||
if(nodepos != nodepos_old)
|
if(nodepos != nodepos_old)
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
|
dstream<<DTIME<<"Pointing at ("<<nodepos.X<<","
|
||||||
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
|
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
|
||||||
|
|
||||||
if(nodepos_old != v3s16(-32768,-32768,-32768))
|
if(nodepos_old != v3s16(-32768,-32768,-32768))
|
||||||
{
|
{
|
||||||
client.clearTempMod(nodepos_old);
|
client.clearTempMod(nodepos_old);
|
||||||
dig_time = 0.0;
|
dig_time = 0.0;
|
||||||
|
nodepos_old = v3s16(-32768,-32768,-32768);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1771,7 +1724,7 @@ void the_game(
|
||||||
|
|
||||||
if(input->getRightClicked())
|
if(input->getRightClicked())
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
|
dstream<<DTIME<<"Ground right-clicked"<<std::endl;
|
||||||
|
|
||||||
// If metadata provides an inventory view, activate it
|
// If metadata provides an inventory view, activate it
|
||||||
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
|
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
|
||||||
|
@ -1836,7 +1789,7 @@ void the_game(
|
||||||
|
|
||||||
} // selected_object == NULL
|
} // selected_object == NULL
|
||||||
|
|
||||||
if(input->getLeftClicked())
|
if(left_punch || (input->getLeftClicked() && !left_punch_muted))
|
||||||
{
|
{
|
||||||
camera.setDigging(0); // left click animation
|
camera.setDigging(0); // left click animation
|
||||||
}
|
}
|
||||||
|
@ -1846,13 +1799,13 @@ void the_game(
|
||||||
|
|
||||||
if(input->getLeftReleased())
|
if(input->getLeftReleased())
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Left button released (stopped digging)"
|
dstream<<DTIME<<"Left button released (stopped digging)"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);
|
client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);
|
||||||
}
|
}
|
||||||
if(input->getRightReleased())
|
if(input->getRightReleased())
|
||||||
{
|
{
|
||||||
//std::cout<<DTIME<<"Right released"<<std::endl;
|
//dstream<<DTIME<<"Right released"<<std::endl;
|
||||||
// Nothing here
|
// Nothing here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2097,7 +2050,7 @@ void the_game(
|
||||||
{
|
{
|
||||||
client.selectPlayerItem(g_selected_item);
|
client.selectPlayerItem(g_selected_item);
|
||||||
old_selected_item = g_selected_item;
|
old_selected_item = g_selected_item;
|
||||||
//std::cout<<"Updating local inventory"<<std::endl;
|
//dstream<<"Updating local inventory"<<std::endl;
|
||||||
client.getLocalInventory(local_inventory);
|
client.getLocalInventory(local_inventory);
|
||||||
|
|
||||||
// Update wielded tool
|
// Update wielded tool
|
||||||
|
@ -2136,7 +2089,7 @@ void the_game(
|
||||||
|
|
||||||
//timer3.stop();
|
//timer3.stop();
|
||||||
|
|
||||||
//std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;
|
//dstream<<DTIME<<"smgr->drawAll()"<<std::endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
TimeTaker timer("smgr");
|
TimeTaker timer("smgr");
|
||||||
|
@ -2162,7 +2115,7 @@ void the_game(
|
||||||
for(core::list< core::aabbox3d<f32> >::Iterator i=hilightboxes.begin();
|
for(core::list< core::aabbox3d<f32> >::Iterator i=hilightboxes.begin();
|
||||||
i != hilightboxes.end(); i++)
|
i != hilightboxes.end(); i++)
|
||||||
{
|
{
|
||||||
/*std::cout<<"hilightbox min="
|
/*dstream<<"hilightbox min="
|
||||||
<<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
|
<<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
|
||||||
<<" max="
|
<<" max="
|
||||||
<<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")"
|
<<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")"
|
||||||
|
|
|
@ -97,7 +97,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||||
{
|
{
|
||||||
std::string inventorystring;
|
std::string inventorystring;
|
||||||
std::getline(is, inventorystring, '|');
|
std::getline(is, inventorystring, '|');
|
||||||
return new MapBlockObjectItem(inventorystring);
|
throw SerializationError("MBOItem not supported anymore");
|
||||||
}
|
}
|
||||||
else if(name == "CraftItem")
|
else if(name == "CraftItem")
|
||||||
{
|
{
|
||||||
|
@ -219,77 +219,6 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
MapBlockObjectItem DEPRECATED
|
|
||||||
TODO: Remove
|
|
||||||
*/
|
|
||||||
#ifndef SERVER
|
|
||||||
video::ITexture * MapBlockObjectItem::getImage() const
|
|
||||||
{
|
|
||||||
if(m_inventorystring.substr(0,3) == "Rat")
|
|
||||||
return g_texturesource->getTextureRaw("rat.png");
|
|
||||||
|
|
||||||
if(m_inventorystring.substr(0,4) == "Sign")
|
|
||||||
return g_texturesource->getTextureRaw("sign.png");
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
std::string MapBlockObjectItem::getText()
|
|
||||||
{
|
|
||||||
if(m_inventorystring.substr(0,3) == "Rat")
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if(m_inventorystring.substr(0,4) == "Sign")
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return "obj";
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject * MapBlockObjectItem::createObject
|
|
||||||
(v3f pos, f32 player_yaw, f32 player_pitch)
|
|
||||||
{
|
|
||||||
std::istringstream is(m_inventorystring);
|
|
||||||
std::string name;
|
|
||||||
std::getline(is, name, ' ');
|
|
||||||
|
|
||||||
if(name == "None")
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else if(name == "Sign")
|
|
||||||
{
|
|
||||||
std::string text;
|
|
||||||
std::getline(is, text, '|');
|
|
||||||
SignObject *obj = new SignObject(NULL, -1, pos);
|
|
||||||
obj->setText(text);
|
|
||||||
obj->setYaw(-player_yaw);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
else if(name == "Rat")
|
|
||||||
{
|
|
||||||
RatObject *obj = new RatObject(NULL, -1, pos);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
else if(name == "ItemObj")
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Now we are an inventory item containing the serialization
|
|
||||||
string of an object that contains the serialization
|
|
||||||
string of an inventory item. Fuck this.
|
|
||||||
*/
|
|
||||||
//assert(0);
|
|
||||||
dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
|
|
||||||
<<"because an item-object should never be inside "
|
|
||||||
<<"an object-item."<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inventory
|
Inventory
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "mapblockobject.h"
|
|
||||||
#include "main.h" // For g_materials
|
#include "main.h" // For g_materials
|
||||||
#include "mapnode.h" // For content_t
|
#include "mapnode.h" // For content_t
|
||||||
|
|
||||||
|
@ -196,56 +195,6 @@ private:
|
||||||
content_t m_content;
|
content_t m_content;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Remove
|
|
||||||
class MapBlockObjectItem : public InventoryItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MapBlockObjectItem(std::string inventorystring):
|
|
||||||
InventoryItem(1)
|
|
||||||
{
|
|
||||||
m_inventorystring = inventorystring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Implementation interface
|
|
||||||
*/
|
|
||||||
virtual const char* getName() const
|
|
||||||
{
|
|
||||||
return "MBOItem";
|
|
||||||
}
|
|
||||||
virtual void serialize(std::ostream &os) const
|
|
||||||
{
|
|
||||||
std::string sane_string(m_inventorystring);
|
|
||||||
str_replace_char(sane_string, '|', '?');
|
|
||||||
os<<getName();
|
|
||||||
os<<" ";
|
|
||||||
os<<sane_string;
|
|
||||||
os<<"|";
|
|
||||||
}
|
|
||||||
virtual InventoryItem* clone()
|
|
||||||
{
|
|
||||||
return new MapBlockObjectItem(m_inventorystring);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
video::ITexture * getImage() const;
|
|
||||||
#endif
|
|
||||||
std::string getText();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Special methods
|
|
||||||
*/
|
|
||||||
std::string getInventoryString()
|
|
||||||
{
|
|
||||||
return m_inventorystring;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject * createObject(v3f pos, f32 player_yaw, f32 player_pitch);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_inventorystring;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An item that is used as a mid-product when crafting.
|
An item that is used as a mid-product when crafting.
|
||||||
Subnames:
|
Subnames:
|
||||||
|
|
|
@ -36,7 +36,6 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
||||||
m_lighting_expired(true),
|
m_lighting_expired(true),
|
||||||
m_day_night_differs(false),
|
m_day_night_differs(false),
|
||||||
m_generated(false),
|
m_generated(false),
|
||||||
m_objects(this),
|
|
||||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_usage_timer(0)
|
m_usage_timer(0)
|
||||||
{
|
{
|
||||||
|
@ -434,18 +433,6 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
|
||||||
getPosRelative(), data_size);
|
getPosRelative(), data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Step objects
|
|
||||||
*/
|
|
||||||
m_objects.step(dtime, server, daynight_ratio);
|
|
||||||
|
|
||||||
//setChangedFlag();
|
|
||||||
raiseModified(MOD_STATE_WRITE_AT_UNLOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MapBlock::updateDayNightDiff()
|
void MapBlock::updateDayNightDiff()
|
||||||
{
|
{
|
||||||
if(data == NULL)
|
if(data == NULL)
|
||||||
|
@ -818,10 +805,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||||
|
|
||||||
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||||
{
|
{
|
||||||
// Versions up from 9 have block objects.
|
// Versions up from 9 have block objects. (DEPRECATED)
|
||||||
if(version >= 9)
|
if(version >= 9)
|
||||||
{
|
{
|
||||||
//serializeObjects(os, version); // DEPRECATED
|
|
||||||
// count=0
|
// count=0
|
||||||
writeU16(os, 0);
|
writeU16(os, 0);
|
||||||
}
|
}
|
||||||
|
@ -842,11 +828,17 @@ void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||||
void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
|
void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Versions up from 9 have block objects.
|
Versions up from 9 have block objects. (DEPRECATED)
|
||||||
*/
|
*/
|
||||||
if(version >= 9)
|
if(version >= 9)
|
||||||
{
|
{
|
||||||
updateObjects(is, version, NULL, 0);
|
u16 count = readU16(is);
|
||||||
|
// Not supported and length not known if count is not 0
|
||||||
|
if(count != 0){
|
||||||
|
dstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
|
||||||
|
<<"Ignoring stuff coming at and after MBOs"<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "mapblockobject.h"
|
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
#include "staticobject.h"
|
#include "staticobject.h"
|
||||||
|
@ -423,68 +422,6 @@ public:
|
||||||
// Copies data from VoxelManipulator getPosRelative()
|
// Copies data from VoxelManipulator getPosRelative()
|
||||||
void copyFrom(VoxelManipulator &dst);
|
void copyFrom(VoxelManipulator &dst);
|
||||||
|
|
||||||
/*
|
|
||||||
MapBlockObject stuff
|
|
||||||
DEPRECATED
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*void serializeObjects(std::ostream &os, u8 version)
|
|
||||||
{
|
|
||||||
m_objects.serialize(os, version);
|
|
||||||
}*/
|
|
||||||
// If smgr!=NULL, new objects are added to the scene
|
|
||||||
void updateObjects(std::istream &is, u8 version,
|
|
||||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
|
||||||
{
|
|
||||||
m_objects.update(is, version, smgr, daynight_ratio);
|
|
||||||
|
|
||||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
|
||||||
}
|
|
||||||
void clearObjects()
|
|
||||||
{
|
|
||||||
m_objects.clear();
|
|
||||||
|
|
||||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
|
||||||
}
|
|
||||||
void addObject(MapBlockObject *object)
|
|
||||||
throw(ContainerFullException, AlreadyExistsException)
|
|
||||||
{
|
|
||||||
m_objects.add(object);
|
|
||||||
|
|
||||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
|
||||||
}
|
|
||||||
void removeObject(s16 id)
|
|
||||||
{
|
|
||||||
m_objects.remove(id);
|
|
||||||
|
|
||||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
|
||||||
}
|
|
||||||
MapBlockObject * getObject(s16 id)
|
|
||||||
{
|
|
||||||
return m_objects.get(id);
|
|
||||||
}
|
|
||||||
JMutexAutoLock * getObjectLock()
|
|
||||||
{
|
|
||||||
return m_objects.getLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Moves objects, deletes objects and spawns new objects
|
|
||||||
*/
|
|
||||||
void stepObjects(float dtime, bool server, u32 daynight_ratio);
|
|
||||||
|
|
||||||
// origin is relative to block
|
|
||||||
void getObjects(v3f origin, f32 max_d,
|
|
||||||
core::array<DistanceSortedObject> &dest)
|
|
||||||
{
|
|
||||||
m_objects.getObjects(origin, max_d, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 getObjectCount()
|
|
||||||
{
|
|
||||||
return m_objects.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SERVER // Only on client
|
#ifndef SERVER // Only on client
|
||||||
/*
|
/*
|
||||||
Methods for setting temporary modifications to nodes for
|
Methods for setting temporary modifications to nodes for
|
||||||
|
@ -688,9 +625,6 @@ private:
|
||||||
|
|
||||||
bool m_generated;
|
bool m_generated;
|
||||||
|
|
||||||
// DEPRECATED
|
|
||||||
MapBlockObjectList m_objects;
|
|
||||||
|
|
||||||
#ifndef SERVER // Only on client
|
#ifndef SERVER // Only on client
|
||||||
/*
|
/*
|
||||||
Set to true if the mesh has been ordered to be updated
|
Set to true if the mesh has been ordered to be updated
|
||||||
|
|
|
@ -1,939 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest-c55
|
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file contains the DEPRECATED MapBlockObject system
|
|
||||||
|
|
||||||
#include "mapblockobject.h"
|
|
||||||
#include "mapblock.h"
|
|
||||||
// For object wrapping
|
|
||||||
#include "map.h"
|
|
||||||
#include "inventory.h"
|
|
||||||
#include "utility.h"
|
|
||||||
#include "mapblock.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
MapBlockObject
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This is here because it uses the MapBlock
|
|
||||||
v3f MapBlockObject::getAbsolutePos()
|
|
||||||
{
|
|
||||||
if(m_block == NULL)
|
|
||||||
return m_pos;
|
|
||||||
|
|
||||||
// getPosRelative gets nodepos relative to map origin
|
|
||||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
|
||||||
return blockpos + m_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObject::setBlockChanged()
|
|
||||||
{
|
|
||||||
if(m_block)
|
|
||||||
m_block->setChangedFlag();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
MovingObject
|
|
||||||
*/
|
|
||||||
|
|
||||||
v3f MovingObject::getAbsoluteShowPos()
|
|
||||||
{
|
|
||||||
if(m_block == NULL)
|
|
||||||
return m_pos;
|
|
||||||
|
|
||||||
// getPosRelative gets nodepos relative to map origin
|
|
||||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
|
||||||
return blockpos + m_showpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovingObject::move(float dtime, v3f acceleration)
|
|
||||||
{
|
|
||||||
DSTACKF("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
|
|
||||||
", dtime=%f, acc=(%f,%f,%f)",
|
|
||||||
__FUNCTION_NAME,
|
|
||||||
getTypeId(),
|
|
||||||
m_pos.X, m_pos.Y, m_pos.Z,
|
|
||||||
m_speed.X, m_speed.Y, m_speed.Z,
|
|
||||||
dtime,
|
|
||||||
acceleration.X, acceleration.Y, acceleration.Z
|
|
||||||
);
|
|
||||||
|
|
||||||
v3s16 oldpos_i = floatToInt(m_pos, BS);
|
|
||||||
|
|
||||||
if(m_block->isValidPosition(oldpos_i) == false)
|
|
||||||
{
|
|
||||||
// Should have wrapped, cancelling further movement.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No collisions if there is no collision box
|
|
||||||
if(m_collision_box == NULL)
|
|
||||||
{
|
|
||||||
m_speed += dtime * acceleration;
|
|
||||||
m_pos += m_speed * dtime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set insane speed to zero
|
|
||||||
// Otherwise there will be divides by zero and other silly stuff
|
|
||||||
if(m_speed.getLength() > 1000.0*BS)
|
|
||||||
m_speed = v3f(0,0,0);
|
|
||||||
|
|
||||||
// Limit speed to a reasonable value
|
|
||||||
float speed_limit = 20.0*BS;
|
|
||||||
if(m_speed.getLength() > speed_limit)
|
|
||||||
m_speed = m_speed * (speed_limit / m_speed.getLength());
|
|
||||||
|
|
||||||
v3f position = m_pos;
|
|
||||||
v3f oldpos = position;
|
|
||||||
|
|
||||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
|
||||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
|
||||||
|
|
||||||
// Maximum time increment (for collision detection etc)
|
|
||||||
// Allow 0.1 blocks per increment
|
|
||||||
// time = distance / speed
|
|
||||||
// NOTE: In the loop below collisions are detected at 0.15*BS radius
|
|
||||||
float speedlength = m_speed.getLength();
|
|
||||||
f32 dtime_max_increment;
|
|
||||||
if(fabs(speedlength) > 0.001)
|
|
||||||
dtime_max_increment = 0.05*BS / speedlength;
|
|
||||||
else
|
|
||||||
dtime_max_increment = 0.5;
|
|
||||||
|
|
||||||
m_touching_ground = false;
|
|
||||||
|
|
||||||
u32 loopcount = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
loopcount++;
|
|
||||||
|
|
||||||
f32 dtime_part;
|
|
||||||
if(dtime > dtime_max_increment)
|
|
||||||
dtime_part = dtime_max_increment;
|
|
||||||
else
|
|
||||||
dtime_part = dtime;
|
|
||||||
dtime -= dtime_part;
|
|
||||||
|
|
||||||
// Begin of dtime limited code
|
|
||||||
|
|
||||||
m_speed += acceleration * dtime_part;
|
|
||||||
position += m_speed * dtime_part;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Collision detection
|
|
||||||
*/
|
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(position, BS);
|
|
||||||
|
|
||||||
// The loop length is limited to the object moving a distance
|
|
||||||
f32 d = (float)BS * 0.15;
|
|
||||||
|
|
||||||
core::aabbox3d<f32> objectbox(
|
|
||||||
m_collision_box->MinEdge + position,
|
|
||||||
m_collision_box->MaxEdge + position
|
|
||||||
);
|
|
||||||
|
|
||||||
core::aabbox3d<f32> objectbox_old(
|
|
||||||
m_collision_box->MinEdge + oldpos,
|
|
||||||
m_collision_box->MaxEdge + oldpos
|
|
||||||
);
|
|
||||||
|
|
||||||
//TODO: Get these ranges from somewhere
|
|
||||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
|
||||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
|
||||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
MapNode n = m_block->getNodeParent(v3s16(x,y,z));
|
|
||||||
if(content_features(n).walkable == false)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
// Doing nothing here will block the object from
|
|
||||||
// walking over map borders
|
|
||||||
}
|
|
||||||
|
|
||||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
|
||||||
|
|
||||||
// See if the object is touching ground
|
|
||||||
if(
|
|
||||||
fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d
|
|
||||||
&& nodebox.MaxEdge.X-d > objectbox.MinEdge.X
|
|
||||||
&& nodebox.MinEdge.X+d < objectbox.MaxEdge.X
|
|
||||||
&& nodebox.MaxEdge.Z-d > objectbox.MinEdge.Z
|
|
||||||
&& nodebox.MinEdge.Z+d < objectbox.MaxEdge.Z
|
|
||||||
){
|
|
||||||
m_touching_ground = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(objectbox.intersectsWithBox(nodebox))
|
|
||||||
{
|
|
||||||
|
|
||||||
v3f dirs[3] = {
|
|
||||||
v3f(0,0,1), // back
|
|
||||||
v3f(0,1,0), // top
|
|
||||||
v3f(1,0,0), // right
|
|
||||||
};
|
|
||||||
for(u16 i=0; i<3; i++)
|
|
||||||
{
|
|
||||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
|
||||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
|
||||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[i]);
|
|
||||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[i]);
|
|
||||||
f32 playermax_old = objectbox_old.MaxEdge.dotProduct(dirs[i]);
|
|
||||||
f32 playermin_old = objectbox_old.MinEdge.dotProduct(dirs[i]);
|
|
||||||
|
|
||||||
bool main_edge_collides =
|
|
||||||
((nodemax > playermin && nodemax <= playermin_old + d
|
|
||||||
&& m_speed.dotProduct(dirs[i]) < 0)
|
|
||||||
||
|
|
||||||
(nodemin < playermax && nodemin >= playermax_old - d
|
|
||||||
&& m_speed.dotProduct(dirs[i]) > 0));
|
|
||||||
|
|
||||||
bool other_edges_collide = true;
|
|
||||||
for(u16 j=0; j<3; j++)
|
|
||||||
{
|
|
||||||
if(j == i)
|
|
||||||
continue;
|
|
||||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
|
||||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
|
||||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[j]);
|
|
||||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[j]);
|
|
||||||
if(!(nodemax - d > playermin && nodemin + d < playermax))
|
|
||||||
{
|
|
||||||
other_edges_collide = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(main_edge_collides && other_edges_collide)
|
|
||||||
{
|
|
||||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
|
||||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
|
||||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // if(objectbox.intersectsWithBox(nodebox))
|
|
||||||
} // for y
|
|
||||||
|
|
||||||
} // End of dtime limited loop
|
|
||||||
while(dtime > 0.001);
|
|
||||||
|
|
||||||
m_pos = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovingObject::simpleMove(float dtime)
|
|
||||||
{
|
|
||||||
m_pos_animation_time_counter += dtime;
|
|
||||||
m_pos_animation_counter += dtime;
|
|
||||||
v3f movevector = m_pos - m_oldpos;
|
|
||||||
f32 moveratio;
|
|
||||||
if(m_pos_animation_time < 0.001)
|
|
||||||
moveratio = 1.0;
|
|
||||||
else
|
|
||||||
moveratio = m_pos_animation_counter / m_pos_animation_time;
|
|
||||||
if(moveratio > 1.5)
|
|
||||||
moveratio = 1.5;
|
|
||||||
m_showpos = m_oldpos + movevector * moveratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
/*
|
|
||||||
RatObject
|
|
||||||
*/
|
|
||||||
void RatObject::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
buf->getMaterial().setTexture
|
|
||||||
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
ItemObject
|
|
||||||
*/
|
|
||||||
#ifndef SERVER
|
|
||||||
void ItemObject::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
// Get image of item for showing
|
|
||||||
video::ITexture *texture = getItemImage();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a mesh
|
|
||||||
*/
|
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
/*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
buf->getMaterial().setTexture(0, texture);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
}
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
// Set it to use the materials of the meshbuffers directly.
|
|
||||||
// This is needed for changing the texture in the future
|
|
||||||
((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
|
|
||||||
mesh->drop();
|
|
||||||
|
|
||||||
updateSceneNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
video::ITexture * ItemObject::getItemImage()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Create an inventory item to see what is its image
|
|
||||||
*/
|
|
||||||
video::ITexture *texture = NULL;
|
|
||||||
InventoryItem *item = createInventoryItem();
|
|
||||||
if(item)
|
|
||||||
texture = item->getImage();
|
|
||||||
if(item)
|
|
||||||
delete item;
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InventoryItem * ItemObject::createInventoryItem()
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
std::istringstream is(m_itemstring, std::ios_base::binary);
|
|
||||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
|
||||||
dstream<<__FUNCTION_NAME<<": m_itemstring=\""
|
|
||||||
<<m_itemstring<<"\" -> item="<<item
|
|
||||||
<<std::endl;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
catch(SerializationError &e)
|
|
||||||
{
|
|
||||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
|
||||||
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
PlayerObject
|
|
||||||
*/
|
|
||||||
#ifndef SERVER
|
|
||||||
void PlayerObject::addToScene(scene::ISceneManager *smgr)
|
|
||||||
{
|
|
||||||
if(m_node != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
|
||||||
|
|
||||||
// Attach a simple mesh to the player for showing an image
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
|
||||||
{ // Front
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
}
|
|
||||||
{ // Back
|
|
||||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
|
||||||
video::S3DVertex vertices[4] =
|
|
||||||
{
|
|
||||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
|
||||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
|
||||||
};
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
// Set material
|
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
|
||||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
|
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
// Add to mesh
|
|
||||||
mesh->addMeshBuffer(buf);
|
|
||||||
buf->drop();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
|
||||||
mesh->drop();
|
|
||||||
updateNodePos();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
MapBlockObjectList
|
|
||||||
*/
|
|
||||||
|
|
||||||
MapBlockObjectList::MapBlockObjectList(MapBlock *block):
|
|
||||||
m_block(block)
|
|
||||||
{
|
|
||||||
m_mutex.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObjectList::~MapBlockObjectList()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The serialization format:
|
|
||||||
[0] u16 number of entries
|
|
||||||
[2] entries (id, typeId, parameters)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MapBlockObjectList::serialize(std::ostream &os, u8 version)
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
u8 buf[2];
|
|
||||||
writeU16(buf, m_objects.size());
|
|
||||||
os.write((char*)buf, 2);
|
|
||||||
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
i.getNode()->getValue()->serialize(os, version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::update(std::istream &is, u8 version,
|
|
||||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Collect all existing ids to a set.
|
|
||||||
|
|
||||||
As things are updated, they are removed from this.
|
|
||||||
|
|
||||||
All remaining ones are deleted.
|
|
||||||
*/
|
|
||||||
core::map<s16, bool> ids_to_delete;
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
ids_to_delete.insert(i.getNode()->getKey(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 buf[6];
|
|
||||||
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
u16 count = readU16(buf);
|
|
||||||
|
|
||||||
for(u16 i=0; i<count; i++)
|
|
||||||
{
|
|
||||||
// Read id
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
s16 id = readS16(buf);
|
|
||||||
|
|
||||||
// Read position
|
|
||||||
// stored as x1000/BS v3s16
|
|
||||||
is.read((char*)buf, 6);
|
|
||||||
v3s16 pos_i = readV3S16(buf);
|
|
||||||
v3f pos((f32)pos_i.X/1000*BS,
|
|
||||||
(f32)pos_i.Y/1000*BS,
|
|
||||||
(f32)pos_i.Z/1000*BS);
|
|
||||||
|
|
||||||
// Read typeId
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
u16 type_id = readU16(buf);
|
|
||||||
|
|
||||||
bool create_new = false;
|
|
||||||
|
|
||||||
// Find an object with the id
|
|
||||||
core::map<s16, MapBlockObject*>::Node *n;
|
|
||||||
n = m_objects.find(id);
|
|
||||||
// If no entry is found for id
|
|
||||||
if(n == NULL)
|
|
||||||
{
|
|
||||||
// Insert dummy pointer node
|
|
||||||
m_objects.insert(id, NULL);
|
|
||||||
// Get node
|
|
||||||
n = m_objects.find(id);
|
|
||||||
// A new object will be created at this node
|
|
||||||
create_new = true;
|
|
||||||
}
|
|
||||||
// If type_id differs
|
|
||||||
else if(n->getValue()->getTypeId() != type_id)
|
|
||||||
{
|
|
||||||
// Delete old object
|
|
||||||
delete n->getValue();
|
|
||||||
// A new object will be created at this node
|
|
||||||
create_new = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject *obj = NULL;
|
|
||||||
|
|
||||||
if(create_new)
|
|
||||||
{
|
|
||||||
/*dstream<<"MapBlockObjectList adding new object"
|
|
||||||
" id="<<id
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
|
|
||||||
{
|
|
||||||
obj = new SignObject(m_block, id, pos);
|
|
||||||
}
|
|
||||||
else if(type_id == MAPBLOCKOBJECT_TYPE_RAT)
|
|
||||||
{
|
|
||||||
obj = new RatObject(m_block, id, pos);
|
|
||||||
}
|
|
||||||
else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
|
|
||||||
{
|
|
||||||
obj = new ItemObject(m_block, id, pos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is fatal because we cannot know the length
|
|
||||||
// of the object's data
|
|
||||||
throw SerializationError
|
|
||||||
("MapBlockObjectList::update(): Unknown MapBlockObject type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(smgr != NULL)
|
|
||||||
//obj->addToScene(smgr, daynight_ratio);
|
|
||||||
obj->addToScene(smgr);
|
|
||||||
|
|
||||||
n->setValue(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obj = n->getValue();
|
|
||||||
obj->updatePos(pos);
|
|
||||||
/*if(daynight_ratio != m_last_update_daynight_ratio)
|
|
||||||
{
|
|
||||||
obj->removeFromScene();
|
|
||||||
obj->addToScene(smgr, daynight_ratio);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now there is an object in obj.
|
|
||||||
// Update it.
|
|
||||||
|
|
||||||
obj->update(is, version);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update light on client
|
|
||||||
*/
|
|
||||||
if(smgr != NULL)
|
|
||||||
{
|
|
||||||
u8 light = LIGHT_MAX;
|
|
||||||
try{
|
|
||||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
|
||||||
MapNode n = m_block->getNodeParent(relpos_i);
|
|
||||||
light = n.getLightBlend(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e) {}
|
|
||||||
obj->updateLight(light);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove from deletion list
|
|
||||||
if(ids_to_delete.find(id) != NULL)
|
|
||||||
ids_to_delete.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all objects whose ids_to_delete remain in ids_to_delete
|
|
||||||
for(core::map<s16, bool>::Iterator
|
|
||||||
i = ids_to_delete.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
s16 id = i.getNode()->getKey();
|
|
||||||
|
|
||||||
/*dstream<<"MapBlockObjectList deleting object"
|
|
||||||
" id="<<id
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
MapBlockObject *obj = m_objects[id];
|
|
||||||
obj->removeFromScene();
|
|
||||||
delete obj;
|
|
||||||
m_objects.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_last_update_daynight_ratio = daynight_ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 MapBlockObjectList::getFreeId() throw(ContainerFullException)
|
|
||||||
{
|
|
||||||
s16 id = 0;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
if(m_objects.find(id) == NULL)
|
|
||||||
return id;
|
|
||||||
if(id == 32767)
|
|
||||||
throw ContainerFullException
|
|
||||||
("MapBlockObjectList doesn't fit more objects");
|
|
||||||
id++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::add(MapBlockObject *object)
|
|
||||||
throw(ContainerFullException, AlreadyExistsException)
|
|
||||||
{
|
|
||||||
if(object == NULL)
|
|
||||||
{
|
|
||||||
dstream<<"MapBlockObjectList::add(): NULL object"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
// Create unique id if id==-1
|
|
||||||
if(object->m_id == -1)
|
|
||||||
{
|
|
||||||
object->m_id = getFreeId();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_objects.find(object->m_id) != NULL)
|
|
||||||
{
|
|
||||||
dstream<<"MapBlockObjectList::add(): "
|
|
||||||
"object with same id already exists"<<std::endl;
|
|
||||||
throw AlreadyExistsException
|
|
||||||
("MapBlockObjectList already has given id");
|
|
||||||
}
|
|
||||||
|
|
||||||
object->m_block = m_block;
|
|
||||||
|
|
||||||
/*v3f p = object->m_pos;
|
|
||||||
dstream<<"MapBlockObjectList::add(): "
|
|
||||||
<<"m_block->getPos()=("
|
|
||||||
<<m_block->getPos().X<<","
|
|
||||||
<<m_block->getPos().Y<<","
|
|
||||||
<<m_block->getPos().Z<<")"
|
|
||||||
<<" inserting object with id="<<object->m_id
|
|
||||||
<<" pos="
|
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
m_objects.insert(object->m_id, object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::clear()
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlockObject *obj = i.getNode()->getValue();
|
|
||||||
//FIXME: This really shouldn't be NULL at any time,
|
|
||||||
// but this condition was added because it was.
|
|
||||||
if(obj != NULL)
|
|
||||||
{
|
|
||||||
obj->removeFromScene();
|
|
||||||
delete obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_objects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::remove(s16 id)
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::map<s16, MapBlockObject*>::Node *n;
|
|
||||||
n = m_objects.find(id);
|
|
||||||
if(n == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
n->getValue()->removeFromScene();
|
|
||||||
delete n->getValue();
|
|
||||||
m_objects.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject * MapBlockObjectList::get(s16 id)
|
|
||||||
{
|
|
||||||
core::map<s16, MapBlockObject*>::Node *n;
|
|
||||||
n = m_objects.find(id);
|
|
||||||
if(n == NULL)
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return n->getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
|
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::map<s16, bool> ids_to_delete;
|
|
||||||
|
|
||||||
{
|
|
||||||
DSTACKF("%s: stepping objects", __FUNCTION_NAME);
|
|
||||||
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlockObject *obj = i.getNode()->getValue();
|
|
||||||
|
|
||||||
DSTACKF("%s: stepping object type %i", __FUNCTION_NAME,
|
|
||||||
obj->getTypeId());
|
|
||||||
|
|
||||||
if(server)
|
|
||||||
{
|
|
||||||
// Update light
|
|
||||||
u8 light = LIGHT_MAX;
|
|
||||||
try{
|
|
||||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
|
||||||
MapNode n = m_block->getNodeParent(relpos_i);
|
|
||||||
light = n.getLightBlend(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e) {}
|
|
||||||
obj->updateLight(light);
|
|
||||||
|
|
||||||
bool to_delete = obj->serverStep(dtime, daynight_ratio);
|
|
||||||
|
|
||||||
if(to_delete)
|
|
||||||
ids_to_delete.insert(obj->m_id, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obj->clientStep(dtime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DSTACKF("%s: deleting objects", __FUNCTION_NAME);
|
|
||||||
|
|
||||||
// Delete objects in delete queue
|
|
||||||
for(core::map<s16, bool>::Iterator
|
|
||||||
i = ids_to_delete.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
s16 id = i.getNode()->getKey();
|
|
||||||
|
|
||||||
MapBlockObject *obj = m_objects[id];
|
|
||||||
obj->removeFromScene();
|
|
||||||
delete obj;
|
|
||||||
m_objects.remove(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Wrap objects on server
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(server == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
{
|
|
||||||
DSTACKF("%s: object wrap loop", __FUNCTION_NAME);
|
|
||||||
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlockObject *obj = i.getNode()->getValue();
|
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(obj->m_pos, BS);
|
|
||||||
|
|
||||||
if(m_block->isValidPosition(pos_i))
|
|
||||||
{
|
|
||||||
// No wrap
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool impossible = wrapObject(obj);
|
|
||||||
|
|
||||||
if(impossible)
|
|
||||||
{
|
|
||||||
// No wrap
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart find
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
// No lock here; this is called so that the lock is already locked.
|
|
||||||
//JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
assert(object->m_block == m_block);
|
|
||||||
assert(m_objects.find(object->m_id) != NULL);
|
|
||||||
assert(m_objects[object->m_id] == object);
|
|
||||||
|
|
||||||
Map *map = m_block->getParent();
|
|
||||||
|
|
||||||
// Calculate blockpos on map
|
|
||||||
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
|
||||||
v3f pos_f_on_oldblock = object->m_pos;
|
|
||||||
v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS);
|
|
||||||
v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
|
|
||||||
v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
|
|
||||||
|
|
||||||
// Get new block
|
|
||||||
MapBlock *newblock;
|
|
||||||
try{
|
|
||||||
newblock = map->getBlockNoCreate(pos_blocks_on_map);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
// Couldn't find block -> not wrapping
|
|
||||||
/*dstream<<"WARNING: Wrapping object not possible: "
|
|
||||||
<<"could not find new block"
|
|
||||||
<<"("<<pos_blocks_on_map.X
|
|
||||||
<<","<<pos_blocks_on_map.Y
|
|
||||||
<<","<<pos_blocks_on_map.Z
|
|
||||||
<<")"<<std::endl;*/
|
|
||||||
/*dstream<<"pos_f_on_oldblock=("
|
|
||||||
<<pos_f_on_oldblock.X<<","
|
|
||||||
<<pos_f_on_oldblock.Y<<","
|
|
||||||
<<pos_f_on_oldblock.Z<<")"
|
|
||||||
<<std::endl;*/
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(newblock == m_block)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: Wrapping object not possible: "
|
|
||||||
"newblock == oldblock"<<std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate position on new block
|
|
||||||
v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS);
|
|
||||||
v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
|
|
||||||
v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS);
|
|
||||||
v3f pos_f_on_newblock = pos_f_on_oldblock
|
|
||||||
- newblock_pos_f_on_map + oldblock_pos_f_on_map;
|
|
||||||
|
|
||||||
// Remove object from this block
|
|
||||||
m_objects.remove(object->m_id);
|
|
||||||
|
|
||||||
// Add object to new block
|
|
||||||
object->m_pos = pos_f_on_newblock;
|
|
||||||
object->m_id = -1;
|
|
||||||
object->m_block = NULL;
|
|
||||||
newblock->addObject(object);
|
|
||||||
|
|
||||||
//dstream<<"NOTE: Wrapped object"<<std::endl;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapBlockObjectList::getObjects(v3f origin, f32 max_d,
|
|
||||||
core::array<DistanceSortedObject> &dest)
|
|
||||||
{
|
|
||||||
for(core::map<s16, MapBlockObject*>::Iterator
|
|
||||||
i = m_objects.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlockObject *obj = i.getNode()->getValue();
|
|
||||||
|
|
||||||
f32 d = (obj->getRelativeShowPos() - origin).getLength();
|
|
||||||
|
|
||||||
if(d > max_d)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DistanceSortedObject dso(obj, d);
|
|
||||||
|
|
||||||
dest.push_back(dso);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//END
|
|
1091
src/mapblockobject.h
1091
src/mapblockobject.h
File diff suppressed because it is too large
Load Diff
|
@ -1405,6 +1405,7 @@ bool get_have_sand(u64 seed, v2s16 p2d)
|
||||||
*/
|
*/
|
||||||
void add_random_objects(MapBlock *block)
|
void add_random_objects(MapBlock *block)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||||
{
|
{
|
||||||
|
@ -1465,6 +1466,7 @@ void add_random_objects(MapBlock *block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block->setChangedFlag();
|
block->setChangedFlag();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void make_block(BlockMakeData *data)
|
void make_block(BlockMakeData *data)
|
||||||
|
|
246
src/server.cpp
246
src/server.cpp
|
@ -860,107 +860,10 @@ void RemoteClient::SendObjectData(
|
||||||
v3s16 center_nodepos = floatToInt(playerpos, BS);
|
v3s16 center_nodepos = floatToInt(playerpos, BS);
|
||||||
v3s16 center = getNodeBlockPos(center_nodepos);
|
v3s16 center = getNodeBlockPos(center_nodepos);
|
||||||
|
|
||||||
s16 d_max = g_settings->getS16("active_object_range");
|
|
||||||
|
|
||||||
// Number of blocks whose objects were written to bos
|
|
||||||
u16 blockcount = 0;
|
|
||||||
|
|
||||||
std::ostringstream bos(std::ios_base::binary);
|
|
||||||
|
|
||||||
for(s16 d = 0; d <= d_max; d++)
|
|
||||||
{
|
|
||||||
core::list<v3s16> list;
|
|
||||||
getFacePositions(list, d);
|
|
||||||
|
|
||||||
core::list<v3s16>::Iterator li;
|
|
||||||
for(li=list.begin(); li!=list.end(); li++)
|
|
||||||
{
|
|
||||||
v3s16 p = *li + center;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Ignore blocks that haven't been sent to the client
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
if(m_blocks_sent.find(p) == NULL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try stepping block and add it to a send queue
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
// Get block
|
|
||||||
MapBlock *block = server->m_env.getMap().getBlockNoCreate(p);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Step block if not in stepped_blocks and add to stepped_blocks.
|
|
||||||
*/
|
|
||||||
if(stepped_blocks.find(p) == NULL)
|
|
||||||
{
|
|
||||||
block->stepObjects(dtime, true, server->m_env.getDayNightRatio());
|
|
||||||
stepped_blocks.insert(p, true);
|
|
||||||
//block->setChangedFlag();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip block if there are no objects
|
|
||||||
if(block->getObjectCount() == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Write objects
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Write blockpos
|
|
||||||
writeV3S16(buf, p);
|
|
||||||
bos.write((char*)buf, 6);
|
|
||||||
|
|
||||||
// Write objects
|
|
||||||
//block->serializeObjects(bos, serialization_version); // DEPRECATED
|
|
||||||
// count=0
|
|
||||||
writeU16(bos, 0);
|
|
||||||
|
|
||||||
blockcount++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Stop collecting objects if data is already too big
|
|
||||||
*/
|
|
||||||
// Sum of player and object data sizes
|
|
||||||
s32 sum = (s32)os.tellp() + 2 + (s32)bos.tellp();
|
|
||||||
// break out if data too big
|
|
||||||
if(sum > MAX_OBJECTDATA_SIZE)
|
|
||||||
{
|
|
||||||
goto skip_subsequent;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //try
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
// Not in memory
|
|
||||||
// Add it to the emerge queue and trigger the thread.
|
|
||||||
// Fetch the block only if it is on disk.
|
|
||||||
|
|
||||||
// Grab and increment counter
|
|
||||||
/*SharedPtr<JMutexAutoLock> lock
|
|
||||||
(m_num_blocks_in_emerge_queue.getLock());
|
|
||||||
m_num_blocks_in_emerge_queue.m_value++;*/
|
|
||||||
|
|
||||||
// Add to queue as an anonymous fetch from disk
|
|
||||||
u8 flags = BLOCK_EMERGE_FLAG_FROMDISK;
|
|
||||||
server->m_emerge_queue.addBlock(0, p, flags);
|
|
||||||
server->m_emergethread.trigger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_subsequent:
|
|
||||||
|
|
||||||
// Write block count
|
// Write block count
|
||||||
writeU16(buf, blockcount);
|
writeU16(buf, 0);
|
||||||
os.write((char*)buf, 2);
|
os.write((char*)buf, 2);
|
||||||
|
|
||||||
// Write block objects
|
|
||||||
os<<bos.str();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send data
|
Send data
|
||||||
*/
|
*/
|
||||||
|
@ -1431,7 +1334,8 @@ void Server::AsyncRunStep()
|
||||||
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objects");
|
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objects");
|
||||||
|
|
||||||
// Radius inside which objects are active
|
// Radius inside which objects are active
|
||||||
s16 radius = 32;
|
s16 radius = g_settings->getS16("active_object_send_range_blocks");
|
||||||
|
radius *= MAP_BLOCKSIZE;
|
||||||
|
|
||||||
for(core::map<u16, RemoteClient*>::Iterator
|
for(core::map<u16, RemoteClient*>::Iterator
|
||||||
i = m_clients.getIterator();
|
i = m_clients.getIterator();
|
||||||
|
@ -2343,87 +2247,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
else if(command == TOSERVER_CLICK_OBJECT)
|
else if(command == TOSERVER_CLICK_OBJECT)
|
||||||
{
|
{
|
||||||
if(datasize < 13)
|
derr_server<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
[0] u16 command
|
|
||||||
[2] u8 button (0=left, 1=right)
|
|
||||||
[3] v3s16 block
|
|
||||||
[9] s16 id
|
|
||||||
[11] u16 item
|
|
||||||
*/
|
|
||||||
u8 button = readU8(&data[2]);
|
|
||||||
v3s16 p;
|
|
||||||
p.X = readS16(&data[3]);
|
|
||||||
p.Y = readS16(&data[5]);
|
|
||||||
p.Z = readS16(&data[7]);
|
|
||||||
s16 id = readS16(&data[9]);
|
|
||||||
//u16 item_i = readU16(&data[11]);
|
|
||||||
|
|
||||||
MapBlock *block = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
block = m_env.getMap().getBlockNoCreate(p);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
derr_server<<"CLICK_OBJECT block not found"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject *obj = block->getObject(id);
|
|
||||||
|
|
||||||
if(obj == NULL)
|
|
||||||
{
|
|
||||||
derr_server<<"CLICK_OBJECT object not found"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Check that object is reasonably close
|
|
||||||
|
|
||||||
// Left click
|
|
||||||
if(button == 0)
|
|
||||||
{
|
|
||||||
InventoryList *ilist = player->inventory.getList("main");
|
|
||||||
if(g_settings->getBool("creative_mode") == false && ilist != NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Skip if inventory has no free space
|
|
||||||
if(ilist->getUsedSlots() == ilist->getSize())
|
|
||||||
{
|
|
||||||
dout_server<<"Player inventory has no free space"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create the inventory item
|
|
||||||
*/
|
|
||||||
InventoryItem *item = NULL;
|
|
||||||
// If it is an item-object, take the item from it
|
|
||||||
if(obj->getTypeId() == MAPBLOCKOBJECT_TYPE_ITEM)
|
|
||||||
{
|
|
||||||
item = ((ItemObject*)obj)->createInventoryItem();
|
|
||||||
}
|
|
||||||
// Else create an item of the object
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item = new MapBlockObjectItem
|
|
||||||
(obj->getInventoryString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to inventory and send inventory
|
|
||||||
ilist->addItem(item);
|
|
||||||
UpdateCrafting(player->peer_id);
|
|
||||||
SendInventory(player->peer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove from block
|
|
||||||
block->removeObject(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
|
else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
|
||||||
{
|
{
|
||||||
|
@ -2442,7 +2267,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
*/
|
*/
|
||||||
u8 button = readU8(&data[2]);
|
u8 button = readU8(&data[2]);
|
||||||
u16 id = readS16(&data[3]);
|
u16 id = readS16(&data[3]);
|
||||||
u16 item_i = readU16(&data[11]);
|
u16 item_i = readU16(&data[5]);
|
||||||
|
|
||||||
ServerActiveObject *obj = m_env.getActiveObject(id);
|
ServerActiveObject *obj = m_env.getActiveObject(id);
|
||||||
|
|
||||||
|
@ -3076,62 +2901,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
#endif
|
#endif
|
||||||
else if(command == TOSERVER_SIGNTEXT)
|
else if(command == TOSERVER_SIGNTEXT)
|
||||||
{
|
{
|
||||||
if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
|
derr_server<<"Server: TOSERVER_SIGNTEXT not supported anymore"
|
||||||
return;
|
<<std::endl;
|
||||||
/*
|
return;
|
||||||
u16 command
|
|
||||||
v3s16 blockpos
|
|
||||||
s16 id
|
|
||||||
u16 textlen
|
|
||||||
textdata
|
|
||||||
*/
|
|
||||||
std::string datastring((char*)&data[2], datasize-2);
|
|
||||||
std::istringstream is(datastring, std::ios_base::binary);
|
|
||||||
u8 buf[6];
|
|
||||||
// Read stuff
|
|
||||||
is.read((char*)buf, 6);
|
|
||||||
v3s16 blockpos = readV3S16(buf);
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
s16 id = readS16(buf);
|
|
||||||
is.read((char*)buf, 2);
|
|
||||||
u16 textlen = readU16(buf);
|
|
||||||
std::string text;
|
|
||||||
for(u16 i=0; i<textlen; i++)
|
|
||||||
{
|
|
||||||
is.read((char*)buf, 1);
|
|
||||||
text += (char)buf[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlock *block = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
block = m_env.getMap().getBlockNoCreate(blockpos);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
derr_server<<"Error while setting sign text: "
|
|
||||||
"block not found"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockObject *obj = block->getObject(id);
|
|
||||||
if(obj == NULL)
|
|
||||||
{
|
|
||||||
derr_server<<"Error while setting sign text: "
|
|
||||||
"object not found"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(obj->getTypeId() != MAPBLOCKOBJECT_TYPE_SIGN)
|
|
||||||
{
|
|
||||||
derr_server<<"Error while setting sign text: "
|
|
||||||
"object is not a sign"<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
((SignObject*)obj)->setText(text);
|
|
||||||
|
|
||||||
obj->getBlock()->setChangedFlag();
|
|
||||||
}
|
}
|
||||||
else if(command == TOSERVER_SIGNNODETEXT)
|
else if(command == TOSERVER_SIGNNODETEXT)
|
||||||
{
|
{
|
||||||
|
|
|
@ -102,6 +102,22 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseConfigLines(std::istream &is, const std::string &endstring)
|
||||||
|
{
|
||||||
|
for(;;){
|
||||||
|
if(is.eof())
|
||||||
|
break;
|
||||||
|
std::string line;
|
||||||
|
std::getline(is, line);
|
||||||
|
std::string trimmedline = trim(line);
|
||||||
|
if(endstring != ""){
|
||||||
|
if(trimmedline == endstring)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parseConfigLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns false on EOF
|
// Returns false on EOF
|
||||||
bool parseConfigObject(std::istream &is)
|
bool parseConfigObject(std::istream &is)
|
||||||
{
|
{
|
||||||
|
@ -481,6 +497,16 @@ public:
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v2f getV2F(std::string name)
|
||||||
|
{
|
||||||
|
v2f value;
|
||||||
|
Strfnd f(get(name));
|
||||||
|
f.next("(");
|
||||||
|
value.X = stof(f.next(","));
|
||||||
|
value.Y = stof(f.next(")"));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
u64 getU64(std::string name)
|
u64 getU64(std::string name)
|
||||||
{
|
{
|
||||||
u64 value = 0;
|
u64 value = 0;
|
||||||
|
@ -515,6 +541,13 @@ public:
|
||||||
set(name, os.str());
|
set(name, os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setV2F(std::string name, v2f value)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"("<<value.X<<","<<value.Y<<")";
|
||||||
|
set(name, os.str());
|
||||||
|
}
|
||||||
|
|
||||||
void setU64(std::string name, u64 value)
|
void setU64(std::string name, u64 value)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
@ -530,6 +563,47 @@ public:
|
||||||
m_defaults.clear();
|
m_defaults.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateValue(Settings &other, const std::string &name)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
if(&other == this)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try{
|
||||||
|
std::string val = other.get(name);
|
||||||
|
m_settings[name] = val;
|
||||||
|
} catch(SettingNotFoundException &e){
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(Settings &other)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
JMutexAutoLock lock2(other.m_mutex);
|
||||||
|
|
||||||
|
if(&other == this)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(core::map<std::string, std::string>::Iterator
|
||||||
|
i = other.m_settings.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
m_settings[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(core::map<std::string, std::string>::Iterator
|
||||||
|
i = other.m_defaults.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
m_defaults[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Settings & operator+=(Settings &other)
|
Settings & operator+=(Settings &other)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
114
src/tile.cpp
114
src/tile.cpp
|
@ -1054,6 +1054,120 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
image->drop();
|
image->drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
"[makealpha:R,G,B:filename.png"
|
||||||
|
Use an image with converting one color to transparent.
|
||||||
|
*/
|
||||||
|
else if(part_of_name.substr(0,11) == "[makealpha:")
|
||||||
|
{
|
||||||
|
if(baseimg != NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||||
|
<<"for part_of_name=\""<<part_of_name
|
||||||
|
<<"\", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Strfnd sf(part_of_name.substr(11));
|
||||||
|
u32 r1 = stoi(sf.next(","));
|
||||||
|
u32 g1 = stoi(sf.next(","));
|
||||||
|
u32 b1 = stoi(sf.next(":"));
|
||||||
|
std::string filename = sf.next("");
|
||||||
|
|
||||||
|
std::string path = getTexturePath(filename.c_str());
|
||||||
|
|
||||||
|
dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
|
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||||
|
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: generate_image(): Loading path \""
|
||||||
|
<<path<<"\" failed"<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
|
{
|
||||||
|
video::SColor c = image->getPixel(x,y);
|
||||||
|
u32 r = c.getRed();
|
||||||
|
u32 g = c.getGreen();
|
||||||
|
u32 b = c.getBlue();
|
||||||
|
if(!(r == r1 && g == g1 && b == b1))
|
||||||
|
continue;
|
||||||
|
c.setAlpha(0);
|
||||||
|
image->setPixel(x,y,c);
|
||||||
|
}
|
||||||
|
// Blit
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
"[makealpha2:R,G,B;R2,G2,B2:filename.png"
|
||||||
|
Use an image with converting two colors to transparent.
|
||||||
|
*/
|
||||||
|
else if(part_of_name.substr(0,12) == "[makealpha2:")
|
||||||
|
{
|
||||||
|
if(baseimg != NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||||
|
<<"for part_of_name=\""<<part_of_name
|
||||||
|
<<"\", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Strfnd sf(part_of_name.substr(12));
|
||||||
|
u32 r1 = stoi(sf.next(","));
|
||||||
|
u32 g1 = stoi(sf.next(","));
|
||||||
|
u32 b1 = stoi(sf.next(";"));
|
||||||
|
u32 r2 = stoi(sf.next(","));
|
||||||
|
u32 g2 = stoi(sf.next(","));
|
||||||
|
u32 b2 = stoi(sf.next(":"));
|
||||||
|
std::string filename = sf.next("");
|
||||||
|
|
||||||
|
std::string path = getTexturePath(filename.c_str());
|
||||||
|
|
||||||
|
dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
|
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||||
|
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: generate_image(): Loading path \""
|
||||||
|
<<path<<"\" failed"<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
|
{
|
||||||
|
video::SColor c = image->getPixel(x,y);
|
||||||
|
u32 r = c.getRed();
|
||||||
|
u32 g = c.getGreen();
|
||||||
|
u32 b = c.getBlue();
|
||||||
|
if(!(r == r1 && g == g1 && b == b1) &&
|
||||||
|
!(r == r2 && g == g2 && b == b2))
|
||||||
|
continue;
|
||||||
|
c.setAlpha(0);
|
||||||
|
image->setPixel(x,y,c);
|
||||||
|
}
|
||||||
|
// Blit
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
[inventorycube{topimage{leftimage{rightimage
|
[inventorycube{topimage{leftimage{rightimage
|
||||||
In every subimage, replace ^ with &.
|
In every subimage, replace ^ with &.
|
||||||
|
|
|
@ -810,6 +810,35 @@ inline float wrapDegrees(float f)
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrap to 0...360 */
|
||||||
|
inline float wrapDegrees_0_360(float f)
|
||||||
|
{
|
||||||
|
// Take examples of f=10, f=720.5, f=-0.5, f=-360.5
|
||||||
|
// This results in
|
||||||
|
// 10, 720, -1, -361
|
||||||
|
int i = floor(f);
|
||||||
|
// 0, 2, 0, -1
|
||||||
|
int l = i / 360;
|
||||||
|
// Wrap to 0...360
|
||||||
|
// 0, 2, -1, -2
|
||||||
|
if(i < 0)
|
||||||
|
l -= 1;
|
||||||
|
// 0, 720, 0, -360
|
||||||
|
int k = l * 360;
|
||||||
|
// 10, 0.5, -0.5, -0.5
|
||||||
|
f -= float(k);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrap to -180...180 */
|
||||||
|
inline float wrapDegrees_180(float f)
|
||||||
|
{
|
||||||
|
f += 180;
|
||||||
|
f = wrapDegrees_0_360(f);
|
||||||
|
f -= 180;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string lowercase(const std::string &s)
|
inline std::string lowercase(const std::string &s)
|
||||||
{
|
{
|
||||||
std::string s2;
|
std::string s2;
|
||||||
|
|
Loading…
Reference in New Issue