#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 = shared_ptr( 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 = shared_ptr( 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 = shared_ptr( 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 = shared_ptr( 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 = shared_ptr( new DataItem(type, id, shared_ptr()) ); 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(id) + L"! (Max is " + _toString(MAX_ID_VALUE) + L")"); } if (itemsById.find(id) != itemsById.end()) { throw new IllegalArgumentException(L"Duplicate id value for " + _toString(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 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 = 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 = 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 = 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 = 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 value) { shared_ptr 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 > *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 = *it; writeDataItem(output, dataItem); } } // add an eof output->writeByte(EOF_MARKER); } vector > *SynchedEntityData::packDirty() { vector > *result = NULL; if (m_isDirty) { AUTO_VAR(itEnd, itemsById.end()); for ( AUTO_VAR(it, itemsById.begin()); it != itEnd; it++ ) { shared_ptr dataItem = (*it).second; if (dataItem->isDirty()) { dataItem->setDirty(false); if (result == NULL) { result = new vector >(); } 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 = (*it).second; writeDataItem(output, dataItem); } // add an eof output->writeByte(EOF_MARKER); } vector > *SynchedEntityData::getAll() { vector > *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 = (*it).second; result->push_back(dataItem); } return result; } void SynchedEntityData::writeDataItem(DataOutputStream *output, shared_ptr 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 instance = (shared_ptr )dataItem->getValue_itemInstance(); Packet::writeItem(instance, output); } break; default: assert(false); // 4J - not implemented break; } } vector > *SynchedEntityData::unpack(DataInputStream *input) //throws IOException { vector > *result = NULL; int currentHeader = input->readByte(); while (currentHeader != EOF_MARKER) { if (result == NULL) { result = new vector >(); } // split type and id int itemType = (currentHeader & TYPE_MASK) >> TYPE_SHIFT; int itemId = (currentHeader & MAX_ID_VALUE); shared_ptr item = shared_ptr(); switch (itemType) { case TYPE_BYTE: { byte dataRead = input->readByte(); item = shared_ptr( new DataItem(itemType, itemId, dataRead) ); } break; case TYPE_SHORT: { short dataRead = input->readShort(); item = shared_ptr( new DataItem(itemType, itemId, dataRead) ); } break; case TYPE_INT: { int dataRead = input->readInt(); item = shared_ptr( new DataItem(itemType, itemId, dataRead) ); } break; case TYPE_STRING: item = shared_ptr( new DataItem(itemType, itemId, Packet::readUtf(input, MAX_STRING_DATA_LENGTH)) ); break; case TYPE_ITEMINSTANCE: { item = shared_ptr(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 > *items) { AUTO_VAR(itEnd, items->end()); for (AUTO_VAR(it, items->begin()); it != itEnd; it++) { shared_ptr 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 = (*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) : 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) { 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 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; }