void SV_BufferRemoveFormat (CDBuffer* self, const char* format, ...) { va_list ap; va_start(ap, format); while (*format != '\0') { CDPointer pointer = va_arg(ap, CDPointer); switch (*format) { case 'b': *((SVByte*) pointer) = SV_BufferRemoveByte(self); break; case 's': *((SVShort*) pointer) = SV_BufferRemoveShort(self); break; case 'i': *((SVInteger*) pointer) = SV_BufferRemoveInteger(self); break; case 'l': *((SVLong*) pointer) = SV_BufferRemoveLong(self); break; case 'f': *((SVFloat*) pointer) = SV_BufferRemoveFloat(self); break; case 'd': *((SVDouble*) pointer) = SV_BufferRemoveDouble(self); break; case 'B': *((SVBoolean*) pointer) = SV_BufferRemoveBoolean(self); break; case 'S': *((SVString*) pointer) = SV_BufferRemoveString(self); break; case 'M': *((SVMetadata**) pointer) = SV_BufferRemoveMetadata(self); break; } format++; } va_end(ap); }
SVPacket* SV_PacketFromBuffers (CDBuffers* buffers) { SVPacket* self = CD_malloc(sizeof(SVPacket)); assert(self); self->chain = SVRequest; self->type = (uint32_t) (uint8_t) SV_BufferRemoveByte(buffers->input); self->data = SV_GetPacketDataFromBuffer(self, buffers->input); if (!self->data) { ERR("unparsable packet 0x%.2X", self->type); SV_DestroyPacket(self); errno = EILSEQ; return NULL; } return self; }
SVMetadata* SV_BufferRemoveMetadata (CDBuffer* self) { SVMetadata* metadata = SV_CreateMetadata(); SVData* current = NULL; SVByte type = 0; // Format strings of the different metadata types static char* formats[] = { "b", "s", "i", "f", "S" }; while (!CD_BufferEmpty(self)) { type = SV_BufferRemoveByte(self); if (type == 127) { break; } current = SV_CreateData(); current->type = type >> 5; if (current->type == SVTypeShortByteShort) { SV_BufferRemoveFormat(self, "sbs", ¤t->data.sbs.first, ¤t->data.sbs.second, ¤t->data.sbs.third ); } else { SV_BufferRemoveFormat(self, formats[current->type], ¤t->data); } SV_AppendData(metadata, current); } return metadata; }
CDPointer SV_GetPacketDataFromBuffer (SVPacket* self, CDBuffer* input) { assert(self); assert(input); switch (self->type) { case SVKeepAlive: { return (CDPointer) CD_malloc(sizeof(SVPacketKeepAlive)); } case SVLogin: { SVPacketLogin* packet = (SVPacketLogin*) CD_malloc(sizeof(SVPacketLogin)); SV_BufferRemoveFormat(input, "iUlb", &packet->request.version, &packet->request.username, &packet->request.mapSeed, &packet->request.dimension ); return (CDPointer) packet; } case SVHandshake: { SVPacketHandshake* packet = (SVPacketHandshake*) CD_malloc(sizeof(SVPacketHandshake)); packet->request.username = SV_BufferRemoveString16(input); return (CDPointer) packet; } case SVChat: { SVPacketChat* packet = (SVPacketChat*) CD_malloc(sizeof(SVPacketChat)); packet->request.message = SV_BufferRemoveString16(input); return (CDPointer) packet; } case SVUseEntity: { SVPacketUseEntity* packet = (SVPacketUseEntity*) CD_malloc(sizeof(SVPacketUseEntity)); SV_BufferRemoveFormat(input, "iib", &packet->request.user, &packet->request.target, &packet->request.leftClick ); return (CDPointer) packet; } case SVRespawn: { return (CDPointer) CD_malloc(sizeof(SVPacketRespawn)); } case SVOnGround: { SVPacketOnGround* packet = (SVPacketOnGround*) CD_malloc(sizeof(SVPacketOnGround)); packet->request.onGround = SV_BufferRemoveBoolean(input); return (CDPointer) packet; } case SVPlayerPosition: { SVPacketPlayerPosition* packet = (SVPacketPlayerPosition*) CD_malloc(sizeof(SVPacketPlayerPosition)); SV_BufferRemoveFormat(input, "ddddb", &packet->request.position.x, &packet->request.position.y, &packet->request.stance, &packet->request.position.z, &packet->request.is.onGround ); return (CDPointer) packet; } case SVPlayerLook: { SVPacketPlayerLook* packet = (SVPacketPlayerLook*) CD_malloc(sizeof(SVPacketPlayerLook)); SV_BufferRemoveFormat(input, "ffb", &packet->request.yaw, &packet->request.pitch, &packet->request.is.onGround ); return (CDPointer) packet; } case SVPlayerMoveLook: { SVPacketPlayerMoveLook* packet = (SVPacketPlayerMoveLook*) CD_malloc(sizeof(SVPacketPlayerMoveLook)); SV_BufferRemoveFormat(input, "ddddffb", &packet->request.position.x, &packet->request.stance, &packet->request.position.y, &packet->request.position.z, &packet->request.yaw, &packet->request.pitch, &packet->request.is.onGround ); return (CDPointer) packet; } case SVPlayerDigging: { SVPacketPlayerDigging* packet = (SVPacketPlayerDigging*) CD_malloc(sizeof(SVPacketPlayerDigging)); packet->request.status = SV_BufferRemoveByte(input); SV_BufferRemoveFormat(input, "ibi", &packet->request.position.x, &packet->request.position.y, &packet->request.position.z ); packet->request.face = SV_BufferRemoveByte(input); return (CDPointer) packet; } case SVPlayerBlockPlacement: { SVPacketPlayerBlockPlacement* packet = (SVPacketPlayerBlockPlacement*) CD_malloc(sizeof(SVPacketPlayerBlockPlacement)); SV_BufferRemoveFormat(input, "ibibs", &packet->request.position.x, &packet->request.position.y, &packet->request.position.z, &packet->request.direction, &packet->request.item.id ); if (packet->request.item.id != -1) { SV_BufferRemoveFormat(input, "bs", &packet->request.item.count, &packet->request.item.uses ); } return (CDPointer) packet; } case SVHoldChange: { SVPacketHoldChange* packet = (SVPacketHoldChange*) CD_malloc(sizeof(SVPacketHoldChange)); packet->request.item.id = SV_BufferRemoveShort(input); return (CDPointer) packet; } case SVAnimation: { SVPacketAnimation* packet = (SVPacketAnimation*) CD_malloc(sizeof(SVPacketAnimation)); SV_BufferRemoveFormat(input, "ib", &packet->request.entity.id, &packet->request.type ); return (CDPointer) packet; } case SVEntityAction: { SVPacketEntityAction* packet = (SVPacketEntityAction*) CD_malloc(sizeof(SVPacketEntityAction)); packet->request.entity.id = SV_BufferRemoveInteger(input); packet->request.action = SV_BufferRemoveByte(input); return (CDPointer) packet; } case SVEntityMetadata: { SVPacketEntityMetadata* packet = (SVPacketEntityMetadata*) CD_malloc(sizeof(SVPacketEntityMetadata)); SV_BufferRemoveFormat(input, "iM", &packet->request.entity.id, &packet->request.metadata ); return (CDPointer) packet; } case SVCloseWindow: { SVPacketCloseWindow* packet = (SVPacketCloseWindow*) CD_malloc(sizeof(SVPacketCloseWindow)); packet->request.id = SV_BufferRemoveByte(input); return (CDPointer) packet; } case SVWindowClick: { SVPacketWindowClick* packet = (SVPacketWindowClick*) CD_malloc(sizeof(SVPacketWindowClick)); SV_BufferRemoveFormat(input, "bsBss", &packet->request.id, &packet->request.slot, &packet->request.rightClick, &packet->request.action, &packet->request.item.id ); if (packet->request.item.id != -1) { SV_BufferRemoveFormat(input, "bs", &packet->request.item.count, &packet->request.item.uses ); } return (CDPointer) packet; } case SVTransaction: { SVPacketTransaction* packet = (SVPacketTransaction*) CD_malloc(sizeof(SVPacketTransaction)); SV_BufferRemoveFormat(input, "bsB", &packet->request.id, &packet->request.action, &packet->request.accepted ); return (CDPointer) packet; } case SVUpdateSign: { SVPacketUpdateSign* packet = (SVPacketUpdateSign*) CD_malloc(sizeof(SVPacketUpdateSign)); SV_BufferRemoveFormat(input, "iisiUUUU", &packet->request.position.x, &packet->request.position.y, &packet->request.position.z, &packet->request.first, &packet->request.second, &packet->request.third, &packet->request.fourth ); return (CDPointer) packet; } case SVIncrementStatistic: { SVPacketIncrementStatistic* packet = (SVPacketIncrementStatistic*) CD_malloc(sizeof(SVPacketIncrementStatistic)); SV_BufferRemoveFormat(input, "ib", &packet->request.id, &packet->request.amount ); return (CDPointer) packet; } case SVDisconnect: { SVPacketDisconnect* packet = (SVPacketDisconnect*) CD_malloc(sizeof(SVPacketDisconnect)); packet->request.reason = SV_BufferRemoveString16(input); return (CDPointer) packet; } default: { return (CDPointer) NULL; } } }