diff options
Diffstat (limited to 'Minecraft.World/SynchedEntityData.cpp')
| -rw-r--r-- | Minecraft.World/SynchedEntityData.cpp | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/Minecraft.World/SynchedEntityData.cpp b/Minecraft.World/SynchedEntityData.cpp new file mode 100644 index 00000000..9f1aa1f7 --- /dev/null +++ b/Minecraft.World/SynchedEntityData.cpp @@ -0,0 +1,558 @@ +#include "stdafx.h" +#include "Class.h" +#include "BasicTypeContainers.h" +#include "InputOutputStream.h" +#include "net.minecraft.h" +#include "net.minecraft.network.packet.h" +#include "net.minecraft.world.item.h" +#include "SynchedEntityData.h" + + +SynchedEntityData::SynchedEntityData() +{ + m_isDirty = false; + m_isEmpty = true; +} + +void SynchedEntityData::define(int id, int value) +{ + MemSect(17); + checkId(id); + int type = TYPE_INT; + shared_ptr<DataItem> dataItem = shared_ptr<DataItem>( new DataItem(type, id, value) ); + itemsById[id] = dataItem; + MemSect(0); + m_isEmpty = false; +} + +void SynchedEntityData::define(int id, byte value) +{ + MemSect(17); + checkId(id); + int type = TYPE_BYTE; + shared_ptr<DataItem> dataItem = shared_ptr<DataItem>( new DataItem(type, id, value) ); + itemsById[id] = dataItem; + MemSect(0); + m_isEmpty = false; +} + +void SynchedEntityData::define(int id, short value) +{ + MemSect(17); + checkId(id); + int type = TYPE_SHORT; + shared_ptr<DataItem> dataItem = shared_ptr<DataItem>( new DataItem(type, id, value) ); + itemsById[id] = dataItem; + MemSect(0); + m_isEmpty = false; +} + +void SynchedEntityData::define(int id, const wstring& value) +{ + MemSect(17); + checkId(id); + int type = TYPE_STRING; + shared_ptr<DataItem> dataItem = shared_ptr<DataItem>( new DataItem(type, id, value) ); + itemsById[id] = dataItem; + MemSect(0); + m_isEmpty = false; +} + +void SynchedEntityData::defineNULL(int id, void *pVal) +{ + MemSect(17); + checkId(id); + int type = TYPE_ITEMINSTANCE; + shared_ptr<DataItem> dataItem = shared_ptr<DataItem>( new DataItem(type, id, shared_ptr<ItemInstance>()) ); + itemsById[id] = dataItem; + MemSect(0); + m_isEmpty = false; +} + +void SynchedEntityData::checkId(int id) +{ +#if 0 + if (id > MAX_ID_VALUE) + { + throw new IllegalArgumentException(L"Data value id is too big with " + _toString<int>(id) + L"! (Max is " + _toString<int>(MAX_ID_VALUE) + L")"); + } + if (itemsById.find(id) != itemsById.end()) + { + throw new IllegalArgumentException(L"Duplicate id value for " + _toString<int>(id) + L"!"); + } +#endif +} + +byte SynchedEntityData::getByte(int id) +{ + return itemsById[id]->getValue_byte(); +} + +short SynchedEntityData::getShort(int id) +{ + return itemsById[id]->getValue_short(); +} + +int SynchedEntityData::getInteger(int id) +{ + return itemsById[id]->getValue_int(); +} + +float SynchedEntityData::getFloat(int id) +{ + assert(false); // 4J - not currently implemented + return 0; +} + +wstring SynchedEntityData::getString(int id) +{ + return itemsById[id]->getValue_wstring(); +} + +shared_ptr<ItemInstance> SynchedEntityData::getItemInstance(int id) +{ + //assert(false); // 4J - not currently implemented + return itemsById[id]->getValue_itemInstance(); +} + +Pos *SynchedEntityData::getPos(int id) +{ + assert(false); // 4J - not currently implemented + return NULL; +} + +void SynchedEntityData::set(int id, int value) +{ + shared_ptr<DataItem> dataItem = itemsById[id]; + + // update the value if it has changed + if (value != dataItem->getValue_int()) + { + dataItem->setValue(value); + dataItem->setDirty(true); + m_isDirty = true; + } +} + +void SynchedEntityData::set(int id, byte value) +{ + shared_ptr<DataItem> dataItem = itemsById[id]; + + // update the value if it has changed + if (value != dataItem->getValue_byte()) + { + dataItem->setValue(value); + dataItem->setDirty(true); + m_isDirty = true; + } +} + +void SynchedEntityData::set(int id, short value) +{ + shared_ptr<DataItem> dataItem = itemsById[id]; + + // update the value if it has changed + if (value != dataItem->getValue_short()) + { + dataItem->setValue(value); + dataItem->setDirty(true); + m_isDirty = true; + } +} + +void SynchedEntityData::set(int id, const wstring& value) +{ + shared_ptr<DataItem> dataItem = itemsById[id]; + + // update the value if it has changed + if (value != dataItem->getValue_wstring()) + { + dataItem->setValue(value); + dataItem->setDirty(true); + m_isDirty = true; + } +} + +void SynchedEntityData::set(int id, shared_ptr<ItemInstance> value) +{ + shared_ptr<DataItem> dataItem = itemsById[id]; + + // update the value if it has changed + if (value != dataItem->getValue_itemInstance()) + { + dataItem->setValue(value); + dataItem->setDirty(true); + m_isDirty = true; + } +} + +void SynchedEntityData::markDirty(int id) +{ + (*itemsById.find(id)).second->dirty = true; + m_isDirty = true; +} + +bool SynchedEntityData::isDirty() +{ + return m_isDirty; +} + +void SynchedEntityData::pack(vector<shared_ptr<DataItem> > *items, DataOutputStream *output) // TODO throws IOException +{ + + if (items != NULL) + { + AUTO_VAR(itEnd, items->end()); + for (AUTO_VAR(it, items->begin()); it != itEnd; it++) + { + shared_ptr<DataItem> dataItem = *it; + writeDataItem(output, dataItem); + } + } + + // add an eof + output->writeByte(EOF_MARKER); +} + +vector<shared_ptr<SynchedEntityData::DataItem> > *SynchedEntityData::packDirty() +{ + + vector<shared_ptr<DataItem> > *result = NULL; + + if (m_isDirty) + { + AUTO_VAR(itEnd, itemsById.end()); + for ( AUTO_VAR(it, itemsById.begin()); it != itEnd; it++ ) + { + shared_ptr<DataItem> dataItem = (*it).second; + if (dataItem->isDirty()) + { + dataItem->setDirty(false); + + if (result == NULL) + { + result = new vector<shared_ptr<DataItem> >(); + } + result->push_back(dataItem); + } + } + } + m_isDirty = false; + + return result; +} + +void SynchedEntityData::packAll(DataOutputStream *output) // throws IOException +{ + AUTO_VAR(itEnd, itemsById.end()); + for (AUTO_VAR(it, itemsById.begin()); it != itEnd; it++ ) + { + shared_ptr<DataItem> dataItem = (*it).second; + writeDataItem(output, dataItem); + } + + // add an eof + output->writeByte(EOF_MARKER); +} + +vector<shared_ptr<SynchedEntityData::DataItem> > *SynchedEntityData::getAll() +{ + vector<shared_ptr<DataItem> > *result = NULL; + + AUTO_VAR(itEnd, itemsById.end()); + for (AUTO_VAR(it, itemsById.begin()); it != itEnd; it++ ) + { + if (result == NULL) + { + result = new vector<shared_ptr<DataItem> >(); + } + shared_ptr<DataItem> dataItem = (*it).second; + result->push_back(dataItem); + } + + return result; +} + + +void SynchedEntityData::writeDataItem(DataOutputStream *output, shared_ptr<DataItem> dataItem) //throws IOException +{ + // pack type and id + int header = ((dataItem->getType() << TYPE_SHIFT) | (dataItem->getId() & MAX_ID_VALUE)) & 0xff; + output->writeByte(header); + + // write value + switch (dataItem->getType()) + { + case TYPE_BYTE: + output->writeByte( dataItem->getValue_byte()); + break; + case TYPE_INT: + output->writeInt( dataItem->getValue_int()); + break; + case TYPE_SHORT: + output->writeShort( dataItem->getValue_short()); + break; + case TYPE_STRING: + Packet::writeUtf(dataItem->getValue_wstring(), output); + break; + case TYPE_ITEMINSTANCE: + { + shared_ptr<ItemInstance> instance = (shared_ptr<ItemInstance> )dataItem->getValue_itemInstance(); + Packet::writeItem(instance, output); + } + break; + + default: + assert(false); // 4J - not implemented + break; + } +} + +vector<shared_ptr<SynchedEntityData::DataItem> > *SynchedEntityData::unpack(DataInputStream *input) //throws IOException +{ + + vector<shared_ptr<DataItem> > *result = NULL; + + int currentHeader = input->readByte(); + + while (currentHeader != EOF_MARKER) + { + + if (result == NULL) + { + result = new vector<shared_ptr<DataItem> >(); + } + + // split type and id + int itemType = (currentHeader & TYPE_MASK) >> TYPE_SHIFT; + int itemId = (currentHeader & MAX_ID_VALUE); + + shared_ptr<DataItem> item = shared_ptr<DataItem>(); + switch (itemType) + { + case TYPE_BYTE: + { + byte dataRead = input->readByte(); + item = shared_ptr<DataItem>( new DataItem(itemType, itemId, dataRead) ); + } + break; + case TYPE_SHORT: + { + short dataRead = input->readShort(); + item = shared_ptr<DataItem>( new DataItem(itemType, itemId, dataRead) ); + } + break; + case TYPE_INT: + { + int dataRead = input->readInt(); + item = shared_ptr<DataItem>( new DataItem(itemType, itemId, dataRead) ); + } + break; + case TYPE_STRING: + item = shared_ptr<DataItem>( new DataItem(itemType, itemId, Packet::readUtf(input, MAX_STRING_DATA_LENGTH)) ); + break; + case TYPE_ITEMINSTANCE: + { + item = shared_ptr<DataItem>(new DataItem(itemType, itemId, Packet::readItem(input))); + } + break; + default: + app.DebugPrintf(" ------ garbage data, or early end of stream due to an incomplete packet\n"); + delete result; + return NULL; + break; + } + result->push_back(item); + + currentHeader = input->readByte(); + } + + return result; +} + +/** +* Assigns values from a list of data items. +* +* @param items +*/ + +void SynchedEntityData::assignValues(vector<shared_ptr<DataItem> > *items) +{ + AUTO_VAR(itEnd, items->end()); + for (AUTO_VAR(it, items->begin()); it != itEnd; it++) + { + shared_ptr<DataItem> item = *it; + AUTO_VAR(itemFromId, itemsById.find(item->getId())); + if (itemFromId != itemsById.end() ) + { + switch(item->getType()) + { + case TYPE_BYTE: + itemFromId->second->setValue(item->getValue_byte()); + break; + case TYPE_SHORT: + itemFromId->second->setValue(item->getValue_short()); + break; + case TYPE_INT: + itemFromId->second->setValue(item->getValue_int()); + break; + case TYPE_STRING: + itemFromId->second->setValue(item->getValue_wstring()); + break; + case TYPE_ITEMINSTANCE: + itemFromId->second->setValue(item->getValue_itemInstance()); + break; + default: + assert(false); // 4J - not implemented + break; + } + } + } +} + +bool SynchedEntityData::isEmpty() +{ + return m_isEmpty; +} + +int SynchedEntityData::getSizeInBytes() +{ + int size = 1; + + AUTO_VAR(itEnd, itemsById.end()); + for (AUTO_VAR(it, itemsById.begin()); it != itEnd; it++ ) + { + shared_ptr<DataItem> dataItem = (*it).second; + + size += 1; + + // write value + switch (dataItem->getType()) + { + case TYPE_BYTE: + size += 1; + break; + case TYPE_SHORT: + size += 2; + break; + case TYPE_INT: + size += 4; + break; + case TYPE_STRING: + size += (int)dataItem->getValue_wstring().length() + 2; // Estimate, assuming all ascii chars + break; + case TYPE_ITEMINSTANCE: + // short + byte + short + size += 2 + 1 + 2; // Estimate, assuming all ascii chars + break; + default: + break; + } + } + return size; +} + + +////////////////// +// DataItem class +///////////////// + +SynchedEntityData::DataItem::DataItem(int type, int id, int value) : type( type ), id( id ) +{ + this->value_int = value; + this->dirty = true; +} + +SynchedEntityData::DataItem::DataItem(int type, int id, byte value) : type( type ), id( id ) +{ + this->value_byte = value; + this->dirty = true; +} + +SynchedEntityData::DataItem::DataItem(int type, int id, short value) : type( type ), id( id ) +{ + this->value_short = value; + this->dirty = true; +} + +SynchedEntityData::DataItem::DataItem(int type, int id, const wstring& value) : type( type ), id( id ) +{ + this->value_wstring = value; + this->dirty = true; +} + +SynchedEntityData::DataItem::DataItem(int type, int id, shared_ptr<ItemInstance> itemInstance) : type( type ), id( id ) +{ + this->value_itemInstance = itemInstance; + this->dirty = true; +} + +int SynchedEntityData::DataItem::getId() +{ + return id; +} + +void SynchedEntityData::DataItem::setValue(int value) +{ + this->value_int = value; +} + +void SynchedEntityData::DataItem::setValue(byte value) +{ + this->value_byte = value; +} + +void SynchedEntityData::DataItem::setValue(short value) +{ + this->value_short = value; +} + +void SynchedEntityData::DataItem::setValue(const wstring& value) +{ + this->value_wstring = value; +} + +void SynchedEntityData::DataItem::setValue(shared_ptr<ItemInstance> itemInstance) +{ + this->value_itemInstance = itemInstance; +} + +int SynchedEntityData::DataItem::getValue_int() +{ + return value_int; +} + +short SynchedEntityData::DataItem::getValue_short() +{ + return value_short; +} + +byte SynchedEntityData::DataItem::getValue_byte() +{ + return value_byte; +} + +wstring SynchedEntityData::DataItem::getValue_wstring() +{ + return value_wstring; +} + +shared_ptr<ItemInstance> SynchedEntityData::DataItem::getValue_itemInstance() +{ + return value_itemInstance; +} + +int SynchedEntityData::DataItem::getType() +{ + return type; +} + +bool SynchedEntityData::DataItem::isDirty() +{ + return dirty; +} + +void SynchedEntityData::DataItem::setDirty(bool dirty) +{ + this->dirty = dirty; +}
\ No newline at end of file |
