Implemented ballistic missiles (fireworks)
+ Added fireworks
This commit is contained in:
parent
cb40d114ab
commit
baf2d88921
@ -39,6 +39,7 @@
|
||||
#
|
||||
|
||||
# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0)
|
||||
|
||||
ApplePlanks, 4 = AppleLog, *
|
||||
ConiferPlanks, 4 = ConiferLog, *
|
||||
BirchPlanks, 4 = BirchLog, *
|
||||
@ -434,6 +435,48 @@ GoldNugget, 9 = GoldIngot, *
|
||||
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 colour-change
|
||||
FireworkStar = FireworkStar, * | Dye ^-1, *
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// CraftingRecipes.cpp
|
||||
|
||||
// Interfaces to the cCraftingRecipes class representing the storage of crafting recipes
|
||||
@ -762,6 +762,93 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
|
||||
Recipe->m_Ingredients.push_back(*itrS);
|
||||
}
|
||||
Recipe->m_Ingredients.insert(Recipe->m_Ingredients.end(), MatchedSlots.begin(), MatchedSlots.end());
|
||||
|
||||
|
||||
// Henceforth is code to handle fireworks
|
||||
// We use Recipe instead of a_Recipe because we want the wildcard ingredients' slot numbers as well, which was just added previously
|
||||
|
||||
if (Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_ROCKET)
|
||||
{
|
||||
for (cRecipeSlots::const_iterator itr = Recipe->m_Ingredients.begin(); itr != 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);
|
||||
Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem);
|
||||
break;
|
||||
}
|
||||
case E_ITEM_GUNPOWDER:
|
||||
{
|
||||
// Gunpowder - increase flight time
|
||||
Recipe->m_Result.m_FireworkItem.m_FlightTimeInTicks += 20;
|
||||
break;
|
||||
}
|
||||
case E_ITEM_PAPER: break;
|
||||
default: LOG("Unexpected item in firework rocket recipe, was the crafting file fireworks section changed?"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_STAR)
|
||||
{
|
||||
for (cRecipeSlots::const_iterator itr = Recipe->m_Ingredients.begin(); itr != 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
|
||||
int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY);
|
||||
Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem);
|
||||
break;
|
||||
}
|
||||
case E_ITEM_DYE:
|
||||
{
|
||||
// Found a dye in ingredients...
|
||||
for (cRecipeSlots::const_iterator itrnumerodos = Recipe->m_Ingredients.begin(); itrnumerodos != Recipe->m_Ingredients.end(); ++itrnumerodos)
|
||||
{
|
||||
// Loop through ingredients. Can we find a star?
|
||||
if (itrnumerodos->m_Item.m_ItemType == E_ITEM_FIREWORK_STAR)
|
||||
{
|
||||
// Yes, this is definately adding fade colours, unless crafting.txt was changed :/
|
||||
for (cRecipeSlots::const_iterator itrnumerotres = Recipe->m_Ingredients.begin(); itrnumerotres != Recipe->m_Ingredients.end(); ++itrnumerotres)
|
||||
{
|
||||
// Loop again, can we find dye?
|
||||
if (itrnumerotres->m_Item.m_ItemType == E_ITEM_DYE)
|
||||
{
|
||||
// Yep, push back fade colour and exit the loop
|
||||
// There is a potential for flexibility here - we can move the goto out of the loop, so we can add multiple dyes (∴ multiple fade colours)
|
||||
// That will require lots of dye-adding to crafting.txt though - TODO, perchance?
|
||||
int GridID = (itrnumerotres->x + a_OffsetX) + a_GridStride * (itrnumerotres->y + a_OffsetY);
|
||||
Recipe->m_Result.m_FireworkItem.m_FadeColours.push_back(cFireworkItem::GetVanillaColourCodeFromDye(a_CraftingGrid[GridID].m_ItemDamage));
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just normal crafting of star, push back normal colours
|
||||
int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY);
|
||||
Recipe->m_Result.m_FireworkItem.m_Colours.push_back(cFireworkItem::GetVanillaColourCodeFromDye(a_CraftingGrid[GridID].m_ItemDamage));
|
||||
|
||||
next:
|
||||
break;
|
||||
}
|
||||
case E_ITEM_GUNPOWDER: break;
|
||||
case E_ITEM_DIAMOND: Recipe->m_Result.m_FireworkItem.m_HasTrail = true; break;
|
||||
case E_ITEM_GLOWSTONE_DUST: Recipe->m_Result.m_FireworkItem.m_HasFlicker = true; break;
|
||||
|
||||
case E_ITEM_FIRE_CHARGE: Recipe->m_Result.m_FireworkItem.m_Type = 1; break;
|
||||
case E_ITEM_GOLD_NUGGET: Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
|
||||
case E_ITEM_FEATHER: Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
|
||||
case E_ITEM_HEAD: Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
|
||||
default: LOG("Unexpected item in firework star recipe, was the crafting file fireworks section changed?"); break; // ermahgerd BARD ardmins
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Recipe.release();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
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 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 pkFirework: return new cFireworkEntity (a_Creator, a_X, a_Y, a_Z );
|
||||
// TODO: the rest
|
||||
case pkFirework:
|
||||
{
|
||||
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);
|
||||
@ -276,6 +283,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
||||
case pkExpBottle: return "ThrownExpBottle";
|
||||
case pkSplashPotion: return "ThrownPotion";
|
||||
case pkWitherSkull: return "WitherSkull";
|
||||
case pkFirework: return "Firework";
|
||||
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
|
||||
}
|
||||
ASSERT(!"Unhandled projectile entity kind!");
|
||||
@ -693,8 +701,10 @@ void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_H
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cFireworkEntity :
|
||||
|
||||
cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z) :
|
||||
super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
||||
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),
|
||||
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)
|
||||
{
|
||||
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 (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;
|
||||
}
|
||||
@ -734,28 +734,35 @@ void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
// The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
|
||||
}
|
||||
|
||||
// Update the position:
|
||||
SetPosition(NextPos);
|
||||
setspeed:
|
||||
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, 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
|
||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace);
|
||||
@ -305,13 +305,19 @@ public:
|
||||
|
||||
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:
|
||||
|
||||
// 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 Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
private:
|
||||
|
||||
int m_ExplodeTimer;
|
||||
cItem m_FireworkItem;
|
||||
|
||||
// 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 "Item.h"
|
||||
@ -139,6 +139,16 @@ void cItem::GetJson(Json::Value & a_OutValue) const
|
||||
{
|
||||
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_CustomName = a_Value.get("Name", "").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 "Enchantments.h"
|
||||
#include "WorldStorage/FireworksSerializer.h"
|
||||
|
||||
|
||||
|
||||
@ -38,7 +39,8 @@ public:
|
||||
m_ItemCount(0),
|
||||
m_ItemDamage(0),
|
||||
m_CustomName(""),
|
||||
m_Lore("")
|
||||
m_Lore(""),
|
||||
m_FireworkItem()
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,7 +59,8 @@ public:
|
||||
m_ItemDamage (a_ItemDamage),
|
||||
m_Enchantments(a_Enchantments),
|
||||
m_CustomName (a_CustomName),
|
||||
m_Lore (a_Lore)
|
||||
m_Lore (a_Lore),
|
||||
m_FireworkItem()
|
||||
{
|
||||
if (!IsValidItem(m_ItemType))
|
||||
{
|
||||
@ -77,7 +80,8 @@ public:
|
||||
m_ItemDamage (a_CopyFrom.m_ItemDamage),
|
||||
m_Enchantments(a_CopyFrom.m_Enchantments),
|
||||
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_CustomName = "";
|
||||
m_Lore = "";
|
||||
m_FireworkItem.EmptyData();
|
||||
}
|
||||
|
||||
|
||||
@ -115,7 +120,8 @@ public:
|
||||
(m_ItemDamage == a_Item.m_ItemDamage) &&
|
||||
(m_Enchantments == a_Item.m_Enchantments) &&
|
||||
(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;
|
||||
AString m_CustomName;
|
||||
AString m_Lore;
|
||||
|
||||
cFireworkItem m_FireworkItem;
|
||||
};
|
||||
// tolua_end
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
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);
|
||||
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -127,13 +127,13 @@ public:
|
||||
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())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2069,17 +2069,20 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
||||
// Load enchantments and custom display names from the NBT data:
|
||||
for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag))
|
||||
{
|
||||
if (
|
||||
(NBT.GetType(tag) == TAG_List) &&
|
||||
(
|
||||
(NBT.GetName(tag) == "ench") ||
|
||||
(NBT.GetName(tag) == "StoredEnchantments")
|
||||
)
|
||||
)
|
||||
AString TagName = NBT.GetName(tag);
|
||||
switch (NBT.GetType(tag))
|
||||
{
|
||||
case TAG_List:
|
||||
{
|
||||
if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
|
||||
{
|
||||
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))
|
||||
{
|
||||
@ -2100,6 +2103,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2262,7 +2273,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||
WriteByte (a_Item.m_ItemCount);
|
||||
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);
|
||||
return;
|
||||
@ -2301,6 +2312,10 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||
}
|
||||
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();
|
||||
AString Compressed;
|
||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||
@ -2465,10 +2480,22 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||
}
|
||||
case cEntity::etProjectile:
|
||||
{
|
||||
if (((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow)
|
||||
cProjectileEntity & Projectile = (cProjectileEntity &)a_Entity;
|
||||
switch (Projectile.GetProjectileKind())
|
||||
{
|
||||
case cProjectileEntity::pkArrow:
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case cProjectileEntity::pkFirework:
|
||||
{
|
||||
WriteByte(0xA8);
|
||||
WriteItem(((const cFireworkEntity &)a_Entity).GetItem());
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2904,9 +2904,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)
|
||||
{
|
||||
return -1;
|
||||
|
@ -693,7 +693,7 @@ public:
|
||||
int SpawnMobFinalize(cMonster* a_Monster);
|
||||
|
||||
/** 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! */
|
||||
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
||||
|
@ -266,7 +266,7 @@ protected:
|
||||
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.
|
||||
sParent m_Stack[MAX_STACK];
|
||||
|
250
src/WorldStorage/FireworksSerializer.cpp
Normal file
250
src/WorldStorage/FireworksSerializer.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FireworksSerializer.h"
|
||||
#include "WorldStorage/FastNBT.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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")
|
||||
{
|
||||
if (a_NBT.GetDataLength(explosiontag) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const int * ColourData = (const int *)(a_NBT.GetData(explosiontag));
|
||||
for (int i = 0; i < ARRAYCOUNT(ColourData); i++)
|
||||
{
|
||||
a_FireworkItem.m_Colours.push_back(ntohl(ColourData[i]));
|
||||
}
|
||||
}
|
||||
else if (ExplosionName == "FadeColors")
|
||||
{
|
||||
if (a_NBT.GetDataLength(explosiontag) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const int * FadeColourData = (const int *)(a_NBT.GetData(explosiontag));
|
||||
for (int i = 0; i < ARRAYCOUNT(FadeColourData); 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 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 1973019;
|
||||
case E_META_DYE_RED: return 11743532;
|
||||
case E_META_DYE_GREEN: return 3887386;
|
||||
case E_META_DYE_BROWN: return 5320730;
|
||||
case E_META_DYE_BLUE: return 2437522;
|
||||
case E_META_DYE_PURPLE: return 8073150;
|
||||
case E_META_DYE_CYAN: return 2651799;
|
||||
case E_META_DYE_LIGHTGRAY: return 11250603;
|
||||
case E_META_DYE_GRAY: return 4408131;
|
||||
case E_META_DYE_PINK: return 14188952;
|
||||
case E_META_DYE_LIGHTGREEN: return 4312372;
|
||||
case E_META_DYE_YELLOW: return 14602026;
|
||||
case E_META_DYE_LIGHTBLUE: return 6719955;
|
||||
case E_META_DYE_MAGENTA: return 12801229;
|
||||
case E_META_DYE_ORANGE: return 15435844;
|
||||
case E_META_DYE_WHITE: return 15790320;
|
||||
default: ASSERT(!"Unhandled dye meta whilst trying to get colour code for fireworks!"); break;
|
||||
}
|
||||
}
|
88
src/WorldStorage/FireworksSerializer.h
Normal file
88
src/WorldStorage/FireworksSerializer.h
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// 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 const inline 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;
|
||||
};
|
@ -90,11 +90,19 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin
|
||||
}
|
||||
|
||||
// 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())
|
||||
{
|
||||
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);
|
||||
}
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
@ -659,6 +659,12 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user