1
0

Merge branch 'master' into NetherFortGen

This commit is contained in:
madmaxoft 2014-03-29 23:05:17 +01:00
commit 47a427d3dc
17 changed files with 285 additions and 27 deletions

View File

@ -5,7 +5,7 @@ LOCAL_MODULE := mcserver
LOCAL_SRC_FILES := $(shell find ../CryptoPP ../lua ../jsoncpp ../zlib ../src ../tolua++ ../iniFile ../expat ../md5 ../sqlite ../luaexpat '(' -name '*.cpp' -o -name '*.c' ')')
LOCAL_SRC_FILES := $(shell find ../lib/polarssl ../lib/lua ../lib/jsoncpp ../lib/zlib ../src ../lib/tolua++ ../lib/iniFile ../lib/expat ../lib/md5 ../lib/sqlite ../lib/luaexpat '(' -name '*.cpp' -o -name '*.c' ')')
LOCAL_SRC_FILES := $(filter-out %SquirrelFunctions.cpp %SquirrelBindings.cpp %cPlugin_Squirrel.cpp %cSquirrelCommandBinder.cpp %minigzip.c %lua.c %tolua.c %toluabind.c %LeakFinder.cpp %StackWalker.cpp %example.c,$(LOCAL_SRC_FILES))
LOCAL_SRC_FILES := $(patsubst %.cpp,../%.cpp,$(LOCAL_SRC_FILES))
LOCAL_SRC_FILES := $(patsubst %.c,../%.c,$(LOCAL_SRC_FILES))
@ -24,17 +24,17 @@ LOCAL_C_INCLUDES := ../src \
../src/packets \
../src/items \
../src/blocks \
../tolua++/src/lib \
../lua/src \
../zlib-1.2.7 \
../iniFile \
../tolua++/include \
../jsoncpp/include \
../jsoncpp/src/lib_json \
../expat/ \
../md5/ \
../sqlite/ \
../luaexpat/ \
../lib/tolua++/src/lib \
../lib/lua/src \
../lib/zlib-1.2.7 \
../lib/iniFile \
../lib/tolua++/include \
../lib/jsoncpp/include \
../lib/jsoncpp/src/lib_json \
../lib/expat/ \
../lib/md5/ \
../lib/sqlite/ \
../lib/luaexpat/ \
.. \

View File

@ -0,0 +1,24 @@
return
{
HOOK_PROJECTILE_HIT_BLOCK =
{
CalledWhen = "A projectile hits a solid block.",
DefaultFnName = "OnProjectileHitBlock", -- also used as pagename
Desc = [[
This hook is called when a {{cProjectileEntity|projectile}} hits a solid block..
]],
Params =
{
{ Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." },
},
Returns = [[
If the function returns false or no value, the next plugin's callback is called. If the function
returns true, no other callback is called for this event and the projectile flies through block..
]],
}, -- HOOK_PROJECTILE_HIT_BLOCK
}

View File

@ -0,0 +1,25 @@
return
{
HOOK_PROJECTILE_HIT_ENTITY =
{
CalledWhen = "A projectile hits another entity.",
DefaultFnName = "OnProjectileHitEntity", -- also used as pagename
Desc = [[
This hook is called when a {{cProjectileEntity|projectile}} hits another entity.
]],
Params =
{
{ Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." },
{ Name = "Entity", Type = "{{cEntity}}", Notes = "The entity wich was hit." },
},
Returns = [[
If the function returns false or no value, the next plugin's callback is called. If the function
returns true, no other callback is called for this event and the projectile flies through the entity.
]],
}, -- HOOK_PROJECTILE_HIT_ENTITY
}

View File

@ -479,6 +479,18 @@ void cLuaState::Push(cEntity * a_Entity)
void cLuaState::Push(cProjectileEntity * a_ProjectileEntity)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, a_ProjectileEntity, "cProjectileEntity");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(cMonster * a_Monster)
{
ASSERT(IsValid());

View File

@ -38,6 +38,7 @@ extern "C"
class cWorld;
class cPlayer;
class cEntity;
class cProjectileEntity;
class cMonster;
class cItem;
class cItems;
@ -183,6 +184,7 @@ public:
void Push(cPlayer * a_Player);
void Push(const cPlayer * a_Player);
void Push(cEntity * a_Entity);
void Push(cProjectileEntity * a_ProjectileEntity);
void Push(cMonster * a_Monster);
void Push(cItem * a_Item);
void Push(cItems * a_Items);

View File

@ -90,6 +90,8 @@ public:
virtual bool OnPluginsLoaded (void) = 0;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile) = 0;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) = 0;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) = 0;
virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) = 0;
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) = 0;

View File

@ -1108,6 +1108,46 @@ bool cPluginLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a
bool cPluginLua::OnProjectileHitBlock(cProjectileEntity & a_Projectile)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PROJECTILE_HIT_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_Projectile, cLuaState::Return, res);
if (res)
{
return true;
}
}
return false;
}
bool cPluginLua::OnProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity & a_HitEntity)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PROJECTILE_HIT_ENTITY];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_Projectile, &a_HitEntity, cLuaState::Return, res);
if (res)
{
return true;
}
}
return false;
}
bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);

View File

@ -113,6 +113,8 @@ public:
virtual bool OnPluginsLoaded (void) override;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile) override;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) override;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) override;
virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) override;
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) override;

View File

@ -1154,6 +1154,48 @@ bool cPluginManager::CallHookPreCrafting(const cPlayer * a_Player, const cCrafti
bool cPluginManager::CallHookProjectileHitBlock(cProjectileEntity & a_Projectile)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PROJECTILE_HIT_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnProjectileHitBlock(a_Projectile))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity & a_HitEntity)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PROJECTILE_HIT_ENTITY);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnProjectileHitEntity(a_Projectile, a_HitEntity))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_SPAWNED_ENTITY);

View File

@ -18,6 +18,9 @@ class cChunkDesc;
// fwd: Entities/Entity.h
class cEntity;
// fwd: Entities/ProjectileEntity.h
class cProjectileEntity;
// fwd: Mobs/Monster.h
class cMonster;
@ -102,6 +105,8 @@ public: // tolua_export
HOOK_PLUGINS_LOADED,
HOOK_POST_CRAFTING,
HOOK_PRE_CRAFTING,
HOOK_PROJECTILE_HIT_BLOCK,
HOOK_PROJECTILE_HIT_ENTITY,
HOOK_SPAWNED_ENTITY,
HOOK_SPAWNED_MONSTER,
HOOK_SPAWNING_ENTITY,
@ -201,6 +206,8 @@ public: // tolua_export
bool CallHookPluginsLoaded (void);
bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookProjectileHitBlock (cProjectileEntity & a_Projectile);
bool CallHookProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity);
bool CallHookSpawnedEntity (cWorld & a_World, cEntity & a_Entity);
bool CallHookSpawnedMonster (cWorld & a_World, cMonster & a_Monster);
bool CallHookSpawningEntity (cWorld & a_World, cEntity & a_Entity);

View File

@ -1606,10 +1606,8 @@ void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket)
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
} // for itr - Chunks[]
// Do NOT stream new chunks, the new world runs its own tick thread and may deadlock
// Instead, the chunks will be streamed when the client is moved to the new world's Tick list,
// by setting state to csAuthenticated
m_State = csAuthenticated;
// StreamChunks() called in cPlayer::MoveToWorld() after new world has been set
// Meanwhile here, we set last streamed values to bogus ones so everything is resent
m_LastStreamedChunkX = 0x7fffffff;
m_LastStreamedChunkZ = 0x7fffffff;
m_HasSentPlayerChunk = false;

View File

@ -1489,6 +1489,7 @@ bool cPlayer::MoveToWorld(const char * a_WorldName)
// Add player to all the necessary parts of the new world
SetWorld(World);
m_ClientHandle->StreamChunks();
World->AddEntity(this);
World->AddPlayer(this);

View File

@ -4,6 +4,7 @@
// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
#include "Globals.h"
#include "../Bindings/PluginManager.h"
#include "ProjectileEntity.h"
#include "../ClientHandle.h"
#include "Player.h"
@ -66,6 +67,11 @@ protected:
eBlockFace Face;
if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
{
if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile))
{
return false;
}
Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
m_Projectile->OnHitSolidBlock(Intersection, Face);
return true;
@ -147,7 +153,11 @@ public:
}
// TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
// TODO: Allow plugins to interfere about which entities can be hit
if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
{
// A plugin disagreed.
return false;
}
if (LineCoeff < m_MinCoeff)
{

View File

@ -15,6 +15,92 @@ uses a prefabricate in a cBlockArea for drawing itself.
#ifdef SELF_TEST
// Create one static prefab to test the parser:
static const cPrefab::sDef g_TestPrefabDef =
{
// Size:
7, 6, 7, // SizeX = 7, SizeY = 6, SizeZ = 7
// Block definitions:
".: 0: 0\n" /* 0 */
"a:112: 0\n" /* netherbrick */
"b:113: 0\n" /* netherbrickfence */,
// Block data:
// Level 1
"aaaaaaa"
"aaaaaaa"
"aaaaaaa"
"aaaaaaa"
"aaaaaaa"
"aaaaaaa"
"aaaaaaa"
// Level 2
"aa...aa"
"a.....a"
"......."
"......."
"......."
"a.....a"
"aa...aa"
// Level 3
"aa...aa"
"a.....a"
"......."
"......."
"......."
"a.....a"
"aa...aa"
// Level 4
"aa...aa"
"a.....a"
"......."
"......."
"......."
"a.....a"
"aa...aa"
// Level 5
"aabbbaa"
"a.....a"
"b.....b"
"b.....b"
"b.....b"
"a.....a"
"aabbbaa"
// Level 6
"aaaaaaa"
"a.....a"
"a.....a"
"a.....a"
"a.....a"
"a.....a"
"aaaaaaa",
// Connections:
"0: 0, 3, 2: 4\n"
"0: 2, 3, 0: 2\n",
// AllowedRotations:
7, /* 1, 2, 3 CCW rotations */
// Merge strategy:
cBlockArea::msImprint
};
static cPrefab g_TestPrefab(g_TestPrefabDef);
#endif
cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ),
m_HitBox(0, 0, 0, a_Def.m_SizeX - 1, a_Def.m_SizeY - 1, a_Def.m_SizeZ - 1),
@ -89,7 +175,8 @@ void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef)
// Initialize the charmap to all-invalid values:
for (size_t i = 0; i < ARRAYCOUNT(a_CharMapOut); i++)
{
a_CharMapOut[i] = -1;
a_CharMapOut[i].m_BlockType = 0;
a_CharMapOut[i].m_BlockMeta = 16; // Mark unassigned entries with a meta that is impossible otherwise
}
// Process the lines in the definition:
@ -104,15 +191,15 @@ void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef)
continue;
}
unsigned char Src = (unsigned char)CharDef[0][0];
BLOCKTYPE BlockType = (BLOCKTYPE)atoi(CharDef[1].c_str());
ASSERT(a_CharMapOut[Src].m_BlockMeta == 16); // This letter has not been assigned yet?
a_CharMapOut[Src].m_BlockType = (BLOCKTYPE)atoi(CharDef[1].c_str());
NIBBLETYPE BlockMeta = 0;
if ((NumElements >= 3) && !CharDef[2].empty())
{
BlockMeta = (NIBBLETYPE)atoi(CharDef[2].c_str());
ASSERT((BlockMeta >= 0) && (BlockMeta <= 15));
}
ASSERT(a_CharMapOut[Src] == -1); // Any duplicates letter-wise?
a_CharMapOut[Src] = (BlockType << 4) | BlockMeta;
a_CharMapOut[Src].m_BlockMeta = BlockMeta;
} // for itr - Lines[]
}
@ -130,11 +217,9 @@ void cPrefab::ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockIma
const unsigned char * BlockImage = (const unsigned char *)a_BlockImage + y * m_Size.x * m_Size.z + z * m_Size.x;
for (int x = 0; x < m_Size.x; x++)
{
int MappedValue = a_CharMap[BlockImage[x]];
ASSERT(MappedValue != -1); // Using a letter not defined in the CharMap?
BLOCKTYPE BlockType = MappedValue >> 4;
NIBBLETYPE BlockMeta = MappedValue & 0x0f;
m_BlockArea[0].SetRelBlockTypeMeta(x, y, z, BlockType, BlockMeta);
const sBlockTypeDef & MappedValue = a_CharMap[BlockImage[x]];
ASSERT(MappedValue.m_BlockMeta != 16); // Using a letter not defined in the CharMap?
m_BlockArea[0].SetRelBlockTypeMeta(x, y, z, MappedValue.m_BlockType, MappedValue.m_BlockMeta);
}
}
}

View File

@ -53,8 +53,15 @@ public:
bool HasConnectorType(int a_ConnectorType) const;
protected:
/** Packs complete definition of a single block, for per-letter assignment. */
struct sBlockTypeDef
{
BLOCKTYPE m_BlockType;
NIBBLETYPE m_BlockMeta;
};
/** Maps letters in the sDef::m_Image onto a number, BlockType * 16 | BlockMeta */
typedef int CharMap[256];
typedef sBlockTypeDef CharMap[256];
/** The cBlockArea that contains the block definitions for the prefab.

View File

@ -304,6 +304,7 @@ void cRoot::LoadWorlds(cIniFile & IniFile)
{
if (IniFile.GetKeyComment("Worlds", 0) != " World=secondworld")
{
IniFile.DeleteKeyComment("Worlds", 0);
IniFile.AddKeyComment("Worlds", " World=secondworld");
}
}