mirror of https://github.com/basinserver/basin/
Added dynamic world loading
This commit is contained in:
parent
be2f415ac5
commit
9d7191cd59
|
@ -74,3 +74,15 @@ int rem_collection(struct collection* coll, void* data) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int contains_collection(struct collection* coll, void* data) {
|
||||||
|
pthread_rwlock_rdlock(&coll->data_mutex);
|
||||||
|
for (int i = 0; i < coll->size; i++) {
|
||||||
|
if (coll->data[i] == data) {
|
||||||
|
pthread_rwlock_unlock(&coll->data_mutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_rwlock_unlock(&coll->data_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,4 +27,6 @@ int add_collection(struct collection* coll, void* data);
|
||||||
|
|
||||||
int rem_collection(struct collection* coll, void* data);
|
int rem_collection(struct collection* coll, void* data);
|
||||||
|
|
||||||
|
int contains_collection(struct collection* coll, void* data);
|
||||||
|
|
||||||
#endif /* COLLECTION_H_ */
|
#endif /* COLLECTION_H_ */
|
||||||
|
|
137
basin/src/game.c
137
basin/src/game.c
|
@ -26,6 +26,96 @@ void flush_outgoing(struct player* player) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadPlayer(struct player* to, struct player* from) {
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_SPAWNPLAYER;
|
||||||
|
pkt->data.play_client.spawnplayer.entity_id = from->entity->id;
|
||||||
|
memcpy(&pkt->data.play_client.spawnplayer.player_uuid, &from->entity->data.player.player->uuid, sizeof(struct uuid));
|
||||||
|
pkt->data.play_client.spawnplayer.x = from->entity->x;
|
||||||
|
pkt->data.play_client.spawnplayer.y = from->entity->y;
|
||||||
|
pkt->data.play_client.spawnplayer.z = from->entity->z;
|
||||||
|
pkt->data.play_client.spawnplayer.yaw = (from->entity->yaw / 360.) * 256.;
|
||||||
|
pkt->data.play_client.spawnplayer.pitch = (from->entity->pitch / 360.) * 256.;
|
||||||
|
writeMetadata(from->entity, &pkt->data.play_client.spawnplayer.metadata.metadata, &pkt->data.play_client.spawnplayer.metadata.metadata_size);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 0;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[from->currentItem + 36], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 5;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[5], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 4;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[6], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 3;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[7], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 2;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[8], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = from->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 1;
|
||||||
|
duplicateSlot(from->inventory.slots == NULL ? NULL : from->inventory.slots[45], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(to->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onInventoryUpdate(struct inventory* inventory, int slot) {
|
||||||
|
if (inventory->type == INVTYPE_PLAYERINVENTORY) {
|
||||||
|
if (slot == inventory->player->currentItem + 36) {
|
||||||
|
BEGIN_BROADCAST_EXCEPT_DIST(inventory->player, inventory->player->entity, 128.)
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = inventory->player->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 0;
|
||||||
|
duplicateSlot(inventory->slots == NULL ? NULL : inventory->slots[inventory->player->currentItem + 36], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(bc_player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing (bc_player);
|
||||||
|
END_BROADCAST
|
||||||
|
} else if (slot >= 5 && slot <= 8) {
|
||||||
|
BEGIN_BROADCAST_EXCEPT_DIST(inventory->player, inventory->player->entity, 128.)
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = inventory->player->entity->id;
|
||||||
|
if (slot == 5) pkt->data.play_client.entityequipment.slot = 5;
|
||||||
|
else if (slot == 6) pkt->data.play_client.entityequipment.slot = 4;
|
||||||
|
else if (slot == 7) pkt->data.play_client.entityequipment.slot = 3;
|
||||||
|
else if (slot == 8) pkt->data.play_client.entityequipment.slot = 2;
|
||||||
|
duplicateSlot(inventory->slots == NULL ? NULL : inventory->slots[slot], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(bc_player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing (bc_player);
|
||||||
|
END_BROADCAST
|
||||||
|
} else if (slot == 45) {
|
||||||
|
BEGIN_BROADCAST_EXCEPT_DIST(inventory->player, inventory->player->entity, 128.)
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYEQUIPMENT;
|
||||||
|
pkt->data.play_client.entityequipment.entity_id = inventory->player->entity->id;
|
||||||
|
pkt->data.play_client.entityequipment.slot = 1;
|
||||||
|
duplicateSlot(inventory->slots == NULL ? NULL : inventory->slots[45], &pkt->data.play_client.entityequipment.item);
|
||||||
|
add_queue(bc_player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing (bc_player);
|
||||||
|
END_BROADCAST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tick_player(struct world* world, struct player* player) {
|
void tick_player(struct world* world, struct player* player) {
|
||||||
if (tick_counter % 200 == 0) {
|
if (tick_counter % 200 == 0) {
|
||||||
if (player->nextKeepAlive != 0) {
|
if (player->nextKeepAlive != 0) {
|
||||||
|
@ -39,6 +129,53 @@ void tick_player(struct world* world, struct player* player) {
|
||||||
add_queue(player->conn->outgoingPacket, pkt);
|
add_queue(player->conn->outgoingPacket, pkt);
|
||||||
flush_outgoing(player);
|
flush_outgoing(player);
|
||||||
}
|
}
|
||||||
|
int32_t pcx = ((int32_t) player->entity->x >> 4);
|
||||||
|
int32_t pcz = ((int32_t) player->entity->z >> 4);
|
||||||
|
if (((int32_t) player->entity->lx >> 4) != pcx || ((int32_t) player->entity->lz >> 4) != pcz || player->loadedChunks->count == 0) {
|
||||||
|
for (int x = -CHUNK_VIEW_DISTANCE + pcx; x <= CHUNK_VIEW_DISTANCE + pcx; x++) {
|
||||||
|
for (int z = -CHUNK_VIEW_DISTANCE + pcz; z <= CHUNK_VIEW_DISTANCE + pcz; z++) {
|
||||||
|
struct chunk* ch = getChunk(player->world, x, z);
|
||||||
|
if (ch != NULL && !contains_collection(player->loadedChunks, ch)) {
|
||||||
|
ch->playersLoaded++;
|
||||||
|
add_collection(player->loadedChunks, ch);
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_CHUNKDATA;
|
||||||
|
pkt->data.play_client.chunkdata.data = ch;
|
||||||
|
pkt->data.play_client.chunkdata.ground_up_continuous = 1;
|
||||||
|
pkt->data.play_client.chunkdata.number_of_block_entities = 0;
|
||||||
|
pkt->data.play_client.chunkdata.block_entities = NULL;
|
||||||
|
add_queue(player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing(player);
|
||||||
|
//printf("client load %i, %i\n", ch->x, ch->z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_rwlock_wrlock(&player->loadedChunks->data_mutex);
|
||||||
|
for (int i = 0; i < player->loadedChunks->size; i++) {
|
||||||
|
struct chunk* ch = player->loadedChunks->data[i];
|
||||||
|
if (ch == NULL) continue;
|
||||||
|
int dx = (ch->x - pcx);
|
||||||
|
if (dx < 0) dx = -dx;
|
||||||
|
int dz = (ch->z - pcz);
|
||||||
|
if (dz < 0) dz = -dz;
|
||||||
|
if (dx > CHUNK_VIEW_DISTANCE || dz > CHUNK_VIEW_DISTANCE) {
|
||||||
|
//printf("client unload %i, %i\n", ch->x, ch->z);
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_UNLOADCHUNK;
|
||||||
|
pkt->data.play_client.unloadchunk.chunk_x = ch->x;
|
||||||
|
pkt->data.play_client.unloadchunk.chunk_z = ch->z;
|
||||||
|
add_queue(player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing(player);
|
||||||
|
player->loadedChunks->data[i] = NULL;
|
||||||
|
player->loadedChunks->count--;
|
||||||
|
if (--ch->playersLoaded <= 0) {
|
||||||
|
//printf("server unload %i, %i\n", ch->x, ch->z);
|
||||||
|
unloadChunk(player->world, ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_rwlock_unlock(&player->loadedChunks->data_mutex);
|
||||||
|
}
|
||||||
if (player->digging >= 0.) {
|
if (player->digging >= 0.) {
|
||||||
struct block_info* bi = &block_infos[getBlockWorld(world, player->digging_position.x, player->digging_position.y, player->digging_position.z)];
|
struct block_info* bi = &block_infos[getBlockWorld(world, player->digging_position.x, player->digging_position.y, player->digging_position.z)];
|
||||||
float digspeed = 0.;
|
float digspeed = 0.;
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
void flush_outgoing(struct player* player);
|
void flush_outgoing(struct player* player);
|
||||||
|
|
||||||
|
void loadPlayer(struct player* to, struct player* from);
|
||||||
|
|
||||||
|
void onInventoryUpdate(struct inventory* inventory, int slot);
|
||||||
|
|
||||||
void tick_world(struct world* world);
|
void tick_world(struct world* world);
|
||||||
|
|
||||||
void broadcast(char* text);
|
void broadcast(char* text);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define GLOBALS_H_
|
#define GLOBALS_H_
|
||||||
|
|
||||||
#define MC_PROTOCOL_VERSION 315
|
#define MC_PROTOCOL_VERSION 315
|
||||||
|
#define CHUNK_VIEW_DISTANCE 10
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,21 @@
|
||||||
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include <GL/gl.h>
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
void newInventory(struct inventory* inv, int type, int id) {
|
void newInventory(struct inventory* inv, int type, int id, int slots) {
|
||||||
inv->title = NULL;
|
inv->title = NULL;
|
||||||
inv->slots = NULL;
|
inv->slots = NULL;
|
||||||
inv->slot_count = 0;
|
inv->slot_count = slots;
|
||||||
inv->props = NULL;
|
inv->props = NULL;
|
||||||
inv->prop_count = 0;
|
inv->prop_count = 0;
|
||||||
inv->type = type;
|
inv->type = type;
|
||||||
inv->windowID = id;
|
inv->windowID = id;
|
||||||
|
inv->player = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _freeInventorySlots(struct inventory* inv) {
|
void _freeInventorySlots(struct inventory* inv) {
|
||||||
|
@ -29,22 +30,22 @@ void _freeInventorySlots(struct inventory* inv) {
|
||||||
if (inv->slots[i] == NULL) continue;
|
if (inv->slots[i] == NULL) continue;
|
||||||
if (inv->slots[i]->nbt != NULL) {
|
if (inv->slots[i]->nbt != NULL) {
|
||||||
freeNBT(inv->slots[i]->nbt);
|
freeNBT(inv->slots[i]->nbt);
|
||||||
free(inv->slots[i]->nbt);
|
xfree(inv->slots[i]->nbt);
|
||||||
}
|
}
|
||||||
free(inv->slots[i]);
|
xfree(inv->slots[i]);
|
||||||
}
|
}
|
||||||
free(inv->slots);
|
xfree(inv->slots);
|
||||||
inv->slots = NULL;
|
inv->slots = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeInventory(struct inventory* inv) {
|
void freeInventory(struct inventory* inv) {
|
||||||
if (inv->title != NULL) free(inv->title);
|
if (inv->title != NULL) xfree(inv->title);
|
||||||
if (inv->props != NULL) {
|
if (inv->props != NULL) {
|
||||||
for (size_t i = 0; i < inv->prop_count; i++) {
|
for (size_t i = 0; i < inv->prop_count; i++) {
|
||||||
free(inv->props[i]);
|
xfree(inv->props[i]);
|
||||||
}
|
}
|
||||||
free(inv->props);
|
xfree(inv->props);
|
||||||
}
|
}
|
||||||
_freeInventorySlots(inv);
|
_freeInventorySlots(inv);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +74,8 @@ void setInventoryItems(struct inventory* inv, struct slot** slots, size_t slot_c
|
||||||
for (size_t i = 0; i < slot_count; i++) {
|
for (size_t i = 0; i < slot_count; i++) {
|
||||||
if (slots[i]->item < 0) {
|
if (slots[i]->item < 0) {
|
||||||
if (slots[i]->nbt != NULL) freeNBT(slots[i]->nbt);
|
if (slots[i]->nbt != NULL) freeNBT(slots[i]->nbt);
|
||||||
free(slots[i]);
|
xfree(slots[i]->nbt);
|
||||||
|
xfree(slots[i]);
|
||||||
slots[i] = NULL;
|
slots[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,27 +87,21 @@ void setInventorySlot(struct inventory* inv, struct slot* slot, int index) {
|
||||||
if (index < 0 || index >= inv->slot_count) return;
|
if (index < 0 || index >= inv->slot_count) return;
|
||||||
if (inv->slots == NULL) {
|
if (inv->slots == NULL) {
|
||||||
if (inv->slot_count < 1) return;
|
if (inv->slot_count < 1) return;
|
||||||
inv->slots = malloc(sizeof(struct slot*) * inv->slot_count);
|
inv->slots = xmalloc(sizeof(struct slot*) * inv->slot_count);
|
||||||
for (int i = 0; i < inv->slot_count; i++) {
|
for (int i = 0; i < inv->slot_count; i++) {
|
||||||
inv->slots[i] = NULL;
|
inv->slots[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (slot != NULL && slot->item < 0) {
|
|
||||||
if (slot->nbt != NULL) {
|
|
||||||
freeNBT(slot->nbt);
|
|
||||||
free(slot->nbt);
|
|
||||||
}
|
|
||||||
free(slot);
|
|
||||||
slot = NULL;
|
|
||||||
}
|
|
||||||
if (inv->slots[index] != NULL) {
|
if (inv->slots[index] != NULL) {
|
||||||
if (inv->slots[index]->nbt != NULL) {
|
if (inv->slots[index]->nbt != NULL) {
|
||||||
freeNBT(inv->slots[index]->nbt);
|
freeNBT(inv->slots[index]->nbt);
|
||||||
free(inv->slots[index]->nbt);
|
xfree(inv->slots[index]->nbt);
|
||||||
}
|
}
|
||||||
free(inv->slots[index]);
|
xfree(inv->slots[index]);
|
||||||
}
|
}
|
||||||
inv->slots[index] = slot;
|
if (slot != NULL && slot->item == -1) slot = NULL;
|
||||||
|
inv->slots[index] = xmalloc(sizeof(struct slot));
|
||||||
|
duplicateSlot(slot, inv->slots[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInventoryProperty(struct inventory* inv, int16_t name, int16_t value) {
|
void setInventoryProperty(struct inventory* inv, int16_t name, int16_t value) {
|
||||||
|
@ -116,12 +112,12 @@ void setInventoryProperty(struct inventory* inv, int16_t name, int16_t value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inv->props = realloc(inv->props, sizeof(int16_t*) * (inv->prop_count + 1));
|
inv->props = xrealloc(inv->props, sizeof(int16_t*) * (inv->prop_count + 1));
|
||||||
} else {
|
} else {
|
||||||
inv->props = malloc(sizeof(int16_t*));
|
inv->props = xmalloc(sizeof(int16_t*));
|
||||||
inv->prop_count = 0;
|
inv->prop_count = 0;
|
||||||
}
|
}
|
||||||
int16_t* dm = malloc(sizeof(int16_t) * 2);
|
int16_t* dm = xmalloc(sizeof(int16_t) * 2);
|
||||||
dm[0] = name;
|
dm[0] = name;
|
||||||
dm[1] = value;
|
dm[1] = value;
|
||||||
inv->props[inv->prop_count++] = dm;
|
inv->props[inv->prop_count++] = dm;
|
||||||
|
|
|
@ -47,9 +47,10 @@ struct inventory {
|
||||||
int16_t** props;
|
int16_t** props;
|
||||||
size_t prop_count;
|
size_t prop_count;
|
||||||
int windowID;
|
int windowID;
|
||||||
|
struct player* player; // only for player inventories
|
||||||
};
|
};
|
||||||
|
|
||||||
void newInventory(struct inventory* inv, int type, int id);
|
void newInventory(struct inventory* inv, int type, int id, int slots);
|
||||||
|
|
||||||
void freeInventory(struct inventory* inv);
|
void freeInventory(struct inventory* inv);
|
||||||
|
|
||||||
|
|
|
@ -7,24 +7,27 @@
|
||||||
|
|
||||||
#include "nbt.h"
|
#include "nbt.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include "xstring.h"
|
||||||
|
#include "util.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
void freeNBT(struct nbt_tag* nbt) {
|
void freeNBT(struct nbt_tag* nbt) {
|
||||||
if (nbt->name != NULL) free(nbt->name);
|
if (nbt->name != NULL) xfree(nbt->name);
|
||||||
if (nbt->children != NULL) {
|
if (nbt->children != NULL) {
|
||||||
for (size_t i = 0; i < nbt->children_count; i++) {
|
for (size_t i = 0; i < nbt->children_count; i++) {
|
||||||
freeNBT(nbt->children[i]);
|
freeNBT(nbt->children[i]);
|
||||||
free(nbt->children[i]);
|
xfree(nbt->children[i]);
|
||||||
}
|
}
|
||||||
free(nbt->children);
|
xfree(nbt->children);
|
||||||
}
|
}
|
||||||
if (nbt->id == NBT_TAG_BYTEARRAY) {
|
if (nbt->id == NBT_TAG_BYTEARRAY) {
|
||||||
free(nbt->data.nbt_bytearray.data);
|
xfree(nbt->data.nbt_bytearray.data);
|
||||||
} else if (nbt->id == NBT_TAG_STRING) {
|
} else if (nbt->id == NBT_TAG_STRING) {
|
||||||
free(nbt->data.nbt_string);
|
xfree(nbt->data.nbt_string);
|
||||||
} else if (nbt->id == NBT_TAG_INTARRAY) {
|
} else if (nbt->id == NBT_TAG_INTARRAY) {
|
||||||
free(nbt->data.nbt_intarray.ints);
|
xfree(nbt->data.nbt_intarray.ints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,19 +39,19 @@ struct nbt_tag* getNBTChild(struct nbt_tag* nbt, char* name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nbt_tag* cloneNBT(struct nbt_tag* nbt) {
|
struct nbt_tag* cloneNBT(struct nbt_tag* nbt) {
|
||||||
struct nbt_tag* nt = malloc(sizeof(struct nbt_tag));
|
struct nbt_tag* nt = xmalloc(sizeof(struct nbt_tag));
|
||||||
nt->name = nbt->name == NULL ? NULL : strdup(nbt->name);
|
nt->name = nbt->name == NULL ? NULL : xstrdup(nbt->name, 0);
|
||||||
nt->id = nbt->id;
|
nt->id = nbt->id;
|
||||||
nt->children_count = nbt->children_count;
|
nt->children_count = nbt->children_count;
|
||||||
nt->children = nt->children_count == 0 ? NULL : malloc(sizeof(struct nbt_tag*) * nt->children_count);
|
nt->children = nt->children_count == 0 ? NULL : xmalloc(sizeof(struct nbt_tag*) * nt->children_count);
|
||||||
memcpy(&nt->data, &nbt->data, sizeof(union nbt_data));
|
memcpy(&nt->data, &nbt->data, sizeof(union nbt_data));
|
||||||
if (nbt->id == NBT_TAG_BYTEARRAY) {
|
if (nbt->id == NBT_TAG_BYTEARRAY) {
|
||||||
nt->data.nbt_bytearray.data = malloc(nt->data.nbt_bytearray.len);
|
nt->data.nbt_bytearray.data = xmalloc(nt->data.nbt_bytearray.len);
|
||||||
memcpy(nt->data.nbt_bytearray.data, nbt->data.nbt_bytearray.data, nt->data.nbt_bytearray.len);
|
memcpy(nt->data.nbt_bytearray.data, nbt->data.nbt_bytearray.data, nt->data.nbt_bytearray.len);
|
||||||
} else if (nbt->id == NBT_TAG_STRING) {
|
} else if (nbt->id == NBT_TAG_STRING) {
|
||||||
nt->data.nbt_string = strdup(nbt->data.nbt_string);
|
nt->data.nbt_string = xstrdup(nbt->data.nbt_string, 0);
|
||||||
} else if (nbt->id == NBT_TAG_INTARRAY) {
|
} else if (nbt->id == NBT_TAG_INTARRAY) {
|
||||||
nt->data.nbt_intarray.ints = malloc(nt->data.nbt_intarray.count * 4);
|
nt->data.nbt_intarray.ints = xmalloc(nt->data.nbt_intarray.count * 4);
|
||||||
memcpy(nt->data.nbt_intarray.ints, nbt->data.nbt_intarray.ints, nt->data.nbt_intarray.count * 4);
|
memcpy(nt->data.nbt_intarray.ints, nbt->data.nbt_intarray.ints, nt->data.nbt_intarray.count * 4);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < nt->children_count; i++) {
|
for (size_t i = 0; i < nt->children_count; i++) {
|
||||||
|
@ -58,7 +61,7 @@ struct nbt_tag* cloneNBT(struct nbt_tag* nbt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int __recurReadNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen, int list) {
|
int __recurReadNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen, int list) {
|
||||||
struct nbt_tag* cur = malloc(sizeof(struct nbt_tag));
|
struct nbt_tag* cur = xmalloc(sizeof(struct nbt_tag));
|
||||||
cur->name = NULL;
|
cur->name = NULL;
|
||||||
cur->children = NULL;
|
cur->children = NULL;
|
||||||
cur->children_count = 0;
|
cur->children_count = 0;
|
||||||
|
@ -247,17 +250,17 @@ int __recurReadNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen,
|
||||||
r += nr;
|
r += nr;
|
||||||
if (!(st != NULL && st->id != NBT_TAG_END && buflen > 0)) continue;
|
if (!(st != NULL && st->id != NBT_TAG_END && buflen > 0)) continue;
|
||||||
if (cur->children == NULL) {
|
if (cur->children == NULL) {
|
||||||
cur->children = malloc(sizeof(struct nbt_tag*));
|
cur->children = xmalloc(sizeof(struct nbt_tag*));
|
||||||
cur->children_count = 0;
|
cur->children_count = 0;
|
||||||
} else {
|
} else {
|
||||||
cur->children = realloc(cur->children, sizeof(struct nbt_tag*) * (cur->children_count + 1));
|
cur->children = xrealloc(cur->children, sizeof(struct nbt_tag*) * (cur->children_count + 1));
|
||||||
}
|
}
|
||||||
cur->children[cur->children_count++] = st;
|
cur->children[cur->children_count++] = st;
|
||||||
} while (st != NULL && st->id != NBT_TAG_END && buflen > 0);
|
} while (st != NULL && st->id != NBT_TAG_END && buflen > 0);
|
||||||
} else if (cur->id == NBT_TAG_INTARRAY) {
|
} else if (cur->id == NBT_TAG_INTARRAY) {
|
||||||
if (buflen < 4) {
|
if (buflen < 4) {
|
||||||
free(cur->name);
|
xfree(cur->name);
|
||||||
free(cur);
|
xfree(cur);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(&cur->data.nbt_intarray.count, buffer, 4);
|
memcpy(&cur->data.nbt_intarray.count, buffer, 4);
|
||||||
|
@ -266,11 +269,11 @@ int __recurReadNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen,
|
||||||
buflen -= 4;
|
buflen -= 4;
|
||||||
r += 4;
|
r += 4;
|
||||||
if (buflen < (cur->data.nbt_intarray.count * 4) || cur->data.nbt_intarray.count <= 0) {
|
if (buflen < (cur->data.nbt_intarray.count * 4) || cur->data.nbt_intarray.count <= 0) {
|
||||||
free(cur->name);
|
xfree(cur->name);
|
||||||
free(cur);
|
xfree(cur);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cur->data.nbt_intarray.ints = malloc(cur->data.nbt_intarray.count * 4);
|
cur->data.nbt_intarray.ints = xmalloc(cur->data.nbt_intarray.count * 4);
|
||||||
memcpy(cur->data.nbt_intarray.ints, buffer, cur->data.nbt_intarray.count * 4);
|
memcpy(cur->data.nbt_intarray.ints, buffer, cur->data.nbt_intarray.count * 4);
|
||||||
buffer += cur->data.nbt_intarray.count * 4;
|
buffer += cur->data.nbt_intarray.count * 4;
|
||||||
buflen -= cur->data.nbt_intarray.count * 4;
|
buflen -= cur->data.nbt_intarray.count * 4;
|
||||||
|
@ -319,7 +322,8 @@ ssize_t decompressNBT(void* data, size_t size, void** dest) {
|
||||||
|
|
||||||
int readNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen) {
|
int readNBT(struct nbt_tag** root, unsigned char* buffer, size_t buflen) {
|
||||||
if (buflen == 0) return 0;
|
if (buflen == 0) return 0;
|
||||||
return __recurReadNBT(root, buffer, buflen, 0);
|
int x = __recurReadNBT(root, buffer, buflen, 0);
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen, int list) {
|
int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen, int list) {
|
||||||
|
@ -335,6 +339,7 @@ int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen,
|
||||||
if (root->id > 0) {
|
if (root->id > 0) {
|
||||||
int16_t sl = strlen(root->name);
|
int16_t sl = strlen(root->name);
|
||||||
memcpy(buffer, &sl, 2);
|
memcpy(buffer, &sl, 2);
|
||||||
|
swapEndian(buffer, 2);
|
||||||
r += 2;
|
r += 2;
|
||||||
buffer += 2;
|
buffer += 2;
|
||||||
buflen -= 2;
|
buflen -= 2;
|
||||||
|
@ -354,30 +359,35 @@ int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen,
|
||||||
} else if (root->id == NBT_TAG_SHORT) {
|
} else if (root->id == NBT_TAG_SHORT) {
|
||||||
if (buflen < 2) return 0;
|
if (buflen < 2) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_short, 2);
|
memcpy(buffer, &root->data.nbt_short, 2);
|
||||||
|
swapEndian(buffer, 2);
|
||||||
r += 2;
|
r += 2;
|
||||||
buffer += 2;
|
buffer += 2;
|
||||||
buflen -= 2;
|
buflen -= 2;
|
||||||
} else if (root->id == NBT_TAG_INT) {
|
} else if (root->id == NBT_TAG_INT) {
|
||||||
if (buflen < 4) return 0;
|
if (buflen < 4) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_int, 4);
|
memcpy(buffer, &root->data.nbt_int, 4);
|
||||||
|
swapEndian(buffer, 4);
|
||||||
r += 4;
|
r += 4;
|
||||||
buffer += 4;
|
buffer += 4;
|
||||||
buflen -= 4;
|
buflen -= 4;
|
||||||
} else if (root->id == NBT_TAG_LONG) {
|
} else if (root->id == NBT_TAG_LONG) {
|
||||||
if (buflen < 8) return 0;
|
if (buflen < 8) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_short, 8);
|
memcpy(buffer, &root->data.nbt_short, 8);
|
||||||
|
swapEndian(buffer, 8);
|
||||||
r += 8;
|
r += 8;
|
||||||
buffer += 8;
|
buffer += 8;
|
||||||
buflen -= 8;
|
buflen -= 8;
|
||||||
} else if (root->id == NBT_TAG_FLOAT) {
|
} else if (root->id == NBT_TAG_FLOAT) {
|
||||||
if (buflen < 4) return 0;
|
if (buflen < 4) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_float, 4);
|
memcpy(buffer, &root->data.nbt_float, 4);
|
||||||
|
swapEndian(buffer, 4);
|
||||||
r += 4;
|
r += 4;
|
||||||
buffer += 4;
|
buffer += 4;
|
||||||
buflen -= 4;
|
buflen -= 4;
|
||||||
} else if (root->id == NBT_TAG_DOUBLE) {
|
} else if (root->id == NBT_TAG_DOUBLE) {
|
||||||
if (buflen < 8) return 0;
|
if (buflen < 8) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_double, 8);
|
memcpy(buffer, &root->data.nbt_double, 8);
|
||||||
|
swapEndian(buffer, 8);
|
||||||
r += 8;
|
r += 8;
|
||||||
buffer += 8;
|
buffer += 8;
|
||||||
buflen -= 8;
|
buflen -= 8;
|
||||||
|
@ -396,6 +406,7 @@ int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen,
|
||||||
if (buflen < 2) return 0;
|
if (buflen < 2) return 0;
|
||||||
uint16_t sl = strlen(root->data.nbt_string);
|
uint16_t sl = strlen(root->data.nbt_string);
|
||||||
memcpy(buffer, &sl, 2);
|
memcpy(buffer, &sl, 2);
|
||||||
|
swapEndian(buffer, 2);
|
||||||
r += 2;
|
r += 2;
|
||||||
buffer += 2;
|
buffer += 2;
|
||||||
buflen -= 2;
|
buflen -= 2;
|
||||||
|
@ -408,6 +419,7 @@ int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen,
|
||||||
if (buflen < 5) return 0;
|
if (buflen < 5) return 0;
|
||||||
buffer[0] = root->data.nbt_list.type;
|
buffer[0] = root->data.nbt_list.type;
|
||||||
memcpy(buffer, &root->data.nbt_list.count, 4);
|
memcpy(buffer, &root->data.nbt_list.count, 4);
|
||||||
|
swapEndian(buffer, 4);
|
||||||
r += 5;
|
r += 5;
|
||||||
buffer += 5;
|
buffer += 5;
|
||||||
buflen -= 5;
|
buflen -= 5;
|
||||||
|
@ -420,15 +432,21 @@ int __recurWriteNBT(struct nbt_tag* root, unsigned char* buffer, size_t buflen,
|
||||||
}
|
}
|
||||||
} else if (root->id == NBT_TAG_COMPOUND) {
|
} else if (root->id == NBT_TAG_COMPOUND) {
|
||||||
for (size_t i = 0; i < root->children_count; i++) {
|
for (size_t i = 0; i < root->children_count; i++) {
|
||||||
int x = __recurWriteNBT(root->children[i], buffer, buflen, 1);
|
int x = __recurWriteNBT(root->children[i], buffer, buflen, 0);
|
||||||
r += x;
|
r += x;
|
||||||
buffer += x;
|
buffer += x;
|
||||||
buflen -= x;
|
buflen -= x;
|
||||||
if (buflen <= 0 || root->children[i]->id == NBT_TAG_END) break;
|
if (buflen <= 0) break;
|
||||||
}
|
}
|
||||||
|
if (buflen <= 1) return 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
buffer++;
|
||||||
|
buflen--;
|
||||||
|
r++;
|
||||||
} else if (root->id == NBT_TAG_INTARRAY) {
|
} else if (root->id == NBT_TAG_INTARRAY) {
|
||||||
if (buflen < 4) return 0;
|
if (buflen < 4) return 0;
|
||||||
memcpy(buffer, &root->data.nbt_intarray.count, 4);
|
memcpy(buffer, &root->data.nbt_intarray.count, 4);
|
||||||
|
swapEndian(buffer, 4);
|
||||||
r += 4;
|
r += 4;
|
||||||
buffer += 4;
|
buffer += 4;
|
||||||
buflen -= 4;
|
buflen -= 4;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "accept.h"
|
#include "accept.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
void swapEndian(void* dou, size_t ss) {
|
void swapEndian(void* dou, size_t ss) {
|
||||||
uint8_t* pxs = (uint8_t*) dou;
|
uint8_t* pxs = (uint8_t*) dou;
|
||||||
|
@ -212,6 +213,50 @@ int readSlot(struct slot* slot, unsigned char* buffer, size_t buflen) {
|
||||||
return 5 + readNBT(&slot->nbt, buffer, buflen);
|
return 5 + readNBT(&slot->nbt, buffer, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void duplicateSlot(struct slot* slot, struct slot* dup) {
|
||||||
|
if (slot == NULL) {
|
||||||
|
memset(dup, 0, sizeof(struct slot));
|
||||||
|
dup->item = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dup->item = slot->item;
|
||||||
|
dup->damage = slot->damage;
|
||||||
|
dup->itemCount = slot->itemCount;
|
||||||
|
dup->nbt = xmalloc(sizeof(struct nbt_tag));
|
||||||
|
duplicateNBT(slot->nbt, dup->nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void duplicateNBT(struct nbt_tag* nbt, struct nbt_tag* dup) {
|
||||||
|
if (nbt == NULL) {
|
||||||
|
memset(dup, 0, sizeof(struct nbt_tag));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dup->name = nbt->name == NULL ? NULL : xstrdup(nbt->name, 0);
|
||||||
|
dup->id = nbt->id;
|
||||||
|
dup->children_count = nbt->children_count;
|
||||||
|
if (dup->id == NBT_TAG_BYTE || dup->id == NBT_TAG_SHORT || dup->id == NBT_TAG_INT || dup->id == NBT_TAG_LONG || dup->id == NBT_TAG_FLOAT || dup->id == NBT_TAG_DOUBLE) {
|
||||||
|
memcpy(&dup->data, &nbt->data, sizeof(union nbt_data));
|
||||||
|
} else if (dup->id == NBT_TAG_BYTEARRAY) {
|
||||||
|
dup->data.nbt_bytearray.len = nbt->data.nbt_bytearray.len;
|
||||||
|
dup->data.nbt_bytearray.data = xmalloc(dup->data.nbt_bytearray.len);
|
||||||
|
memcpy(dup->data.nbt_bytearray.data, nbt->data.nbt_bytearray.data, dup->data.nbt_bytearray.len);
|
||||||
|
} else if (dup->id == NBT_TAG_STRING) {
|
||||||
|
dup->data.nbt_string = xstrdup(nbt->data.nbt_string, 0);
|
||||||
|
} else if (dup->id == NBT_TAG_LIST) {
|
||||||
|
dup->data.nbt_list.type = nbt->data.nbt_list.type;
|
||||||
|
dup->data.nbt_list.count = nbt->data.nbt_list.count;
|
||||||
|
} else if (dup->id == NBT_TAG_INTARRAY) {
|
||||||
|
dup->data.nbt_intarray.count = nbt->data.nbt_intarray.count;
|
||||||
|
dup->data.nbt_intarray.ints = xmalloc(4 * dup->data.nbt_intarray.count);
|
||||||
|
memcpy(dup->data.nbt_intarray.ints, nbt->data.nbt_intarray.ints, dup->data.nbt_bytearray.len);
|
||||||
|
}
|
||||||
|
dup->children = xmalloc(sizeof(struct nbt_tag*) * dup->children_count);
|
||||||
|
for (size_t i = 0; i < dup->children_count; i++) {
|
||||||
|
dup->children[i] = xmalloc(sizeof(struct nbt_tag));
|
||||||
|
duplicateNBT(nbt->children[i], dup->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int writeSlot(struct slot* slot, unsigned char* buffer, size_t buflen) {
|
int writeSlot(struct slot* slot, unsigned char* buffer, size_t buflen) {
|
||||||
if (buflen < 2) return -1;
|
if (buflen < 2) return -1;
|
||||||
memcpy(buffer, &slot->item, 2);
|
memcpy(buffer, &slot->item, 2);
|
||||||
|
|
|
@ -40,11 +40,6 @@ struct entity_metadata {
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
|
||||||
#define STATE_HANDSHAKE 0
|
|
||||||
#define STATE_STATUS 1
|
|
||||||
#define STATE_LOGIN 2
|
|
||||||
#define STATE_PLAY 3
|
|
||||||
|
|
||||||
void swapEndian(void* dou, size_t ss);
|
void swapEndian(void* dou, size_t ss);
|
||||||
|
|
||||||
int getVarIntSize(int32_t input);
|
int getVarIntSize(int32_t input);
|
||||||
|
@ -65,6 +60,12 @@ int readString(char** output, unsigned char* buffer, size_t buflen);
|
||||||
|
|
||||||
int readSlot(struct slot* slot, unsigned char* buffer, size_t buflen);
|
int readSlot(struct slot* slot, unsigned char* buffer, size_t buflen);
|
||||||
|
|
||||||
|
int writeSlot(struct slot* slot, unsigned char* buffer, size_t buflen);
|
||||||
|
|
||||||
|
void duplicateSlot(struct slot* slot, struct slot* dup);
|
||||||
|
|
||||||
|
void duplicateNBT(struct nbt_tag* nbt, struct nbt_tag* dup);
|
||||||
|
|
||||||
ssize_t readPacket(struct conn* conn, unsigned char* buf, size_t buflen, struct packet* packet);
|
ssize_t readPacket(struct conn* conn, unsigned char* buf, size_t buflen, struct packet* packet);
|
||||||
|
|
||||||
ssize_t writePacket(struct conn* conn, struct packet* packet);
|
ssize_t writePacket(struct conn* conn, struct packet* packet);
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
#include "nbt.h"
|
#include "nbt.h"
|
||||||
|
|
||||||
#define STATE_HANDSHAKE 0
|
#define STATE_HANDSHAKE 0
|
||||||
#define STATE_PLAY 1
|
#define STATE_PLAY 3
|
||||||
#define STATE_STATUS 2
|
#define STATE_STATUS 1
|
||||||
#define STATE_LOGIN 3
|
#define STATE_LOGIN 2
|
||||||
|
|
||||||
#define PKT_HANDSHAKE_SERVER_HANDSHAKE 0
|
#define PKT_HANDSHAKE_SERVER_HANDSHAKE 0
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "accept.h"
|
#include "accept.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "xstring.h"
|
||||||
|
|
||||||
struct player* newPlayer(struct entity* entity, char* name, struct uuid uuid, struct conn* conn, uint8_t gamemode) {
|
struct player* newPlayer(struct entity* entity, char* name, struct uuid uuid, struct conn* conn, uint8_t gamemode) {
|
||||||
struct player* player = xmalloc(sizeof(struct player));
|
struct player* player = xmalloc(sizeof(struct player));
|
||||||
|
@ -44,10 +46,15 @@ struct player* newPlayer(struct entity* entity, char* name, struct uuid uuid, st
|
||||||
memset(&player->digging_position, 0, sizeof(struct encpos));
|
memset(&player->digging_position, 0, sizeof(struct encpos));
|
||||||
player->digging = -1.;
|
player->digging = -1.;
|
||||||
player->digspeed = 0.;
|
player->digspeed = 0.;
|
||||||
|
newInventory(&player->inventory, INVTYPE_PLAYERINVENTORY, 0, 46);
|
||||||
|
player->inventory.player = player;
|
||||||
|
player->loadedChunks = new_collection(0);
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freePlayer(struct player* player) {
|
void freePlayer(struct player* player) {
|
||||||
|
del_collection(player->loadedChunks);
|
||||||
|
freeInventory(&player->inventory);
|
||||||
xfree(player->name);
|
xfree(player->name);
|
||||||
xfree(player);
|
xfree(player);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ struct player {
|
||||||
struct encpos digging_position;
|
struct encpos digging_position;
|
||||||
float digging;
|
float digging;
|
||||||
float digspeed;
|
float digspeed;
|
||||||
|
struct inventory inventory;
|
||||||
|
struct collection* loadedChunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct player* newPlayer(struct entity* entity, char* name, struct uuid, struct conn* conn, uint8_t gamemode);
|
struct player* newPlayer(struct entity* entity, char* name, struct uuid, struct conn* conn, uint8_t gamemode);
|
||||||
|
|
|
@ -71,10 +71,12 @@ int add_queue(struct queue* queue, void* data) {
|
||||||
memcpy(ndata, queue->data + queue->start, (queue->end - queue->start) * sizeof(void*));
|
memcpy(ndata, queue->data + queue->start, (queue->end - queue->start) * sizeof(void*));
|
||||||
} else {
|
} else {
|
||||||
memcpy(ndata, queue->data + queue->start, (orc - queue->start) * sizeof(void*));
|
memcpy(ndata, queue->data + queue->start, (orc - queue->start) * sizeof(void*));
|
||||||
memcpy(ndata + (orc - queue->start), queue->data + queue->end, (queue->start - queue->end) * sizeof(void*));
|
memcpy(ndata + (orc - queue->start), queue->data, (queue->end) * sizeof(void*));
|
||||||
}
|
}
|
||||||
xfree(queue->data);
|
xfree(queue->data);
|
||||||
queue->data = ndata;
|
queue->data = ndata;
|
||||||
|
queue->start = 0;
|
||||||
|
queue->end = orc;
|
||||||
} else if (queue->capacity == 0) {
|
} else if (queue->capacity == 0) {
|
||||||
} else {
|
} else {
|
||||||
while (queue->size == queue->capacity) {
|
while (queue->size == queue->capacity) {
|
||||||
|
@ -93,10 +95,12 @@ int add_queue(struct queue* queue, void* data) {
|
||||||
memcpy(ndata, queue->data + queue->start, (queue->end - queue->start) * sizeof(void*));
|
memcpy(ndata, queue->data + queue->start, (queue->end - queue->start) * sizeof(void*));
|
||||||
} else {
|
} else {
|
||||||
memcpy(ndata, queue->data + queue->start, (orc - queue->start) * sizeof(void*));
|
memcpy(ndata, queue->data + queue->start, (orc - queue->start) * sizeof(void*));
|
||||||
memcpy(ndata + (orc - queue->start), queue->data + queue->end, (queue->start - queue->end) * sizeof(void*));
|
memcpy(ndata + (orc - queue->start), queue->data, (queue->end) * sizeof(void*));
|
||||||
}
|
}
|
||||||
xfree(queue->data);
|
xfree(queue->data);
|
||||||
queue->data = ndata;
|
queue->data = ndata;
|
||||||
|
queue->start = 0;
|
||||||
|
queue->end = orc;
|
||||||
} else queue->end -= rp;
|
} else queue->end -= rp;
|
||||||
}
|
}
|
||||||
queue->size++;
|
queue->size++;
|
||||||
|
@ -133,8 +137,8 @@ void* pop_nowait_queue(struct queue* queue) {
|
||||||
if (queue->mt) {
|
if (queue->mt) {
|
||||||
pthread_mutex_lock(&queue->data_mutex);
|
pthread_mutex_lock(&queue->data_mutex);
|
||||||
}
|
}
|
||||||
if (queue->size == 0) {
|
if (queue->size <= 0) {
|
||||||
pthread_mutex_unlock(&queue->data_mutex);
|
if (queue->mt) pthread_mutex_unlock(&queue->data_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
void* data = queue->data[queue->start++];
|
void* data = queue->data[queue->start++];
|
||||||
|
|
|
@ -54,12 +54,12 @@ void closeConn(struct work_param* param, struct conn* conn) {
|
||||||
}
|
}
|
||||||
despawnPlayer(conn->player->world, conn->player);
|
despawnPlayer(conn->player->world, conn->player);
|
||||||
freeEntity(conn->player->entity);
|
freeEntity(conn->player->entity);
|
||||||
|
freePlayer(conn->player);
|
||||||
}
|
}
|
||||||
if (conn->host_ip != NULL) xfree(conn->host_ip);
|
if (conn->host_ip != NULL) xfree(conn->host_ip);
|
||||||
if (conn->readBuffer != NULL) xfree(conn->readBuffer);
|
if (conn->readBuffer != NULL) xfree(conn->readBuffer);
|
||||||
if (conn->writeBuffer != NULL) xfree(conn->writeBuffer);
|
if (conn->writeBuffer != NULL) xfree(conn->writeBuffer);
|
||||||
xfree(conn);
|
xfree(conn);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
|
@ -91,7 +91,7 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
rep.id = PKT_STATUS_CLIENT_RESPONSE;
|
rep.id = PKT_STATUS_CLIENT_RESPONSE;
|
||||||
rep.data.status_client.response.json_response = xmalloc(1000);
|
rep.data.status_client.response.json_response = xmalloc(1000);
|
||||||
rep.data.status_client.response.json_response[999] = 0;
|
rep.data.status_client.response.json_response[999] = 0;
|
||||||
snprintf(rep.data.status_client.response.json_response, 999, "{\"version\":{\"name\":\"1.11.2\",\"protocol\":%i},\"players\":{\"max\":%i,\"online\":%i},\"description\":{\"text\":\"%s\"}}", MC_PROTOCOL_VERSION, max_players, 0, motd);
|
snprintf(rep.data.status_client.response.json_response, 999, "{\"version\":{\"name\":\"1.11\",\"protocol\":%i},\"players\":{\"max\":%i,\"online\":%i},\"description\":{\"text\":\"%s\"}}", MC_PROTOCOL_VERSION, max_players, 0, motd);
|
||||||
if (writePacket(conn, &rep) < 0) goto rete;
|
if (writePacket(conn, &rep) < 0) goto rete;
|
||||||
xfree(rep.data.status_client.response.json_response);
|
xfree(rep.data.status_client.response.json_response);
|
||||||
} else if (inp->id == PKT_STATUS_SERVER_PING) {
|
} else if (inp->id == PKT_STATUS_SERVER_PING) {
|
||||||
|
@ -124,7 +124,7 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
xfree(rep.data.login_client.loginsuccess.uuid);
|
xfree(rep.data.login_client.loginsuccess.uuid);
|
||||||
conn->state = STATE_PLAY;
|
conn->state = STATE_PLAY;
|
||||||
struct entity* ep = newEntity(nextEntityID++, (float) overworld->spawnpos.x + .5, (float) overworld->spawnpos.y, (float) overworld->spawnpos.z + .5, ENT_PLAYER, 0., 0.);
|
struct entity* ep = newEntity(nextEntityID++, (float) overworld->spawnpos.x + .5, (float) overworld->spawnpos.y, (float) overworld->spawnpos.z + .5, ENT_PLAYER, 0., 0.);
|
||||||
struct player* player = newPlayer(ep, xstrdup(inp->data.login_client.loginsuccess.username, 0), uuid, conn, 0); // TODO default gamemode
|
struct player* player = newPlayer(ep, xstrdup(rep.data.login_client.loginsuccess.username, 0), uuid, conn, 1); // TODO default gamemode
|
||||||
conn->player = player;
|
conn->player = player;
|
||||||
add_collection(players, player);
|
add_collection(players, player);
|
||||||
rep.id = PKT_PLAY_CLIENT_JOINGAME;
|
rep.id = PKT_PLAY_CLIENT_JOINGAME;
|
||||||
|
@ -151,7 +151,7 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
memcpy(&rep.data.play_client.spawnposition.location, &overworld->spawnpos, sizeof(struct encpos));
|
memcpy(&rep.data.play_client.spawnposition.location, &overworld->spawnpos, sizeof(struct encpos));
|
||||||
if (writePacket(conn, &rep) < 0) goto rete;
|
if (writePacket(conn, &rep) < 0) goto rete;
|
||||||
rep.id = PKT_PLAY_CLIENT_PLAYERABILITIES;
|
rep.id = PKT_PLAY_CLIENT_PLAYERABILITIES;
|
||||||
rep.data.play_client.playerabilities.flags = 0x4; // TODO: allows flying, remove
|
rep.data.play_client.playerabilities.flags = 0x4 | 0x8; // TODO: allows flying, remove
|
||||||
rep.data.play_client.playerabilities.flying_speed = 0.05;
|
rep.data.play_client.playerabilities.flying_speed = 0.05;
|
||||||
rep.data.play_client.playerabilities.field_of_view_modifier = .1;
|
rep.data.play_client.playerabilities.field_of_view_modifier = .1;
|
||||||
if (writePacket(conn, &rep) < 0) goto rete;
|
if (writePacket(conn, &rep) < 0) goto rete;
|
||||||
|
@ -208,37 +208,15 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
if (ent == NULL || entity_distsq(ent, player->entity) > 16384.) continue;
|
if (ent == NULL || entity_distsq(ent, player->entity) > 16384.) continue;
|
||||||
if (ent->type == ENT_PLAYER) {
|
if (ent->type == ENT_PLAYER) {
|
||||||
if (ent->data.player.player != player) {
|
if (ent->data.player.player != player) {
|
||||||
rep.id = PKT_PLAY_CLIENT_SPAWNPLAYER;
|
loadPlayer(player, ent->data.player.player);
|
||||||
rep.data.play_client.spawnplayer.entity_id = ent->id;
|
loadPlayer(ent->data.player.player, player);
|
||||||
memcpy(&rep.data.play_client.spawnplayer.player_uuid, &ent->data.player.player->uuid, sizeof(struct uuid));
|
|
||||||
rep.data.play_client.spawnplayer.x = ent->x;
|
|
||||||
rep.data.play_client.spawnplayer.y = ent->y;
|
|
||||||
rep.data.play_client.spawnplayer.z = ent->z;
|
|
||||||
rep.data.play_client.spawnplayer.yaw = (ent->yaw / 360.) * 256.;
|
|
||||||
rep.data.play_client.spawnplayer.pitch = (ent->pitch / 360.) * 256.;
|
|
||||||
rep.data.play_client.spawnplayer.metadata.metadata = NULL;
|
|
||||||
rep.data.play_client.spawnplayer.metadata.metadata_size = 0;
|
|
||||||
writeMetadata(ent, &rep.data.play_client.spawnplayer.metadata.metadata, &rep.data.play_client.spawnplayer.metadata.metadata_size);
|
|
||||||
if (writePacket(conn, &rep) < 0) goto rete;
|
|
||||||
struct packet* pkt = xmalloc(sizeof(struct packet));
|
|
||||||
pkt->id = PKT_PLAY_CLIENT_SPAWNPLAYER;
|
|
||||||
pkt->data.play_client.spawnplayer.entity_id = player->entity->id;
|
|
||||||
memcpy(&pkt->data.play_client.spawnplayer.player_uuid, &player->entity->data.player.player->uuid, sizeof(struct uuid));
|
|
||||||
pkt->data.play_client.spawnplayer.x = player->entity->x;
|
|
||||||
pkt->data.play_client.spawnplayer.y = player->entity->y;
|
|
||||||
pkt->data.play_client.spawnplayer.z = player->entity->z;
|
|
||||||
pkt->data.play_client.spawnplayer.yaw = (player->entity->yaw / 360.) * 256.;
|
|
||||||
pkt->data.play_client.spawnplayer.pitch = (player->entity->pitch / 360.) * 256.;
|
|
||||||
writeMetadata(player->entity, &pkt->data.play_client.spawnplayer.metadata.metadata, &pkt->data.play_client.spawnplayer.metadata.metadata_size);
|
|
||||||
add_queue(ent->data.player.player->conn->outgoingPacket, pkt);
|
|
||||||
flush_outgoing(ent->data.player.player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char bct[256];
|
char bct[256];
|
||||||
snprintf(bct, 256, "%s has joined the server!", player->name);
|
snprintf(bct, 256, "%s has joined the server!", player->name);
|
||||||
broadcast(bct);
|
broadcast(bct);
|
||||||
for (int x = -9; x < 10; x++) {
|
/*for (int x = -9; x < 10; x++) {
|
||||||
for (int z = -9; z < 10; z++) {
|
for (int z = -9; z < 10; z++) {
|
||||||
struct chunk* ch = getChunk(overworld, x + (int32_t) ep->x / 16, z + (int32_t) ep->z / 16);
|
struct chunk* ch = getChunk(overworld, x + (int32_t) ep->x / 16, z + (int32_t) ep->z / 16);
|
||||||
if (ch != NULL) {
|
if (ch != NULL) {
|
||||||
|
@ -252,13 +230,13 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
flush_outgoing(player);
|
flush_outgoing(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (conn->state == STATE_PLAY) {
|
} else if (conn->state == STATE_PLAY) {
|
||||||
if (inp->id == PKT_PLAY_SERVER_KEEPALIVE) {
|
if (inp->id == PKT_PLAY_SERVER_KEEPALIVE) {
|
||||||
if (rep.data.play_client.keepalive.keep_alive_id == conn->player->nextKeepAlive) {
|
if (inp->data.play_server.keepalive.keep_alive_id == conn->player->nextKeepAlive) {
|
||||||
conn->player->nextKeepAlive = 0;
|
conn->player->nextKeepAlive = 0;
|
||||||
}
|
}
|
||||||
} else if (inp->id == PKT_PLAY_SERVER_CHATMESSAGE) {
|
} else if (inp->id == PKT_PLAY_SERVER_CHATMESSAGE) {
|
||||||
|
@ -305,7 +283,7 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
} else if (inp->id == PKT_PLAY_SERVER_PLAYERDIGGING) {
|
} else if (inp->id == PKT_PLAY_SERVER_PLAYERDIGGING) {
|
||||||
if (inp->data.play_server.playerdigging.status == 0) {
|
if (inp->data.play_server.playerdigging.status == 0) {
|
||||||
float hard = block_infos[getBlockWorld(conn->player->world, inp->data.play_server.playerdigging.location.x, inp->data.play_server.playerdigging.location.y, inp->data.play_server.playerdigging.location.z)].hardness;
|
float hard = block_infos[getBlockWorld(conn->player->world, inp->data.play_server.playerdigging.location.x, inp->data.play_server.playerdigging.location.y, inp->data.play_server.playerdigging.location.z)].hardness;
|
||||||
if (hard > 0.) {
|
if (hard > 0. && conn->player->gamemode == 0) {
|
||||||
conn->player->digging = 0.;
|
conn->player->digging = 0.;
|
||||||
memcpy(&conn->player->digging_position, &inp->data.play_server.playerdigging.location, sizeof(struct encpos));
|
memcpy(&conn->player->digging_position, &inp->data.play_server.playerdigging.location, sizeof(struct encpos));
|
||||||
BEGIN_BROADCAST_EXCEPT_DIST(conn->player, conn->player->entity, 128.)
|
BEGIN_BROADCAST_EXCEPT_DIST(conn->player, conn->player->entity, 128.)
|
||||||
|
@ -317,7 +295,7 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
add_queue(bc_player->conn->outgoingPacket, pkt);
|
add_queue(bc_player->conn->outgoingPacket, pkt);
|
||||||
flush_outgoing (bc_player);
|
flush_outgoing (bc_player);
|
||||||
END_BROADCAST
|
END_BROADCAST
|
||||||
} else if (hard == 0.) {
|
} else if (hard == 0. || conn->player->gamemode == 1) {
|
||||||
setBlockWorld(conn->player->world, 0, inp->data.play_server.playerdigging.location.x, inp->data.play_server.playerdigging.location.y, inp->data.play_server.playerdigging.location.z);
|
setBlockWorld(conn->player->world, 0, inp->data.play_server.playerdigging.location.x, inp->data.play_server.playerdigging.location.y, inp->data.play_server.playerdigging.location.z);
|
||||||
conn->player->digging = -1.;
|
conn->player->digging = -1.;
|
||||||
memset(&conn->player->digging_position, 0, sizeof(struct encpos));
|
memset(&conn->player->digging_position, 0, sizeof(struct encpos));
|
||||||
|
@ -338,6 +316,32 @@ int handleRead(struct conn* conn, struct work_param* param, int fd) {
|
||||||
flush_outgoing (bc_player);
|
flush_outgoing (bc_player);
|
||||||
END_BROADCAST
|
END_BROADCAST
|
||||||
}
|
}
|
||||||
|
} else if (inp->id == PKT_PLAY_SERVER_CREATIVEINVENTORYACTION) {
|
||||||
|
if (inp->data.play_server.creativeinventoryaction.clicked_item.item >= 0 && inp->data.play_server.creativeinventoryaction.slot == -1) {
|
||||||
|
//drop item
|
||||||
|
} else {
|
||||||
|
int16_t sl = inp->data.play_server.creativeinventoryaction.slot;
|
||||||
|
setInventorySlot(&conn->player->inventory, &inp->data.play_server.creativeinventoryaction.clicked_item, sl);
|
||||||
|
onInventoryUpdate(&conn->player->inventory, sl);
|
||||||
|
}
|
||||||
|
} else if (inp->id == PKT_PLAY_SERVER_HELDITEMCHANGE) {
|
||||||
|
if (inp->data.play_server.helditemchange.slot >= 0 && inp->data.play_server.helditemchange.slot < 9) {
|
||||||
|
conn->player->currentItem = inp->data.play_server.helditemchange.slot;
|
||||||
|
onInventoryUpdate(&conn->player->inventory, conn->player->currentItem + 36);
|
||||||
|
}
|
||||||
|
} else if (inp->id == PKT_PLAY_SERVER_ENTITYACTION) {
|
||||||
|
if (inp->data.play_server.entityaction.action_id == 0) conn->player->entity->sneaking = 1;
|
||||||
|
else if (inp->data.play_server.entityaction.action_id == 1) conn->player->entity->sneaking = 0;
|
||||||
|
else if (inp->data.play_server.entityaction.action_id == 3) conn->player->entity->sprinting = 1;
|
||||||
|
else if (inp->data.play_server.entityaction.action_id == 4) conn->player->entity->sprinting = 0;
|
||||||
|
BEGIN_BROADCAST_EXCEPT_DIST(conn->player, conn->player->entity, 128.)
|
||||||
|
struct packet* pkt = xmalloc(sizeof(struct packet));
|
||||||
|
pkt->id = PKT_PLAY_CLIENT_ENTITYMETADATA;
|
||||||
|
pkt->data.play_client.entitymetadata.entity_id = conn->player->entity->id;
|
||||||
|
writeMetadata(conn->player->entity, &pkt->data.play_client.entitymetadata.metadata.metadata, &pkt->data.play_client.entitymetadata.metadata.metadata_size);
|
||||||
|
add_queue(bc_player->conn->outgoingPacket, pkt);
|
||||||
|
flush_outgoing (bc_player);
|
||||||
|
END_BROADCAST
|
||||||
}
|
}
|
||||||
//printf("recv: %i\n", inp->id);
|
//printf("recv: %i\n", inp->id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,22 @@ struct chunk* getChunk(struct world* world, int16_t x, int16_t z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void unloadChunk(struct world* world, struct chunk* chunk) {
|
void unloadChunk(struct world* world, struct chunk* chunk) {
|
||||||
chunk->unload = 1;
|
//TODO: save chunk
|
||||||
|
int16_t rx = chunk->x >> 5;
|
||||||
|
int16_t rz = chunk->z >> 5;
|
||||||
|
pthread_rwlock_rdlock(&world->regions->data_mutex);
|
||||||
|
for (size_t i = 0; i < world->regions->size; i++) {
|
||||||
|
if (world->regions->data[i] != NULL && ((struct region*) world->regions->data[i])->x == rx && ((struct region*) world->regions->data[i])->z == rz) {
|
||||||
|
struct region* r = ((struct region*) world->regions->data[i]);
|
||||||
|
r->loaded[chunk->z & 0x1F][chunk->x & 0x1F] = 0;
|
||||||
|
r->chunks[chunk->z & 0x1F][chunk->x & 0x1F] = 0;
|
||||||
|
freeChunk(chunk);
|
||||||
|
pthread_rwlock_unlock(&world->regions->data_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_rwlock_unlock(&world->regions->data_mutex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBiome(struct world* world, int32_t x, int32_t z) {
|
int getBiome(struct world* world, int32_t x, int32_t z) {
|
||||||
|
@ -240,12 +255,19 @@ struct chunk* newChunk(int16_t x, int16_t z) {
|
||||||
chunk->z = z;
|
chunk->z = z;
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
chunk->empty[i] = 1;
|
chunk->empty[i] = 1;
|
||||||
chunk->unload = 0;
|
chunk->playersLoaded = 0;
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeChunk(struct chunk* chunk) {
|
void freeChunk(struct chunk* chunk) {
|
||||||
if (chunk->skyLight != NULL) xfree(chunk->skyLight);
|
if (chunk->skyLight != NULL) xfree(chunk->skyLight);
|
||||||
|
if (chunk->tileEntities != NULL) {
|
||||||
|
for (size_t i = 0; i < chunk->tileEntity_count; i++) {
|
||||||
|
freeNBT(chunk->tileEntities[i]);
|
||||||
|
xfree(chunk->tileEntities[i]);
|
||||||
|
}
|
||||||
|
xfree(chunk->tileEntities);
|
||||||
|
}
|
||||||
xfree(chunk);
|
xfree(chunk);
|
||||||
}
|
}
|
||||||
struct region* newRegion(char* path, int16_t x, int16_t z) {
|
struct region* newRegion(char* path, int16_t x, int16_t z) {
|
||||||
|
|
|
@ -35,12 +35,13 @@ struct chunk {
|
||||||
unsigned char blockLight[256][16][8]; // y, z, x(4-bit)
|
unsigned char blockLight[256][16][8]; // y, z, x(4-bit)
|
||||||
unsigned char* skyLight; // if non-NULL, points to a 2048-byte nibble-array.
|
unsigned char* skyLight; // if non-NULL, points to a 2048-byte nibble-array.
|
||||||
int empty[16];
|
int empty[16];
|
||||||
int unload;
|
|
||||||
int lightpopulated;
|
int lightpopulated;
|
||||||
int terrainpopulated;
|
int terrainpopulated;
|
||||||
uint64_t inhabitedticks;
|
uint64_t inhabitedticks;
|
||||||
uint16_t heightMap[16][16]; // z, x
|
uint16_t heightMap[16][16]; // z, x
|
||||||
struct nbt** tileEntities;
|
size_t tileEntity_count;
|
||||||
|
struct nbt_tag** tileEntities;
|
||||||
|
uint32_t playersLoaded;
|
||||||
//TODO: tileTicks
|
//TODO: tileTicks
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue