1
0
Fork 0

Merge branch 'Projectiles'

This commit is contained in:
madmaxoft 2013-08-30 20:49:33 +02:00
commit 105251a986
16 changed files with 772 additions and 169 deletions

View File

@ -1,5 +1,7 @@
.xls
Statistics.txt
*.bmp
Debug/
Release/
Profiling
*.png

View File

@ -15,6 +15,7 @@ Possible usage:
- count the per-chunk density of specific blocks
- count the per-chunk density of dungeons, by measuring the number of zombie/skeleton/regularspider spawners
- count the per-chunk-per-biome density of trees, by measuring the number of dirt-log vertical transitions, correlating to biome data
- draw a vertical map of the world based on a specific measured value (biome, elevation, ...)
This project is Windows-only, although it shouldn't be too difficult to make it portable.

View File

@ -321,6 +321,14 @@
RelativePath=".\HeightMap.h"
>
</File>
<File
RelativePath=".\ImageComposingCallback.cpp"
>
</File>
<File
RelativePath=".\ImageComposingCallback.h"
>
</File>
<File
RelativePath=".\Processor.cpp"
>

View File

@ -22,44 +22,53 @@ class cParsedNBT;
/** The base class for all chunk-processor callbacks, declares the interface.
The processor calls each virtual function in the order they are declared here with the specified args.
If the function returns true, the processor moves on to next chunk and starts calling the callbacks again from start with
the new chunk data.
If the function returns true, the processor doesn't process the data item, moves on to the next chunk
and starts calling the callbacks again from start with the new chunk data.
So if a statistics collector doesn't need data decompression at all, it can stop the processor from doing so early-enough
and still get meaningful data.
A callback is guaranteed to run in a single thread and always the same thread.
A callback is guaranteed to run in a single thread and always the same thread for the same chunk.
A callback is guaranteed to run on all chunks in a region and one region is guaranteed to be handled by only callback.
*/
class cCallback abstract
{
public:
enum
{
CALLBACK_CONTINUE = false,
CALLBACK_ABORT = true,
} ;
virtual ~cCallback() {} // Force a virtual destructor in each descendant
/// Called when a new region file is about to be opened; by default allow the region
virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) { return CALLBACK_CONTINUE; }
/// Called to inform the stats module of the chunk coords for newly processing chunk
virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) = 0;
/// Called to inform about the chunk's data offset in the file (chunk mini-header), the number of sectors it uses and the timestamp field value
virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) { return true; }
virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) { return CALLBACK_ABORT; }
/// Called to inform of the compressed chunk data size and position in the file (offset from file start to the actual data)
virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) { return true; }
virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) { return CALLBACK_ABORT; }
/// Just in case you wanted to process the NBT yourself ;)
virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) { return true; }
virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) { return CALLBACK_ABORT; }
/// The chunk's NBT should specify chunk coords, these are sent here:
virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) { return true; }
virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) { return CALLBACK_ABORT; }
/// The chunk contains a LastUpdate value specifying the last tick in which it was saved.
virtual bool OnLastUpdate(Int64 a_LastUpdate) { return true; }
virtual bool OnLastUpdate(Int64 a_LastUpdate) { return CALLBACK_ABORT; }
virtual bool OnTerrainPopulated(bool a_Populated) { return true; }
virtual bool OnTerrainPopulated(bool a_Populated) { return CALLBACK_ABORT; }
virtual bool OnBiomes(const unsigned char * a_BiomeData) { return true; }
virtual bool OnBiomes(const unsigned char * a_BiomeData) { return CALLBACK_ABORT; }
/** Called when a heightmap for the chunk is read from the file.
Note that the heightmap is given in big-endian ints, so if you want it, you need to ntohl() it first!
*/
virtual bool OnHeightMap(const int * a_HeightMapBE) { return true; }
virtual bool OnHeightMap(const int * a_HeightMapBE) { return CALLBACK_ABORT; }
/** If there is data for the section, this callback is called; otherwise OnEmptySection() is called instead.
All OnSection() callbacks are called first, and only then all the remaining sections are reported in OnEmptySection().
@ -71,16 +80,16 @@ public:
const NIBBLETYPE * a_BlockMeta,
const NIBBLETYPE * a_BlockLight,
const NIBBLETYPE * a_BlockSkyLight
) { return true; }
) { return CALLBACK_ABORT; }
/** If there is no data for a section, this callback is called; otherwise OnSection() is called instead.
OnEmptySection() callbacks are called after all OnSection() callbacks.
*/
virtual bool OnEmptySection(unsigned char a_Y) { return false; }
virtual bool OnEmptySection(unsigned char a_Y) { return CALLBACK_CONTINUE; }
/** Called after all sections have been processed via either OnSection() or OnEmptySection().
*/
virtual bool OnSectionsFinished(void) { return true; }
virtual bool OnSectionsFinished(void) { return CALLBACK_ABORT; }
/** Called for each entity in the chunk.
Common parameters are parsed from the NBT.
@ -98,7 +107,7 @@ public:
char a_IsOnGround,
cParsedNBT & a_NBT,
int a_NBTTag
) { return true; }
) { return CALLBACK_ABORT; }
/** Called for each tile entity in the chunk.
Common parameters are parsed from the NBT.
@ -110,14 +119,17 @@ public:
int a_PosX, int a_PosY, int a_PosZ,
cParsedNBT & a_NBT,
int a_NBTTag
) { return true; }
) { return CALLBACK_ABORT; }
/// Called for each tile tick in the chunk
virtual bool OnTileTick(
int a_BlockType,
int a_TicksLeft,
int a_PosX, int a_PosY, int a_PosZ
) { return true; }
) { return CALLBACK_ABORT; }
/// Called after the entire region file has been processed. No more callbacks for this region will be called. No processing by default
virtual void OnRegionFinished(int a_RegionX, int a_RegionZ) {}
} ;
typedef std::vector<cCallback *> cCallbacks;

View File

@ -0,0 +1,189 @@
// ImageComposingCallback.cpp
// Implements the cImageComposingCallback class that implements a subset of cCallback for composing per-region images
#include "Globals.h"
#include "ImageComposingCallback.h"
cImageComposingCallback::cImageComposingCallback(const AString & a_FileNamePrefix) :
m_FileNamePrefix(a_FileNamePrefix),
m_CurrentRegionX(INVALID_REGION_COORD),
m_CurrentRegionZ(INVALID_REGION_COORD),
m_ImageData(new int[32 * 16 * 32 * 16])
{
}
cImageComposingCallback::~cImageComposingCallback()
{
delete[] m_ImageData;
}
bool cImageComposingCallback::OnNewRegion(int a_RegionX, int a_RegionZ)
{
ASSERT(m_CurrentRegionX == INVALID_REGION_COORD);
ASSERT(m_CurrentRegionZ == INVALID_REGION_COORD); // Has any previous region been finished properly?
m_CurrentRegionX = a_RegionX;
m_CurrentRegionZ = a_RegionZ;
OnEraseImage();
return CALLBACK_CONTINUE;
}
void cImageComposingCallback::OnRegionFinished(int a_RegionX, int a_RegionZ)
{
ASSERT(m_CurrentRegionX != INVALID_REGION_COORD);
ASSERT(m_CurrentRegionZ != INVALID_REGION_COORD); // Has a region been started properly?
ASSERT(m_CurrentRegionX == a_RegionX);
ASSERT(m_CurrentRegionZ == a_RegionZ); // Is it the same region that has been started?
AString FileName = GetFileName(a_RegionX, a_RegionZ);
if (!FileName.empty())
{
OnBeforeImageSaved(a_RegionX, a_RegionZ, FileName);
SaveImage(FileName);
OnAfterImageSaved(a_RegionX, a_RegionZ, FileName);
}
m_CurrentRegionX = INVALID_REGION_COORD;
m_CurrentRegionZ = INVALID_REGION_COORD;
}
AString cImageComposingCallback::GetFileName(int a_RegionX, int a_RegionZ)
{
return Printf("%s.%d.%d", m_FileNamePrefix.c_str(), a_RegionX, a_RegionZ);
}
void cImageComposingCallback::OnEraseImage(void)
{
// By default erase the image to black:
EraseImage(0);
}
void cImageComposingCallback::EraseImage(int a_Color)
{
for (int i = 0; i < PIXEL_COUNT; i++)
{
m_ImageData[i] = a_Color;
}
}
void cImageComposingCallback::EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ)
{
int Base = a_RelChunkZ * IMAGE_HEIGHT + a_RelChunkX * 16;
for (int v = 0; v < 16; v++)
{
int BaseV = Base + v * IMAGE_HEIGHT;
for (int u = 0; u < 16; u++)
{
m_ImageData[BaseV + u] = a_Color;
}
} // for y
}
void cImageComposingCallback::SetPixel(int a_RelU, int a_RelV, int a_Color)
{
ASSERT((a_RelU >= 0) && (a_RelU < IMAGE_WIDTH));
ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT));
m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV] = a_Color;
}
int cImageComposingCallback::GetPixel(int a_RelU, int a_RelV)
{
if ((a_RelU < 0) || (a_RelU >= IMAGE_WIDTH) || (a_RelV < 0) || (a_RelV >= IMAGE_HEIGHT))
{
// Outside the image data
return -1;
}
return m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV];
}
void cImageComposingCallback::SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels)
{
ASSERT((a_RelUStart >= 0) && (a_RelUStart + a_CountU < IMAGE_WIDTH));
ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT));
ASSERT(a_Pixels != NULL);
int Base = a_RelUStart + a_RelV * IMAGE_WIDTH;
for (int u = 0; u < a_CountU; u++)
{
m_ImageData[Base + u] = a_Pixels[u];
}
}
void cImageComposingCallback::SaveImage(const AString & a_FileName)
{
cFile f(a_FileName, cFile::fmWrite);
if (!f.IsOpen())
{
return;
}
// Header for BMP files (is the same for the same-size files)
static const unsigned char BMPHeader[] =
{
0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
} ;
f.Write(BMPHeader, sizeof(BMPHeader));
f.Write(m_ImageData, PIXEL_COUNT * 4);
}

View File

@ -0,0 +1,95 @@
// ImageComposingCallback
// Declares the cImageComposingCallback class that implements a subset of cCallback for composing per-region images
#pragma once
#include "Callback.h"
/** Implements the plumbing for composing per-region images from multiple chunks.
To use this class, create a descendant that writes the image data using
SetPixel() or SetPixelURow() functions.
For the purpose of this class the image data is indexed U (horz) * V (vert), to avoid confusion with other coords.
The image is a 32bpp raw imagedata, written into a BMP file.
*/
class cImageComposingCallback :
public cCallback
{
public:
enum
{
INVALID_REGION_COORD = 99999, ///< Used for un-assigned region coords
IMAGE_WIDTH = 32 * 16,
IMAGE_HEIGHT = 32 * 16,
PIXEL_COUNT = IMAGE_WIDTH * IMAGE_HEIGHT, ///< Total pixel count of the image data
} ;
cImageComposingCallback(const AString & a_FileNamePrefix);
virtual ~cImageComposingCallback();
// cCallback overrides:
virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) override;
virtual void OnRegionFinished(int a_RegionX, int a_RegionZ) override;
// New introduced overridable functions:
/// Called when a file is about to be saved, to generate the filename
virtual AString GetFileName(int a_RegionX, int a_RegionZ);
/// Called before the file is saved
virtual void OnBeforeImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {}
/// Called after the image is saved to a file
virtual void OnAfterImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {}
/// Called when a new region is beginning, to erase the image data
virtual void OnEraseImage(void);
// Functions for manipulating the image:
/// Erases the entire image with the specified color
void EraseImage(int a_Color);
/// Erases the specified chunk's portion of the image with the specified color. Note that chunk coords are relative to the current region
void EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ);
/// Returns the current region X coord
int GetCurrentRegionX(void) const { return m_CurrentRegionX; }
/// Returns the current region Z coord
int GetCurrentRegionZ(void) const { return m_CurrentRegionZ; }
/// Sets the pixel at the specified UV coords to the specified color
void SetPixel(int a_RelU, int a_RelV, int a_Color);
/// Returns the color of the pixel at the specified UV coords; -1 if outside
int GetPixel(int a_RelU, int a_RelV);
/// Sets a row of pixels. a_Pixels is expected to be a_CountU pixels wide. a_RelUStart + a_CountU is assumed less than image width
void SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels);
protected:
/// Prefix for the filenames, when generated by the default GetFileName() function
AString m_FileNamePrefix;
/// Coords of the currently processed region
int m_CurrentRegionX, m_CurrentRegionZ;
/// Raw image data; 1 MiB worth of data, therefore unsuitable for stack allocation. [u + IMAGE_WIDTH * v]
int * m_ImageData;
void SaveImage(const AString & a_FileName);
} ;

View File

@ -76,6 +76,12 @@ void cProcessor::cThread::ProcessFile(const AString & a_FileName)
return;
}
if (m_Callback.OnNewRegion(RegionX, RegionZ))
{
// Callback doesn't want the region file processed
return;
}
cFile f;
if (!f.Open(a_FileName, cFile::fmRead))
{
@ -92,6 +98,8 @@ void cProcessor::cThread::ProcessFile(const AString & a_FileName)
}
ProcessFileData(FileContents.data(), FileContents.size(), RegionX * 32, RegionZ * 32);
m_Callback.OnRegionFinished(RegionX, RegionZ);
}

View File

@ -2347,6 +2347,10 @@
RelativePath="..\source\items\ItemSword.h"
>
</File>
<File
RelativePath="..\source\Items\ItemThrowable.h"
>
</File>
<File
RelativePath="..\source\items\ItemWood.h"
>

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 08/30/13 14:30:24.
** Generated automatically by tolua++-1.0.92 on 08/30/13 18:03:04.
*/
#ifndef __cplusplus
@ -203,63 +203,66 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cThrownEnderPearlEntity");
tolua_usertype(tolua_S,"TakeDamageInfo");
tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cMonster");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"cMonster");
tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cStringMap");
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cBlockArea");
tolua_usertype(tolua_S,"cEnchantments");
tolua_usertype(tolua_S,"cLuaWindow");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cRoot");
tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"std::vector<cIniFile::key>");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"std::vector<std::string>");
tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"cClientHandle");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"Vector3i");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"cThrownSnowballEntity");
tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cCraftingRecipes");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
tolua_usertype(tolua_S,"cArrowEntity");
tolua_usertype(tolua_S,"cDropSpenserEntity");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cDispenserEntity");
tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cItemGrid::cListener");
tolua_usertype(tolua_S,"HTTPTemplateRequest");
tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cFurnaceEntity");
tolua_usertype(tolua_S,"cDropperEntity");
tolua_usertype(tolua_S,"cLineBlockTracer");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cPluginLua");
tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cLineBlockTracer");
tolua_usertype(tolua_S,"cCriticalSection");
tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cListeners");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"cThrownEggEntity");
tolua_usertype(tolua_S,"cGroupManager");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
tolua_usertype(tolua_S,"cCriticalSection");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cProjectileEntity");
tolua_usertype(tolua_S,"cPluginLua");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"Vector3d");
}
@ -7650,6 +7653,92 @@ static int tolua_AllToLua_cPlayer_GetEquippedItem00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetThrowStartPos of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetThrowStartPos00
static int tolua_AllToLua_cPlayer_GetThrowStartPos00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetThrowStartPos'", NULL);
#endif
{
Vector3d tolua_ret = (Vector3d) self->GetThrowStartPos();
{
#ifdef __cplusplus
void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#else
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#endif
}
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetThrowStartPos'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetThrowSpeed of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetThrowSpeed00
static int tolua_AllToLua_cPlayer_GetThrowSpeed00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) ||
!tolua_isnumber(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0);
double a_SpeedCoeff = ((double) tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetThrowSpeed'", NULL);
#endif
{
Vector3d tolua_ret = (Vector3d) self->GetThrowSpeed(a_SpeedCoeff);
{
#ifdef __cplusplus
void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#else
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#endif
}
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetThrowSpeed'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetGameMode of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetGameMode00
static int tolua_AllToLua_cPlayer_GetGameMode00(lua_State* tolua_S)
@ -9704,88 +9793,6 @@ static int tolua_AllToLua_cProjectileEntity_IsInGround00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: PosFromPlayerPos of class cArrowEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_PosFromPlayerPos00
static int tolua_AllToLua_cArrowEntity_PosFromPlayerPos00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cPlayer",0,&tolua_err)) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cPlayer* a_Player = ((const cPlayer*) tolua_tousertype(tolua_S,2,0));
{
Vector3d tolua_ret = (Vector3d) cArrowEntity::PosFromPlayerPos(*a_Player);
{
#ifdef __cplusplus
void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#else
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#endif
}
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'PosFromPlayerPos'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: SpeedFromPlayerLook of class cArrowEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00
static int tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cPlayer",0,&tolua_err)) ||
!tolua_isnumber(tolua_S,3,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,4,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cPlayer* a_Player = ((const cPlayer*) tolua_tousertype(tolua_S,2,0));
double a_Force = ((double) tolua_tonumber(tolua_S,3,0));
{
Vector3d tolua_ret = (Vector3d) cArrowEntity::SpeedFromPlayerLook(*a_Player,a_Force);
{
#ifdef __cplusplus
void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#else
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
#endif
}
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'SpeedFromPlayerLook'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetPickupState of class cArrowEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_GetPickupState00
static int tolua_AllToLua_cArrowEntity_GetPickupState00(lua_State* tolua_S)
@ -28588,6 +28595,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetStance",tolua_AllToLua_cPlayer_GetStance00);
tolua_function(tolua_S,"GetInventory",tolua_AllToLua_cPlayer_GetInventory00);
tolua_function(tolua_S,"GetEquippedItem",tolua_AllToLua_cPlayer_GetEquippedItem00);
tolua_function(tolua_S,"GetThrowStartPos",tolua_AllToLua_cPlayer_GetThrowStartPos00);
tolua_function(tolua_S,"GetThrowSpeed",tolua_AllToLua_cPlayer_GetThrowSpeed00);
tolua_function(tolua_S,"GetGameMode",tolua_AllToLua_cPlayer_GetGameMode00);
tolua_function(tolua_S,"SetGameMode",tolua_AllToLua_cPlayer_SetGameMode00);
tolua_function(tolua_S,"IsGameModeCreative",tolua_AllToLua_cPlayer_IsGameModeCreative00);
@ -28677,14 +28686,21 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"psNoPickup",cArrowEntity::psNoPickup);
tolua_constant(tolua_S,"psInSurvivalOrCreative",cArrowEntity::psInSurvivalOrCreative);
tolua_constant(tolua_S,"psInCreative",cArrowEntity::psInCreative);
tolua_function(tolua_S,"PosFromPlayerPos",tolua_AllToLua_cArrowEntity_PosFromPlayerPos00);
tolua_function(tolua_S,"SpeedFromPlayerLook",tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00);
tolua_function(tolua_S,"GetPickupState",tolua_AllToLua_cArrowEntity_GetPickupState00);
tolua_function(tolua_S,"SetPickupState",tolua_AllToLua_cArrowEntity_SetPickupState00);
tolua_function(tolua_S,"GetDamageCoeff",tolua_AllToLua_cArrowEntity_GetDamageCoeff00);
tolua_function(tolua_S,"SetDamageCoeff",tolua_AllToLua_cArrowEntity_SetDamageCoeff00);
tolua_function(tolua_S,"CanPickup",tolua_AllToLua_cArrowEntity_CanPickup00);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cThrownEggEntity","cThrownEggEntity","cProjectileEntity",NULL);
tolua_beginmodule(tolua_S,"cThrownEggEntity");
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cThrownEnderPearlEntity","cThrownEnderPearlEntity","cProjectileEntity",NULL);
tolua_beginmodule(tolua_S,"cThrownEnderPearlEntity");
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cThrownSnowballEntity","cThrownSnowballEntity","cProjectileEntity",NULL);
tolua_beginmodule(tolua_S,"cThrownSnowballEntity");
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPluginManager","cPluginManager","",NULL);
tolua_beginmodule(tolua_S,"cPluginManager");
tolua_constant(tolua_S,"HOOK_BLOCK_TO_PICKUPS",cPluginManager::HOOK_BLOCK_TO_PICKUPS);

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 08/30/13 14:30:25.
** Generated automatically by tolua++-1.0.92 on 08/30/13 18:03:05.
*/
/* Exported function */

View File

@ -857,6 +857,36 @@ void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
Vector3d cPlayer::GetThrowStartPos(void) const
{
Vector3d res = GetEyePosition();
// Adjust the position to be just outside the player's bounding box:
res.x += 0.16 * cos(GetPitch());
res.y += -0.1;
res.z += 0.16 * sin(GetPitch());
return res;
}
Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
{
Vector3d res = GetLookVector();
res.Normalize();
// TODO: Add a slight random change (+-0.0075 in each direction)
return res * a_SpeedCoeff;
}
void cPlayer::MoveTo( const Vector3d & a_NewPos )
{
if ((a_NewPos.y < -990) && (GetPosY() > -100))

View File

@ -73,7 +73,7 @@ public:
void CancelChargingBow(void);
/// Returns true if the player is currently charging the bow
bool IsChargingBox(void) const { return m_IsChargingBow; }
bool IsChargingBow(void) const { return m_IsChargingBow; }
void SetTouchGround( bool a_bTouchGround );
inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
@ -90,6 +90,12 @@ public:
// tolua_begin
/// Returns the position where projectiles thrown by this player should start, player eye position + adjustment
Vector3d GetThrowStartPos(void) const;
/// Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff.
Vector3d GetThrowSpeed(double a_SpeedCoeff) const;
/// Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable
eGameMode GetGameMode(void) const { return m_GameMode; }

View File

@ -101,11 +101,14 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
switch (a_Kind)
{
case pkArrow: return new cArrowEntity(a_Creator, a_X, a_Y, a_Z, Speed);
case pkArrow: return new cArrowEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkEgg: return new cThrownEggEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkEnderPearl: return new cThrownEnderPearlEntity(a_Creator, a_X, a_Y, a_Z, Speed);
case pkSnowball: return new cThrownSnowballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
// TODO: the rest
}
LOGWARNING("%s: Unknown kind: %d", __FUNCTION__, a_Kind);
LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind);
return NULL;
}
@ -210,10 +213,20 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
void cProjectileEntity::SpawnOn(cClientHandle & a_Client)
{
// Default spawning - use the projectile kind to spawn an object:
a_Client.SendSpawnObject(*this, m_ProjectileKind, 0, 0, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cArrowEntity:
cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed) :
cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5),
m_PickupState(psNoPickup),
m_DamageCoeff(2)
@ -230,7 +243,7 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a
cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
super(pkArrow, &a_Player, PosFromPlayerPos(a_Player), SpeedFromPlayerLook(a_Player, a_Force), 0.5, 0.5),
super(pkArrow, &a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20), 0.5, 0.5),
m_PickupState(psInSurvivalOrCreative),
m_DamageCoeff(2)
{
@ -240,36 +253,6 @@ cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
Vector3d cArrowEntity::PosFromPlayerPos(const cPlayer & a_Player)
{
Vector3d res = a_Player.GetEyePosition();
// Adjust the position to be just outside the player's bounding box:
res.x += 0.16 * cos(a_Player.GetPitch());
res.y += -0.1;
res.z += 0.16 * sin(a_Player.GetPitch());
return res;
}
Vector3d cArrowEntity::SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force)
{
Vector3d res = a_Player.GetLookVector();
res.Normalize();
// TODO: Add a slight random change (+-0.0075 in each direction)
return res * a_Force * 1.5 * 20;
}
bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
{
switch (m_PickupState)
@ -294,3 +277,75 @@ void cArrowEntity::SpawnOn(cClientHandle & a_Client)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cThrownEggEntity:
cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
super(pkEgg, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
{
SetSpeed(a_Speed);
}
void cThrownEggEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
// TODO: Random-spawn a chicken or four
Destroy();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cThrownEnderPearlEntity :
cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
super(pkEnderPearl, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
{
SetSpeed(a_Speed);
}
void cThrownEnderPearlEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
// TODO: Teleport the creator here, make them take 5 damage
Destroy();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cThrownSnowballEntity :
cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
super(pkSnowball, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
{
SetSpeed(a_Speed);
}
void cThrownSnowballEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
// TODO: Apply damage to certain mobs (blaze etc.) and anger all mobs
Destroy();
}

View File

@ -78,6 +78,7 @@ protected:
// cEntity overrides:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
virtual void SpawnOn(cClientHandle & a_Client) override;
// tolua_begin
} ;
@ -105,19 +106,13 @@ public:
CLASS_PROTODEF(cArrowEntity);
/// Creates a new arrow with psNoPickup state and default damage modifier coeff
cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed);
cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
/// Creates a new arrow as shot by a player, initializes it from the player object
cArrowEntity(cPlayer & a_Player, double a_Force);
// tolua_begin
/// Returns the initial arrow position, as defined by the player eye position + adjustment.
static Vector3d PosFromPlayerPos(const cPlayer & a_Player);
/// Returns the initial arrow speed, as defined by the player look vector and the force coefficient
static Vector3d SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force);
/// Returns whether the arrow can be picked up by players
ePickupState GetPickupState(void) const { return m_PickupState; }
@ -143,12 +138,100 @@ protected:
/// The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow
double m_DamageCoeff;
// cEntity overrides:
// cProjectileEntity overrides:
virtual void SpawnOn(cClientHandle & a_Client) override;
// tolua_begin
} ;
class cThrownEggEntity :
public cProjectileEntity
{
typedef cProjectileEntity super;
public:
// tolua_end
CLASS_PROTODEF(cThrownEggEntity);
cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
protected:
// tolua_end
// cProjectileEntity overrides:
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
// tolua_begin
} ;
class cThrownEnderPearlEntity :
public cProjectileEntity
{
typedef cProjectileEntity super;
public:
// tolua_end
CLASS_PROTODEF(cThrownEnderPearlEntity);
cThrownEnderPearlEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
protected:
// tolua_end
// cProjectileEntity overrides:
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
// tolua_begin
} ;
class cThrownSnowballEntity :
public cProjectileEntity
{
typedef cProjectileEntity super;
public:
// tolua_end
CLASS_PROTODEF(cThrownSnowballEntity);
cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
protected:
// tolua_end
// cProjectileEntity overrides:
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
// tolua_begin
} ;
// tolua_end

View File

@ -22,6 +22,7 @@
#include "ItemLighter.h"
#include "ItemMinecart.h"
#include "ItemPickaxe.h"
#include "ItemThrowable.h"
#include "ItemRedstoneDust.h"
#include "ItemRedstoneRepeater.h"
#include "ItemSapling.h"
@ -88,12 +89,15 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
case E_ITEM_EGG: return new cItemEggHandler();
case E_ITEM_ENDER_PEARL: return new cItemEnderPearlHandler();
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType);
case E_ITEM_SNOWBALL: return new cItemSnowballHandler();
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);

View File

@ -0,0 +1,90 @@
// ItemThrowable.h
// Declares the itemhandlers for throwable items: eggs, snowballs and ender pearls
#pragma once
class cItemThrowableHandler :
public cItemHandler
{
typedef cItemHandler super;
public:
cItemThrowableHandler(int a_ItemType, cProjectileEntity::eKind a_ProjectileKind, double a_SpeedCoeff) :
super(a_ItemType),
m_ProjectileKind(a_ProjectileKind),
m_SpeedCoeff(a_SpeedCoeff)
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
Vector3d Pos = a_Player->GetThrowStartPos();
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &Speed);
return true;
}
protected:
cProjectileEntity::eKind m_ProjectileKind;
double m_SpeedCoeff;
} ;
class cItemEggHandler :
public cItemThrowableHandler
{
typedef cItemThrowableHandler super;
public:
cItemEggHandler(void) :
super(E_ITEM_EGG, cProjectileEntity::pkEgg, 30)
{
}
} ;
class cItemSnowballHandler :
public cItemThrowableHandler
{
typedef cItemThrowableHandler super;
public:
cItemSnowballHandler(void) :
super(E_ITEM_SNOWBALL, cProjectileEntity::pkSnowball, 30)
{
}
} ;
class cItemEnderPearlHandler :
public cItemThrowableHandler
{
typedef cItemThrowableHandler super;
public:
cItemEnderPearlHandler(void) :
super(E_ITEM_ENDER_PEARL, cProjectileEntity::pkEnderPearl, 30)
{
}
} ;