Merge pull request #731 from mc-server/ballisticmissiles
Ballistic firework missiles
This commit is contained in:
commit
1985a9c33e
@ -39,6 +39,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0)
|
# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0)
|
||||||
|
|
||||||
ApplePlanks, 4 = AppleLog, *
|
ApplePlanks, 4 = AppleLog, *
|
||||||
ConiferPlanks, 4 = ConiferLog, *
|
ConiferPlanks, 4 = ConiferLog, *
|
||||||
BirchPlanks, 4 = BirchLog, *
|
BirchPlanks, 4 = BirchLog, *
|
||||||
@ -434,6 +435,55 @@ GoldNugget, 9 = GoldIngot, *
|
|||||||
EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1
|
EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1
|
||||||
|
|
||||||
|
|
||||||
|
#******************************************************#
|
||||||
|
# Fireworks & Co.
|
||||||
|
# (Best not to add non-vanilla items to this as it will cause internal firework data handling code to log warnings)
|
||||||
|
|
||||||
|
# Ballistic firework rockets - plain and with firework star, all with 1 - 3 gunpowder
|
||||||
|
FireworkRocket = Paper, * | Gunpowder, *
|
||||||
|
FireworkRocket = Paper, * | Gunpowder, * | Gunpowder, *
|
||||||
|
FireworkRocket = Paper, * | Gunpowder, * | Gunpowder, * | Gunpowder, *
|
||||||
|
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, *
|
||||||
|
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, * | Gunpowder, *
|
||||||
|
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, * | Gunpowder, * | Gunpowder, *
|
||||||
|
|
||||||
|
# Radioactive firework stars
|
||||||
|
# Plain powder and dye
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, *
|
||||||
|
|
||||||
|
# Powder and effect, with effect combining
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Glowdust, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Glowdust, * | Diamond, *
|
||||||
|
|
||||||
|
# Powder and shape (no shape combining possible)
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, *
|
||||||
|
|
||||||
|
# Power and shape (no shape combining possible), combined with effect
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Glowdust, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Glowdust, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Glowdust, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Glowdust, *
|
||||||
|
|
||||||
|
# Power and shape (no shape combining possible), combined with effect (with effect combining)
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Glowdust, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Glowdust, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Glowdust, * | Diamond, *
|
||||||
|
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Glowdust, * | Diamond, *
|
||||||
|
|
||||||
|
# Star fade colour-change
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
/** Maximum number of explosions to send this tick, server will start dropping if exceeded */
|
/** Maximum number of explosions to send this tick, server will start dropping if exceeded */
|
||||||
#define MAX_EXPLOSIONS_PER_TICK 20
|
#define MAX_EXPLOSIONS_PER_TICK 20
|
||||||
|
|
||||||
|
/** Maximum number of block change interactions a player can perform per tick - exceeding this causes a kick */
|
||||||
|
#define MAX_BLOCK_CHANGE_INTERACTIONS 20
|
||||||
|
|
||||||
/** How many ticks before the socket is closed after the client is destroyed (#31) */
|
/** How many ticks before the socket is closed after the client is destroyed (#31) */
|
||||||
static const int TICKS_BEFORE_CLOSE = 20;
|
static const int TICKS_BEFORE_CLOSE = 20;
|
||||||
|
|
||||||
@ -700,6 +703,14 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
|
|||||||
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status
|
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
m_NumBlockChangeInteractionsThisTick++;
|
||||||
|
|
||||||
|
if (!CheckBlockInteractionsRate())
|
||||||
|
{
|
||||||
|
Kick("Too many blocks were destroyed per unit time - hacked client?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
|
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
|
||||||
if (PlgMgr->CallHookPlayerLeftClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status))
|
if (PlgMgr->CallHookPlayerLeftClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status))
|
||||||
{
|
{
|
||||||
@ -708,12 +719,6 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckBlockInteractionsRate())
|
|
||||||
{
|
|
||||||
// Too many interactions per second, simply ignore. Probably a hacked client, so don't even send bak the block
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (a_Status)
|
switch (a_Status)
|
||||||
{
|
{
|
||||||
case DIG_STATUS_DROP_HELD: // Drop held item
|
case DIG_STATUS_DROP_HELD: // Drop held item
|
||||||
@ -944,7 +949,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
|||||||
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
||||||
BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||||
|
|
||||||
if (a_BlockFace > -1)
|
if (a_BlockFace != BLOCK_FACE_NONE)
|
||||||
{
|
{
|
||||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
||||||
@ -955,7 +960,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
|||||||
|
|
||||||
if (!CheckBlockInteractionsRate())
|
if (!CheckBlockInteractionsRate())
|
||||||
{
|
{
|
||||||
LOGD("Too many block interactions, aborting placement");
|
Kick("Too many blocks were placed/interacted with per unit time - hacked client?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1634,28 +1639,12 @@ bool cClientHandle::CheckBlockInteractionsRate(void)
|
|||||||
{
|
{
|
||||||
ASSERT(m_Player != NULL);
|
ASSERT(m_Player != NULL);
|
||||||
ASSERT(m_Player->GetWorld() != NULL);
|
ASSERT(m_Player->GetWorld() != NULL);
|
||||||
/*
|
|
||||||
// TODO: _X 2012_11_01: This needs a total re-thinking and rewriting
|
if (m_NumBlockChangeInteractionsThisTick > MAX_BLOCK_CHANGE_INTERACTIONS)
|
||||||
int LastActionCnt = m_Player->GetLastBlockActionCnt();
|
|
||||||
if ((m_Player->GetWorld()->GetTime() - m_Player->GetLastBlockActionTime()) < 0.1)
|
|
||||||
{
|
{
|
||||||
// Limit the number of block interactions per tick
|
|
||||||
m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time.
|
|
||||||
m_Player->SetLastBlockActionCnt(LastActionCnt + 1);
|
|
||||||
if (m_Player->GetLastBlockActionCnt() > MAXBLOCKCHANGEINTERACTIONS)
|
|
||||||
{
|
|
||||||
// Kick if more than MAXBLOCKCHANGEINTERACTIONS per tick
|
|
||||||
LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot) Was Kicked.", m_Username.c_str());
|
|
||||||
Kick("You're a baaaaaad boy!");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Player->SetLastBlockActionCnt(0); // Reset count
|
|
||||||
m_Player->SetLastBlockActionTime(); // Player tried to interact with a block. Reset last block interation time.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1728,8 +1717,9 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset explosion counter:
|
// Reset explosion & block change counters:
|
||||||
m_NumExplosionsThisTick = 0;
|
m_NumExplosionsThisTick = 0;
|
||||||
|
m_NumBlockChangeInteractionsThisTick = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ class cClientHandle : // tolua_export
|
|||||||
public cSocketThreads::cCallback
|
public cSocketThreads::cCallback
|
||||||
{ // tolua_export
|
{ // tolua_export
|
||||||
public:
|
public:
|
||||||
static const int MAXBLOCKCHANGEINTERACTIONS = 20; // 5 didn't help, 10 still doesn't work in Creative, 20 seems to have done the trick
|
|
||||||
|
|
||||||
#if defined(ANDROID_NDK)
|
#if defined(ANDROID_NDK)
|
||||||
static const int DEFAULT_VIEW_DISTANCE = 4; // The default ViewDistance (used when no value is set in Settings.ini)
|
static const int DEFAULT_VIEW_DISTANCE = 4; // The default ViewDistance (used when no value is set in Settings.ini)
|
||||||
@ -322,6 +321,9 @@ private:
|
|||||||
/** Number of explosions sent this tick */
|
/** Number of explosions sent this tick */
|
||||||
int m_NumExplosionsThisTick;
|
int m_NumExplosionsThisTick;
|
||||||
|
|
||||||
|
/** Number of place or break interactions this tick */
|
||||||
|
int m_NumBlockChangeInteractionsThisTick;
|
||||||
|
|
||||||
static int s_ClientCount;
|
static int s_ClientCount;
|
||||||
int m_UniqueID;
|
int m_UniqueID;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
// CraftingRecipes.cpp
|
// CraftingRecipes.cpp
|
||||||
|
|
||||||
// Interfaces to the cCraftingRecipes class representing the storage of crafting recipes
|
// Interfaces to the cCraftingRecipes class representing the storage of crafting recipes
|
||||||
@ -762,9 +762,94 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
|
|||||||
Recipe->m_Ingredients.push_back(*itrS);
|
Recipe->m_Ingredients.push_back(*itrS);
|
||||||
}
|
}
|
||||||
Recipe->m_Ingredients.insert(Recipe->m_Ingredients.end(), MatchedSlots.begin(), MatchedSlots.end());
|
Recipe->m_Ingredients.insert(Recipe->m_Ingredients.end(), MatchedSlots.begin(), MatchedSlots.end());
|
||||||
|
|
||||||
|
// We use Recipe instead of a_Recipe because we want the wildcard ingredients' slot numbers as well, which was just added previously
|
||||||
|
HandleFireworks(a_CraftingGrid, Recipe.get(), a_GridStride, a_OffsetX, a_OffsetY);
|
||||||
|
|
||||||
return Recipe.release();
|
return Recipe.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY)
|
||||||
|
{
|
||||||
|
// TODO: add support for more than one dye in the recipe
|
||||||
|
// A manual and temporary solution (listing everything) is in crafting.txt for fade colours, but a programmatic solutions needs to be done for everything else
|
||||||
|
|
||||||
|
if (a_Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_ROCKET)
|
||||||
|
{
|
||||||
|
for (cRecipeSlots::const_iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr)
|
||||||
|
{
|
||||||
|
switch (itr->m_Item.m_ItemType)
|
||||||
|
{
|
||||||
|
case E_ITEM_FIREWORK_STAR:
|
||||||
|
{
|
||||||
|
// Result was a rocket, found a star - copy star data to rocket data
|
||||||
|
int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY);
|
||||||
|
a_Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_GUNPOWDER:
|
||||||
|
{
|
||||||
|
// Gunpowder - increase flight time
|
||||||
|
a_Recipe->m_Result.m_FireworkItem.m_FlightTimeInTicks += 20;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_PAPER: break;
|
||||||
|
default: LOG("Unexpected item in firework rocket a_Recipe, was the crafting file fireworks section changed?"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (a_Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_STAR)
|
||||||
|
{
|
||||||
|
std::vector<int> DyeColours;
|
||||||
|
bool FoundStar = false;
|
||||||
|
|
||||||
|
for (cRecipeSlots::const_iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr)
|
||||||
|
{
|
||||||
|
switch (itr->m_Item.m_ItemType)
|
||||||
|
{
|
||||||
|
case E_ITEM_FIREWORK_STAR:
|
||||||
|
{
|
||||||
|
// Result was star, found another star - probably adding fade colours, but copy data over anyhow
|
||||||
|
FoundStar = true;
|
||||||
|
int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY);
|
||||||
|
a_Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_DYE:
|
||||||
|
{
|
||||||
|
int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY);
|
||||||
|
DyeColours.push_back(cFireworkItem::GetVanillaColourCodeFromDye(a_CraftingGrid[GridID].m_ItemDamage));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_GUNPOWDER: break;
|
||||||
|
case E_ITEM_DIAMOND: a_Recipe->m_Result.m_FireworkItem.m_HasTrail = true; break;
|
||||||
|
case E_ITEM_GLOWSTONE_DUST: a_Recipe->m_Result.m_FireworkItem.m_HasFlicker = true; break;
|
||||||
|
|
||||||
|
case E_ITEM_FIRE_CHARGE: a_Recipe->m_Result.m_FireworkItem.m_Type = 1; break;
|
||||||
|
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
|
||||||
|
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
|
||||||
|
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
|
||||||
|
default: LOG("Unexpected item in firework star a_Recipe, was the crafting file fireworks section changed?"); break; // ermahgerd BARD ardmins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FoundStar && (!DyeColours.empty()))
|
||||||
|
{
|
||||||
|
// Found a star and a dye? Fade colours.
|
||||||
|
a_Recipe->m_Result.m_FireworkItem.m_FadeColours = DyeColours;
|
||||||
|
}
|
||||||
|
else if (!DyeColours.empty())
|
||||||
|
{
|
||||||
|
// Only dye? Normal colours.
|
||||||
|
a_Recipe->m_Result.m_FireworkItem.m_Colours = DyeColours;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,6 +165,9 @@ protected:
|
|||||||
|
|
||||||
/// Checks if the grid matches the specified recipe, offset by the specified offsets. Returns a matched cRecipe * if so, or NULL if not matching. Caller must delete the return value!
|
/// Checks if the grid matches the specified recipe, offset by the specified offsets. Returns a matched cRecipe * if so, or NULL if not matching. Caller must delete the return value!
|
||||||
cRecipe * MatchRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride, const cRecipe * a_Recipe, int a_OffsetX, int a_OffsetY);
|
cRecipe * MatchRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride, const cRecipe * a_Recipe, int a_OffsetX, int a_OffsetY);
|
||||||
|
|
||||||
|
/** Searches for anything firework related, and does the data setting if appropriate */
|
||||||
|
void HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,18 +10,11 @@
|
|||||||
#include "../BlockEntities/BlockEntity.h"
|
#include "../BlockEntities/BlockEntity.h"
|
||||||
#include "../GroupManager.h"
|
#include "../GroupManager.h"
|
||||||
#include "../Group.h"
|
#include "../Group.h"
|
||||||
#include "../ChatColor.h"
|
|
||||||
#include "../Item.h"
|
|
||||||
#include "../Tracer.h"
|
|
||||||
#include "../Root.h"
|
#include "../Root.h"
|
||||||
#include "../OSSupport/Timer.h"
|
#include "../OSSupport/Timer.h"
|
||||||
#include "../MersenneTwister.h"
|
|
||||||
#include "../Chunk.h"
|
#include "../Chunk.h"
|
||||||
#include "../Items/ItemHandler.h"
|
#include "../Items/ItemHandler.h"
|
||||||
|
|
||||||
#include "../Vector3d.h"
|
|
||||||
#include "../Vector3f.h"
|
|
||||||
|
|
||||||
#include "inifile/iniFile.h"
|
#include "inifile/iniFile.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
@ -45,10 +38,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
|||||||
, m_Inventory(*this)
|
, m_Inventory(*this)
|
||||||
, m_CurrentWindow(NULL)
|
, m_CurrentWindow(NULL)
|
||||||
, m_InventoryWindow(NULL)
|
, m_InventoryWindow(NULL)
|
||||||
, m_TimeLastPickupCheck(0.f)
|
|
||||||
, m_Color('-')
|
, m_Color('-')
|
||||||
, m_LastBlockActionTime(0)
|
|
||||||
, m_LastBlockActionCnt(0)
|
|
||||||
, m_GameMode(eGameMode_NotSet)
|
, m_GameMode(eGameMode_NotSet)
|
||||||
, m_IP("")
|
, m_IP("")
|
||||||
, m_ClientHandle(a_Client)
|
, m_ClientHandle(a_Client)
|
||||||
@ -86,7 +76,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
|||||||
m_LastPlayerListTime = t1.GetNowTime();
|
m_LastPlayerListTime = t1.GetNowTime();
|
||||||
|
|
||||||
m_TimeLastTeleportPacket = 0;
|
m_TimeLastTeleportPacket = 0;
|
||||||
m_TimeLastPickupCheck = 0;
|
|
||||||
|
|
||||||
m_PlayerName = a_PlayerName;
|
m_PlayerName = a_PlayerName;
|
||||||
m_bDirtyPosition = true; // So chunks are streamed to player at spawn
|
m_bDirtyPosition = true; // So chunks are streamed to player at spawn
|
||||||
@ -1047,27 +1036,6 @@ void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::SetLastBlockActionTime()
|
|
||||||
{
|
|
||||||
if (m_World != NULL)
|
|
||||||
{
|
|
||||||
m_LastBlockActionTime = m_World->GetWorldAge() / 20.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::SetLastBlockActionCnt( int a_LastBlockActionCnt )
|
|
||||||
{
|
|
||||||
m_LastBlockActionCnt = a_LastBlockActionCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::SetGameMode(eGameMode a_GameMode)
|
void cPlayer::SetGameMode(eGameMode a_GameMode)
|
||||||
{
|
{
|
||||||
if ((a_GameMode < gmMin) || (a_GameMode >= gmMax))
|
if ((a_GameMode < gmMin) || (a_GameMode >= gmMax))
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
/// Returns the curently equipped weapon; empty item if none
|
/// Returns the curently equipped weapon; empty item if none
|
||||||
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
|
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
|
||||||
|
|
||||||
/// Returns the currently equipped helmet; empty item if nonte
|
/// Returns the currently equipped helmet; empty item if none
|
||||||
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
|
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
|
||||||
|
|
||||||
/// Returns the currently equipped chestplate; empty item if none
|
/// Returns the currently equipped chestplate; empty item if none
|
||||||
@ -166,11 +166,6 @@ public:
|
|||||||
|
|
||||||
void SetIP(const AString & a_IP);
|
void SetIP(const AString & a_IP);
|
||||||
|
|
||||||
float GetLastBlockActionTime() { return m_LastBlockActionTime; }
|
|
||||||
int GetLastBlockActionCnt() { return m_LastBlockActionCnt; }
|
|
||||||
void SetLastBlockActionCnt( int );
|
|
||||||
void SetLastBlockActionTime();
|
|
||||||
|
|
||||||
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
|
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
|
||||||
void LoginSetGameMode(eGameMode a_GameMode);
|
void LoginSetGameMode(eGameMode a_GameMode);
|
||||||
|
|
||||||
@ -416,12 +411,8 @@ protected:
|
|||||||
cWindow * m_CurrentWindow;
|
cWindow * m_CurrentWindow;
|
||||||
cWindow * m_InventoryWindow;
|
cWindow * m_InventoryWindow;
|
||||||
|
|
||||||
float m_TimeLastPickupCheck;
|
|
||||||
|
|
||||||
char m_Color;
|
char m_Color;
|
||||||
|
|
||||||
float m_LastBlockActionTime;
|
|
||||||
int m_LastBlockActionCnt;
|
|
||||||
eGameMode m_GameMode;
|
eGameMode m_GameMode;
|
||||||
AString m_IP;
|
AString m_IP;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed)
|
cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item, const Vector3d * a_Speed)
|
||||||
{
|
{
|
||||||
Vector3d Speed;
|
Vector3d Speed;
|
||||||
if (a_Speed != NULL)
|
if (a_Speed != NULL)
|
||||||
@ -231,8 +231,15 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
|
|||||||
case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
||||||
case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
||||||
case pkExpBottle: return new cExpBottleEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
case pkExpBottle: return new cExpBottleEntity (a_Creator, a_X, a_Y, a_Z, Speed);
|
||||||
case pkFirework: return new cFireworkEntity (a_Creator, a_X, a_Y, a_Z );
|
case pkFirework:
|
||||||
// TODO: the rest
|
{
|
||||||
|
if (a_Item.m_FireworkItem.m_Colours.empty())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new cFireworkEntity(a_Creator, a_X, a_Y, a_Z, a_Item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind);
|
LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind);
|
||||||
@ -276,6 +283,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
|||||||
case pkExpBottle: return "ThrownExpBottle";
|
case pkExpBottle: return "ThrownExpBottle";
|
||||||
case pkSplashPotion: return "ThrownPotion";
|
case pkSplashPotion: return "ThrownPotion";
|
||||||
case pkWitherSkull: return "WitherSkull";
|
case pkWitherSkull: return "WitherSkull";
|
||||||
|
case pkFirework: return "Firework";
|
||||||
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
|
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
|
||||||
}
|
}
|
||||||
ASSERT(!"Unhandled projectile entity kind!");
|
ASSERT(!"Unhandled projectile entity kind!");
|
||||||
@ -693,8 +701,10 @@ void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_H
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cFireworkEntity :
|
// cFireworkEntity :
|
||||||
|
|
||||||
cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z) :
|
cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item) :
|
||||||
super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
|
||||||
|
m_ExplodeTimer(0),
|
||||||
|
m_FireworkItem(a_Item)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,30 +712,20 @@ super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFireworkEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
|
|
||||||
{
|
|
||||||
if ((a_HitFace != BLOCK_FACE_BOTTOM) && (a_HitFace != BLOCK_FACE_NONE))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
SetPosition(GetPosX(), GetPosY() - 0.5, GetPosZ());
|
|
||||||
|
|
||||||
m_IsInGround = true;
|
|
||||||
|
|
||||||
BroadcastMovementUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
|
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
|
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||||
|
int PosY = POSY_TOINT;
|
||||||
|
|
||||||
|
if ((PosY < 0) || (PosY >= cChunkDef::Height))
|
||||||
|
{
|
||||||
|
goto setspeed;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_IsInGround)
|
if (m_IsInGround)
|
||||||
{
|
{
|
||||||
if (a_Chunk.GetBlock((int)GetPosX(), (int)GetPosY() + 1, (int)GetPosZ()) == E_BLOCK_AIR)
|
if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) == E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
m_IsInGround = false;
|
m_IsInGround = false;
|
||||||
}
|
}
|
||||||
@ -734,28 +734,35 @@ void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Vector3d PerTickSpeed = GetSpeed() / 20;
|
|
||||||
Vector3d Pos = GetPosition();
|
|
||||||
|
|
||||||
// Trace the tick's worth of movement as a line:
|
|
||||||
Vector3d NextPos = Pos + PerTickSpeed;
|
|
||||||
cProjectileTracerCallback TracerCallback(this);
|
|
||||||
if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
|
||||||
{
|
{
|
||||||
// Something has been hit, abort all other processing
|
if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) != E_BLOCK_AIR)
|
||||||
|
{
|
||||||
|
OnHitSolidBlock(GetPosition(), BLOCK_FACE_YM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
|
}
|
||||||
|
|
||||||
// Update the position:
|
setspeed:
|
||||||
SetPosition(NextPos);
|
AddSpeedY(1);
|
||||||
|
AddPosition(GetSpeed() * (a_Dt / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
// Add slowdown and gravity effect to the speed:
|
|
||||||
Vector3d NewSpeed(GetSpeed());
|
|
||||||
NewSpeed.y += 2;
|
|
||||||
NewSpeed *= TracerCallback.GetSlowdownCoeff();
|
|
||||||
SetSpeed(NewSpeed);
|
void cFireworkEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||||
|
{
|
||||||
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
|
||||||
|
if (m_ExplodeTimer == m_FireworkItem.m_FireworkItem.m_FlightTimeInTicks)
|
||||||
|
{
|
||||||
|
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_FIREWORK_EXPLODE);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ExplodeTimer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
|
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
|
||||||
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
|
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
|
||||||
|
|
||||||
static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL);
|
static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item, const Vector3d * a_Speed = NULL);
|
||||||
|
|
||||||
/// Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given
|
/// Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given
|
||||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace);
|
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace);
|
||||||
@ -305,13 +305,19 @@ public:
|
|||||||
|
|
||||||
CLASS_PROTODEF(cFireworkEntity);
|
CLASS_PROTODEF(cFireworkEntity);
|
||||||
|
|
||||||
cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z);
|
cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item);
|
||||||
|
const cItem & GetItem(void) const { return m_FireworkItem; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int m_ExplodeTimer;
|
||||||
|
cItem m_FireworkItem;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
|
22
src/Item.cpp
22
src/Item.cpp
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||||
|
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
@ -139,6 +139,16 @@ void cItem::GetJson(Json::Value & a_OutValue) const
|
|||||||
{
|
{
|
||||||
a_OutValue["Lore"] = m_Lore;
|
a_OutValue["Lore"] = m_Lore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
|
||||||
|
{
|
||||||
|
a_OutValue["Flicker"] = m_FireworkItem.m_HasFlicker;
|
||||||
|
a_OutValue["Trail"] = m_FireworkItem.m_HasTrail;
|
||||||
|
a_OutValue["Type"] = m_FireworkItem.m_Type;
|
||||||
|
a_OutValue["FlightTimeInTicks"] = m_FireworkItem.m_FlightTimeInTicks;
|
||||||
|
a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem);
|
||||||
|
a_OutValue["FadeColours"] = m_FireworkItem.FadeColoursToString(m_FireworkItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +167,16 @@ void cItem::FromJson(const Json::Value & a_Value)
|
|||||||
m_Enchantments.AddFromString(a_Value.get("ench", "").asString());
|
m_Enchantments.AddFromString(a_Value.get("ench", "").asString());
|
||||||
m_CustomName = a_Value.get("Name", "").asString();
|
m_CustomName = a_Value.get("Name", "").asString();
|
||||||
m_Lore = a_Value.get("Lore", "").asString();
|
m_Lore = a_Value.get("Lore", "").asString();
|
||||||
|
|
||||||
|
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
|
||||||
|
{
|
||||||
|
m_FireworkItem.m_HasFlicker = a_Value.get("Flicker", false).asBool();
|
||||||
|
m_FireworkItem.m_HasTrail = a_Value.get("Trail", false).asBool();
|
||||||
|
m_FireworkItem.m_Type = (NIBBLETYPE)a_Value.get("Type", 0).asInt();
|
||||||
|
m_FireworkItem.m_FlightTimeInTicks = (short)a_Value.get("FlightTimeInTicks", 0).asInt();
|
||||||
|
m_FireworkItem.ColoursFromString(a_Value.get("Colours", "").asString(), m_FireworkItem);
|
||||||
|
m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/Item.h
16
src/Item.h
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "Enchantments.h"
|
#include "Enchantments.h"
|
||||||
|
#include "WorldStorage/FireworksSerializer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +39,8 @@ public:
|
|||||||
m_ItemCount(0),
|
m_ItemCount(0),
|
||||||
m_ItemDamage(0),
|
m_ItemDamage(0),
|
||||||
m_CustomName(""),
|
m_CustomName(""),
|
||||||
m_Lore("")
|
m_Lore(""),
|
||||||
|
m_FireworkItem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +59,8 @@ public:
|
|||||||
m_ItemDamage (a_ItemDamage),
|
m_ItemDamage (a_ItemDamage),
|
||||||
m_Enchantments(a_Enchantments),
|
m_Enchantments(a_Enchantments),
|
||||||
m_CustomName (a_CustomName),
|
m_CustomName (a_CustomName),
|
||||||
m_Lore (a_Lore)
|
m_Lore (a_Lore),
|
||||||
|
m_FireworkItem()
|
||||||
{
|
{
|
||||||
if (!IsValidItem(m_ItemType))
|
if (!IsValidItem(m_ItemType))
|
||||||
{
|
{
|
||||||
@ -77,7 +80,8 @@ public:
|
|||||||
m_ItemDamage (a_CopyFrom.m_ItemDamage),
|
m_ItemDamage (a_CopyFrom.m_ItemDamage),
|
||||||
m_Enchantments(a_CopyFrom.m_Enchantments),
|
m_Enchantments(a_CopyFrom.m_Enchantments),
|
||||||
m_CustomName (a_CopyFrom.m_CustomName),
|
m_CustomName (a_CopyFrom.m_CustomName),
|
||||||
m_Lore (a_CopyFrom.m_Lore)
|
m_Lore (a_CopyFrom.m_Lore),
|
||||||
|
m_FireworkItem(a_CopyFrom.m_FireworkItem)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +94,7 @@ public:
|
|||||||
m_Enchantments.Clear();
|
m_Enchantments.Clear();
|
||||||
m_CustomName = "";
|
m_CustomName = "";
|
||||||
m_Lore = "";
|
m_Lore = "";
|
||||||
|
m_FireworkItem.EmptyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,7 +120,8 @@ public:
|
|||||||
(m_ItemDamage == a_Item.m_ItemDamage) &&
|
(m_ItemDamage == a_Item.m_ItemDamage) &&
|
||||||
(m_Enchantments == a_Item.m_Enchantments) &&
|
(m_Enchantments == a_Item.m_Enchantments) &&
|
||||||
(m_CustomName == a_Item.m_CustomName) &&
|
(m_CustomName == a_Item.m_CustomName) &&
|
||||||
(m_Lore == a_Item.m_Lore)
|
(m_Lore == a_Item.m_Lore) &&
|
||||||
|
m_FireworkItem.IsEqualTo(a_Item.m_FireworkItem)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +183,8 @@ public:
|
|||||||
cEnchantments m_Enchantments;
|
cEnchantments m_Enchantments;
|
||||||
AString m_CustomName;
|
AString m_CustomName;
|
||||||
AString m_Lore;
|
AString m_Lore;
|
||||||
|
|
||||||
|
cFireworkItem m_FireworkItem;
|
||||||
};
|
};
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
|
|
||||||
Vector3d Pos = a_Player->GetThrowStartPos();
|
Vector3d Pos = a_Player->GetThrowStartPos();
|
||||||
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
||||||
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &Speed);
|
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -127,13 +127,13 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem());
|
||||||
|
|
||||||
if (!a_Player->IsGameModeCreative())
|
if (!a_Player->IsGameModeCreative())
|
||||||
{
|
{
|
||||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, 0);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,17 +68,28 @@ void cSheep::OnRightClicked(cPlayer & a_Player)
|
|||||||
|
|
||||||
void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
|
void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// The sheep should not move when he's eating so only handle the physics.
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
int PosX = POSX_TOINT;
|
||||||
|
int PosY = POSY_TOINT - 1;
|
||||||
|
int PosZ = POSZ_TOINT;
|
||||||
|
|
||||||
|
if ((PosY <= 0) || (PosY > cChunkDef::Height))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_TimeToStopEating > 0)
|
if (m_TimeToStopEating > 0)
|
||||||
{
|
{
|
||||||
HandlePhysics(a_Dt, a_Chunk);
|
m_bMovingToDestination = false; // The sheep should not move when he's eating
|
||||||
m_TimeToStopEating--;
|
m_TimeToStopEating--;
|
||||||
|
|
||||||
if (m_TimeToStopEating == 0)
|
if (m_TimeToStopEating == 0)
|
||||||
{
|
{
|
||||||
if (m_World->GetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ()) == E_BLOCK_GRASS)
|
if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime
|
||||||
{
|
{
|
||||||
// The sheep ate the grass so we change it to dirt.
|
// The sheep ate the grass so we change it to dirt
|
||||||
m_World->SetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ(), E_BLOCK_DIRT, 0);
|
m_World->SetBlock(PosX, PosY, PosZ, E_BLOCK_DIRT, 0);
|
||||||
|
GetWorld()->BroadcastSoundParticleEffect(2001, PosX, PosY, PosX, E_BLOCK_GRASS);
|
||||||
m_IsSheared = false;
|
m_IsSheared = false;
|
||||||
m_World->BroadcastEntityMetadata(*this);
|
m_World->BroadcastEntityMetadata(*this);
|
||||||
}
|
}
|
||||||
@ -86,12 +97,11 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
|
||||||
if (m_World->GetTickRandomNumber(600) == 1)
|
if (m_World->GetTickRandomNumber(600) == 1)
|
||||||
{
|
{
|
||||||
if (m_World->GetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ()) == E_BLOCK_GRASS)
|
if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS)
|
||||||
{
|
{
|
||||||
m_World->BroadcastEntityStatus(*this, 10);
|
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_SHEEP_EATING);
|
||||||
m_TimeToStopEating = 40;
|
m_TimeToStopEating = 40;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2079,17 +2079,20 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
|||||||
// Load enchantments and custom display names from the NBT data:
|
// Load enchantments and custom display names from the NBT data:
|
||||||
for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag))
|
for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag))
|
||||||
{
|
{
|
||||||
if (
|
AString TagName = NBT.GetName(tag);
|
||||||
(NBT.GetType(tag) == TAG_List) &&
|
switch (NBT.GetType(tag))
|
||||||
(
|
{
|
||||||
(NBT.GetName(tag) == "ench") ||
|
case TAG_List:
|
||||||
(NBT.GetName(tag) == "StoredEnchantments")
|
{
|
||||||
)
|
if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
|
||||||
)
|
|
||||||
{
|
{
|
||||||
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
|
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
|
||||||
}
|
}
|
||||||
else if ((NBT.GetType(tag) == TAG_Compound) && (NBT.GetName(tag) == "display")) // Custom name and lore tag
|
break;
|
||||||
|
}
|
||||||
|
case TAG_Compound:
|
||||||
|
{
|
||||||
|
if (TagName == "display") // Custom name and lore tag
|
||||||
{
|
{
|
||||||
for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
|
for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
|
||||||
{
|
{
|
||||||
@ -2110,6 +2113,14 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((TagName == "Fireworks") || (TagName == "Explosion"))
|
||||||
|
{
|
||||||
|
cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, NBT, tag, (ENUM_ITEM_ID)a_Item.m_ItemType);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: LOGD("Unimplemented NBT data when parsing!"); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2272,7 +2283,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
|||||||
WriteByte (a_Item.m_ItemCount);
|
WriteByte (a_Item.m_ItemCount);
|
||||||
WriteShort(a_Item.m_ItemDamage);
|
WriteShort(a_Item.m_ItemDamage);
|
||||||
|
|
||||||
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty())
|
if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
|
||||||
{
|
{
|
||||||
WriteShort(-1);
|
WriteShort(-1);
|
||||||
return;
|
return;
|
||||||
@ -2311,6 +2322,10 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
|||||||
}
|
}
|
||||||
Writer.EndCompound();
|
Writer.EndCompound();
|
||||||
}
|
}
|
||||||
|
if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))
|
||||||
|
{
|
||||||
|
cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, (ENUM_ITEM_ID)a_Item.m_ItemType);
|
||||||
|
}
|
||||||
Writer.Finish();
|
Writer.Finish();
|
||||||
AString Compressed;
|
AString Compressed;
|
||||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||||
@ -2487,10 +2502,22 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
|||||||
}
|
}
|
||||||
case cEntity::etProjectile:
|
case cEntity::etProjectile:
|
||||||
{
|
{
|
||||||
if (((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow)
|
cProjectileEntity & Projectile = (cProjectileEntity &)a_Entity;
|
||||||
|
switch (Projectile.GetProjectileKind())
|
||||||
|
{
|
||||||
|
case cProjectileEntity::pkArrow:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
WriteByte(0x10);
|
||||||
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0);
|
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case cProjectileEntity::pkFirework:
|
||||||
|
{
|
||||||
|
WriteByte(0xA8);
|
||||||
|
WriteItem(((const cFireworkEntity &)a_Entity).GetItem());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2980,9 +2980,9 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed)
|
int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem a_Item, const Vector3d * a_Speed)
|
||||||
{
|
{
|
||||||
cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Speed);
|
cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Item, a_Speed);
|
||||||
if (Projectile == NULL)
|
if (Projectile == NULL)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@ -3007,16 +3007,16 @@ void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Resul
|
|||||||
{
|
{
|
||||||
size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space
|
size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space
|
||||||
|
|
||||||
std::string LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); //Find the last word
|
AString LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); // Find the last word
|
||||||
std::string PlayerName ((*itr)->GetName());
|
AString PlayerName ((*itr)->GetName());
|
||||||
std::size_t Found = PlayerName.find(LastWord); //Try to find last word in playername
|
size_t Found = PlayerName.find(LastWord); // Try to find last word in playername
|
||||||
|
|
||||||
if (Found!=0)
|
if (Found == AString::npos)
|
||||||
{
|
{
|
||||||
continue; // No match
|
continue; // No match
|
||||||
}
|
}
|
||||||
|
|
||||||
a_Results.push_back((*itr)->GetName()); //Match!
|
a_Results.push_back(PlayerName); // Match!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +708,7 @@ public:
|
|||||||
int SpawnMobFinalize(cMonster* a_Monster);
|
int SpawnMobFinalize(cMonster* a_Monster);
|
||||||
|
|
||||||
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise */
|
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise */
|
||||||
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed = NULL); // tolua_export
|
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem a_Item, const Vector3d * a_Speed = NULL); // tolua_export
|
||||||
|
|
||||||
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
|
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
|
||||||
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
||||||
|
@ -309,7 +309,7 @@ protected:
|
|||||||
eTagType m_ItemType; // for TAG_List, the element type
|
eTagType m_ItemType; // for TAG_List, the element type
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
static const int MAX_STACK = 50; // Highliy doubtful that an NBT would be constructed this many levels deep
|
static const int MAX_STACK = 50; // Highly doubtful that an NBT would be constructed this many levels deep
|
||||||
|
|
||||||
// These two fields emulate a stack. A raw array is used due to speed issues - no reallocations are allowed.
|
// These two fields emulate a stack. A raw array is used due to speed issues - no reallocations are allowed.
|
||||||
sParent m_Stack[MAX_STACK];
|
sParent m_Stack[MAX_STACK];
|
||||||
|
252
src/WorldStorage/FireworksSerializer.cpp
Normal file
252
src/WorldStorage/FireworksSerializer.cpp
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "FireworksSerializer.h"
|
||||||
|
#include "WorldStorage/FastNBT.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFireworkItem::WriteToNBTCompound(const cFireworkItem & a_FireworkItem, cFastNBTWriter & a_Writer, const ENUM_ITEM_ID a_Type)
|
||||||
|
{
|
||||||
|
switch (a_Type)
|
||||||
|
{
|
||||||
|
case E_ITEM_FIREWORK_ROCKET:
|
||||||
|
{
|
||||||
|
a_Writer.BeginCompound("Fireworks");
|
||||||
|
a_Writer.AddByte("Flight", a_FireworkItem.m_FlightTimeInTicks / 20);
|
||||||
|
a_Writer.BeginList("Explosions", TAG_Compound);
|
||||||
|
a_Writer.BeginCompound("");
|
||||||
|
a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker);
|
||||||
|
a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail);
|
||||||
|
a_Writer.AddByte("Type", a_FireworkItem.m_Type);
|
||||||
|
a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size());
|
||||||
|
a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size());
|
||||||
|
a_Writer.EndCompound();
|
||||||
|
a_Writer.EndList();
|
||||||
|
a_Writer.EndCompound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_FIREWORK_STAR:
|
||||||
|
{
|
||||||
|
a_Writer.BeginCompound("Explosion");
|
||||||
|
a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker);
|
||||||
|
a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail);
|
||||||
|
a_Writer.AddByte("Type", a_FireworkItem.m_Type);
|
||||||
|
if (!a_FireworkItem.m_Colours.empty())
|
||||||
|
{
|
||||||
|
a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size());
|
||||||
|
}
|
||||||
|
if (!a_FireworkItem.m_FadeColours.empty())
|
||||||
|
{
|
||||||
|
a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size());
|
||||||
|
}
|
||||||
|
a_Writer.EndCompound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: ASSERT(!"Unhandled firework item!"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_ID a_Type)
|
||||||
|
{
|
||||||
|
if (a_TagIdx < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a_Type)
|
||||||
|
{
|
||||||
|
case E_ITEM_FIREWORK_STAR:
|
||||||
|
{
|
||||||
|
for (int explosiontag = a_NBT.GetFirstChild(a_TagIdx); explosiontag >= 0; explosiontag = a_NBT.GetNextSibling(explosiontag))
|
||||||
|
{
|
||||||
|
eTagType TagType = a_NBT.GetType(explosiontag);
|
||||||
|
if (TagType == TAG_Byte) // Custon name tag
|
||||||
|
{
|
||||||
|
AString ExplosionName = a_NBT.GetName(explosiontag);
|
||||||
|
|
||||||
|
if (ExplosionName == "Flicker")
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_HasFlicker = (a_NBT.GetByte(explosiontag) == 1);
|
||||||
|
}
|
||||||
|
else if (ExplosionName == "Trail")
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_HasTrail = (a_NBT.GetByte(explosiontag) == 1);
|
||||||
|
}
|
||||||
|
else if (ExplosionName == "Type")
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_Type = a_NBT.GetByte(explosiontag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TagType == TAG_IntArray)
|
||||||
|
{
|
||||||
|
AString ExplosionName = a_NBT.GetName(explosiontag);
|
||||||
|
|
||||||
|
if (ExplosionName == "Colors")
|
||||||
|
{
|
||||||
|
// Divide by four as data length returned in bytes
|
||||||
|
int DataLength = a_NBT.GetDataLength(explosiontag) / 4;
|
||||||
|
if (DataLength == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int * ColourData = (const int *)(a_NBT.GetData(explosiontag));
|
||||||
|
for (int i = 0; i < DataLength; i++)
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_Colours.push_back(ntohl(ColourData[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ExplosionName == "FadeColors")
|
||||||
|
{
|
||||||
|
int DataLength = a_NBT.GetDataLength(explosiontag) / 4;
|
||||||
|
if (DataLength == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int * FadeColourData = (const int *)(a_NBT.GetData(explosiontag));
|
||||||
|
for (int i = 0; i < DataLength; i++)
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_FadeColours.push_back(ntohl(FadeColourData[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_ITEM_FIREWORK_ROCKET:
|
||||||
|
{
|
||||||
|
for (int fireworkstag = a_NBT.GetFirstChild(a_TagIdx); fireworkstag >= 0; fireworkstag = a_NBT.GetNextSibling(fireworkstag))
|
||||||
|
{
|
||||||
|
eTagType TagType = a_NBT.GetType(fireworkstag);
|
||||||
|
if (TagType == TAG_Byte) // Custon name tag
|
||||||
|
{
|
||||||
|
if (a_NBT.GetName(fireworkstag) == "Flight")
|
||||||
|
{
|
||||||
|
a_FireworkItem.m_FlightTimeInTicks = a_NBT.GetByte(fireworkstag) * 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((TagType == TAG_List) && (a_NBT.GetName(fireworkstag) == "Explosions"))
|
||||||
|
{
|
||||||
|
int ExplosionsChild = a_NBT.GetFirstChild(fireworkstag);
|
||||||
|
if ((a_NBT.GetType(ExplosionsChild) == TAG_Compound) && (a_NBT.GetName(ExplosionsChild).empty()))
|
||||||
|
{
|
||||||
|
ParseFromNBT(a_FireworkItem, a_NBT, ExplosionsChild, E_ITEM_FIREWORK_STAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: ASSERT(!"Unhandled firework item!"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cFireworkItem::ColoursToString(const cFireworkItem & a_FireworkItem)
|
||||||
|
{
|
||||||
|
AString Result;
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator itr = a_FireworkItem.m_Colours.begin(); itr != a_FireworkItem.m_Colours.end(); ++itr)
|
||||||
|
{
|
||||||
|
AppendPrintf(Result, "%i;", *itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFireworkItem::ColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem)
|
||||||
|
{
|
||||||
|
AStringVector Split = StringSplit(a_String, ";");
|
||||||
|
|
||||||
|
for (size_t itr = 0; itr < Split.size(); ++itr)
|
||||||
|
{
|
||||||
|
if (Split[itr].empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_FireworkItem.m_Colours.push_back(atoi(Split[itr].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cFireworkItem::FadeColoursToString(const cFireworkItem & a_FireworkItem)
|
||||||
|
{
|
||||||
|
AString Result;
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator itr = a_FireworkItem.m_FadeColours.begin(); itr != a_FireworkItem.m_FadeColours.end(); ++itr)
|
||||||
|
{
|
||||||
|
AppendPrintf(Result, "%i;", *itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFireworkItem::FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem)
|
||||||
|
{
|
||||||
|
AStringVector Split = StringSplit(a_String, ";");
|
||||||
|
|
||||||
|
for (size_t itr = 0; itr < Split.size(); ++itr)
|
||||||
|
{
|
||||||
|
if (Split[itr].empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_FireworkItem.m_FadeColours.push_back(atoi(Split[itr].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cFireworkItem::GetVanillaColourCodeFromDye(short a_DyeMeta)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Colours are supposed to be calculated via: R << 16 + G << 8 + B
|
||||||
|
However, the RGB values fireworks use aren't the same as the ones for dyes (the ones listed in the MC Wiki)
|
||||||
|
Therefore, here is a list of numbers gotten via the Protocol Proxy
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (a_DyeMeta)
|
||||||
|
{
|
||||||
|
case E_META_DYE_BLACK: return 0x1E1B1B;
|
||||||
|
case E_META_DYE_RED: return 0xB3312C;
|
||||||
|
case E_META_DYE_GREEN: return 0x3B511A;
|
||||||
|
case E_META_DYE_BROWN: return 0x51301A;
|
||||||
|
case E_META_DYE_BLUE: return 0x253192;
|
||||||
|
case E_META_DYE_PURPLE: return 0x7B2FBE;
|
||||||
|
case E_META_DYE_CYAN: return 0x287697;
|
||||||
|
case E_META_DYE_LIGHTGRAY: return 0xABABAB;
|
||||||
|
case E_META_DYE_GRAY: return 0x434343;
|
||||||
|
case E_META_DYE_PINK: return 0xD88198;
|
||||||
|
case E_META_DYE_LIGHTGREEN: return 0x41CD34;
|
||||||
|
case E_META_DYE_YELLOW: return 0xDECF2A;
|
||||||
|
case E_META_DYE_LIGHTBLUE: return 0x6689D3;
|
||||||
|
case E_META_DYE_MAGENTA: return 0xC354CD;
|
||||||
|
case E_META_DYE_ORANGE: return 0xEB8844;
|
||||||
|
case E_META_DYE_WHITE: return 0xF0F0F0;
|
||||||
|
default: ASSERT(!"Unhandled dye meta whilst trying to get colour code for fireworks!"); return 0;
|
||||||
|
}
|
||||||
|
}
|
92
src/WorldStorage/FireworksSerializer.h
Normal file
92
src/WorldStorage/FireworksSerializer.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
// FireworksSerializer.h
|
||||||
|
|
||||||
|
// Declares the cFireworkItem class representing a firework or firework star
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
|
||||||
|
class cFastNBTWriter;
|
||||||
|
class cParsedNBT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cFireworkItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cFireworkItem(void) :
|
||||||
|
m_HasFlicker(false),
|
||||||
|
m_HasTrail(false),
|
||||||
|
m_Type(0),
|
||||||
|
m_FlightTimeInTicks(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CopyFrom(const cFireworkItem & a_Item)
|
||||||
|
{
|
||||||
|
m_FlightTimeInTicks = a_Item.m_FlightTimeInTicks;
|
||||||
|
m_HasFlicker = a_Item.m_HasFlicker;
|
||||||
|
m_HasTrail = a_Item.m_HasTrail;
|
||||||
|
m_Type = a_Item.m_Type;
|
||||||
|
m_Colours = a_Item.m_Colours;
|
||||||
|
m_FadeColours = a_Item.m_FadeColours;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void EmptyData(void)
|
||||||
|
{
|
||||||
|
m_FlightTimeInTicks = 0;
|
||||||
|
m_HasFlicker = false;
|
||||||
|
m_Type = 0;
|
||||||
|
m_HasTrail = false;
|
||||||
|
m_Colours.clear();
|
||||||
|
m_FadeColours.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsEqualTo(const cFireworkItem & a_Item) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
(m_FlightTimeInTicks == a_Item.m_FlightTimeInTicks) &&
|
||||||
|
(m_HasFlicker == a_Item.m_HasFlicker) &&
|
||||||
|
(m_HasTrail == a_Item.m_HasTrail) &&
|
||||||
|
(m_Type == a_Item.m_Type) &&
|
||||||
|
(m_Colours == a_Item.m_Colours) &&
|
||||||
|
(m_FadeColours == a_Item.m_FadeColours)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Writes firework NBT data to a Writer object */
|
||||||
|
static void WriteToNBTCompound(const cFireworkItem & a_FireworkItem, cFastNBTWriter & a_Writer, const ENUM_ITEM_ID a_Type);
|
||||||
|
|
||||||
|
/** Reads NBT data from a NBT object and populates a FireworkItem with it */
|
||||||
|
static void ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_ID a_Type);
|
||||||
|
|
||||||
|
/** Converts the firework's vector of colours into a string of values separated by a semicolon */
|
||||||
|
static AString ColoursToString(const cFireworkItem & a_FireworkItem);
|
||||||
|
|
||||||
|
/** Parses a string containing encoded firework colours and populates a FireworkItem with it */
|
||||||
|
static void ColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem);
|
||||||
|
|
||||||
|
/** Converts the firework's vector of fade colours into a string of values separated by a semicolon */
|
||||||
|
static AString FadeColoursToString(const cFireworkItem & a_FireworkItem);
|
||||||
|
|
||||||
|
/** Parses a string containing encoded firework fade colours and populates a FireworkItem with it */
|
||||||
|
static void FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem);
|
||||||
|
|
||||||
|
/** Returns a colour code for fireworks used by the network code */
|
||||||
|
static int GetVanillaColourCodeFromDye(short a_DyeMeta);
|
||||||
|
|
||||||
|
bool m_HasFlicker;
|
||||||
|
bool m_HasTrail;
|
||||||
|
NIBBLETYPE m_Type;
|
||||||
|
short m_FlightTimeInTicks;
|
||||||
|
std::vector<int> m_Colours;
|
||||||
|
std::vector<int> m_FadeColours;
|
||||||
|
};
|
@ -91,11 +91,19 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the enchantments:
|
// Write the enchantments:
|
||||||
|
if (!a_Item.m_Enchantments.IsEmpty() || ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)))
|
||||||
|
{
|
||||||
|
m_Writer.BeginCompound("tag");
|
||||||
|
if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))
|
||||||
|
{
|
||||||
|
cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, m_Writer, (ENUM_ITEM_ID)a_Item.m_ItemType);
|
||||||
|
}
|
||||||
|
|
||||||
if (!a_Item.m_Enchantments.IsEmpty())
|
if (!a_Item.m_Enchantments.IsEmpty())
|
||||||
{
|
{
|
||||||
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
|
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
|
||||||
m_Writer.BeginCompound("tag");
|
|
||||||
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName);
|
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName);
|
||||||
|
}
|
||||||
m_Writer.EndCompound();
|
m_Writer.EndCompound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,6 +664,12 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_
|
|||||||
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag);
|
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FireworksTag = a_NBT.FindChildByName(TagTag, ((a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ? "Fireworks" : "Explosion"));
|
||||||
|
if (EnchTag > 0)
|
||||||
|
{
|
||||||
|
cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, a_NBT, FireworksTag, (ENUM_ITEM_ID)a_Item.m_ItemType);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user