From 7008a54132d3858dbb470ea9d00da649306a8665 Mon Sep 17 00:00:00 2001 From: Protryon Date: Sat, 4 May 2019 17:15:00 -0700 Subject: [PATCH] player refactoring --- include/basin/game.h | 2 +- include/basin/network.h | 2 +- include/basin/player.h | 11 +- include/basin/world.h | 4 + src/command.c | 29 +-- src/game.c | 5 +- src/main.c | 1 - src/player.c | 388 ++++++++++++++++++---------------------- src/player_packet.c | 6 +- src/world.c | 11 +- 10 files changed, 207 insertions(+), 252 deletions(-) diff --git a/include/basin/game.h b/include/basin/game.h index 0976719..f75b56c 100644 --- a/include/basin/game.h +++ b/include/basin/game.h @@ -46,7 +46,7 @@ void broadcast(char* text, char* color); void broadcastf(char* color, char* fmt, ...); #define BEGIN_BROADCAST(players) pthread_rwlock_rdlock(&(players)->rwlock); ITER_MAP(players) { struct player* bc_player = (struct player*)value; { -#define BEGIN_BROADCAST_DIST(distfrom, dist) pthread_rwlock_rdlock(&(players)->rwlock); ITER_MAP(distfrom->world->players) { struct player* bc_player = (struct player*)value; if(entity_distsq(bc_player->entity, distfrom) < dist * dist) { +#define BEGIN_BROADCAST_DIST(distfrom, dist) pthread_rwlock_rdlock(&(distfrom->world->players)->rwlock); ITER_MAP(distfrom->world->players) { struct player* bc_player = (struct player*)value; if(entity_distsq(bc_player->entity, distfrom) < dist * dist) { #define BEGIN_BROADCAST_DISTXYZ(x, y, z, players, dist) pthread_rwlock_rdlock(&(players)->rwlock); ITER_MAP(players) { struct player* bc_player = (struct player*)value; if (entity_distsq_block(bc_player->entity, x, y, z) < dist * dist) { #define BEGIN_BROADCAST_EXCEPT(players, except) pthread_rwlock_rdlock(&(players)->rwlock); ITER_MAP(players) { struct player* bc_player = (struct player*)value; if (bc_player != except) { #define BEGIN_BROADCAST_EXCEPT_DIST(except, distfrom, dist) pthread_rwlock_rdlock(&(distfrom->world->players)->rwlock); ITER_MAP(distfrom->world->players) { struct player* bc_player = (struct player*)value; if (bc_player != except && entity_distsq(bc_player->entity, distfrom) < dist * dist) { diff --git a/include/basin/network.h b/include/basin/network.h index 59ed477..8f9b4af 100644 --- a/include/basin/network.h +++ b/include/basin/network.h @@ -8,10 +8,10 @@ #ifndef BASIN_NETWORK_H_ #define BASIN_NETWORK_H_ -#include #include #include +struct slot; struct packet; struct __attribute__((__packed__)) encpos { diff --git a/include/basin/player.h b/include/basin/player.h index f3613ac..3fb6bd1 100644 --- a/include/basin/player.h +++ b/include/basin/player.h @@ -11,6 +11,7 @@ #include #include #include +#include #include struct player { @@ -30,7 +31,7 @@ struct player { struct queue* incoming_packets; uint32_t next_keep_alive; uint8_t spawned_in; - uint32_t chunks_sent + uint32_t chunks_sent; uint8_t trigger_rechunk; struct inventory* inventory; @@ -50,7 +51,7 @@ struct player { int32_t xptotal; int32_t xplevel; int32_t score; - size_t last_teleport_id; + int32_t last_teleport_id; int8_t sleeping; int16_t fire; //TODO: enderitems inventory @@ -76,13 +77,9 @@ void player_hungerUpdate(struct player* player); void player_send_entity_move(struct player* player, struct entity* entity); -<<<<<<< HEAD void player_receive_packet(struct player* player, struct packet* inp); -void player_tick(struct world* world, struct player* player); -======= void player_tick(struct player* player); ->>>>>>> 0a05322... tweaks void player_kick(struct player* player, char* message); @@ -94,7 +91,7 @@ float player_getAttackStrength(struct player* player, float adjust); void player_teleport(struct player* player, double x, double y, double z); -struct player* player_get_by_name(char* name); +struct player* player_get_by_name(struct server* server, char* name); void player_set_gamemode(struct player* player, int gamemode); diff --git a/include/basin/world.h b/include/basin/world.h index d7f53f2..a25c849 100644 --- a/include/basin/world.h +++ b/include/basin/world.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,9 @@ struct world { uint64_t seed; struct perlin perlin; struct queue* chunk_requests; + // locked under chunk_requests mutex + struct mempool* chunk_request_pool; + size_t tick_counter; }; // "*_guess" functions accept a chunk guess and call the proper function if the chunk is a miss. used to optimize chunk lookups in intensive local algorithms. probably overused. diff --git a/src/command.c b/src/command.c index f504744..e10fdf0 100644 --- a/src/command.c +++ b/src/command.c @@ -15,14 +15,14 @@ #include #include -void command_gamemode(struct player* player, char** args, size_t args_count) { +void command_gamemode(struct server* server, struct player* player, char** args, size_t args_count) { if (player != NULL) return; if (args_count == 0 || args_count > 2) { sendMessageToPlayer(player, "Usage: /gamemode [player]", "red"); return; } struct player* target = player; - if (args_count == 2) target = player_get_by_name(args[1]); + if (args_count == 2) target = player_get_by_name(player->server, args[1]); if (target == NULL) { sendMessageToPlayer(player, "[ERROR] No such player found.", "red"); return; @@ -38,14 +38,14 @@ void command_gamemode(struct player* player, char** args, size_t args_count) { sendMessageToPlayer(NULL, "Done.", "default"); } -void command_tp(struct player* player, char** args, size_t args_count) { +void command_tp(struct server* server, struct player* player, char** args, size_t args_count) { if (player != NULL) return; if (args_count == 0 || args_count > 4) { sendMessageToPlayer(player, "Usage: /tp OR /tp or or ", "red"); return; } if (args_count >= 3) { - struct player* from = args_count == 3 ? player : player_get_by_name(args[0]); + struct player* from = args_count == 3 ? player : player_get_by_name(server, args[0]); if (from == NULL) { sendMessageToPlayer(player, "[ERROR] No such player found.", "red"); return; @@ -53,8 +53,8 @@ void command_tp(struct player* player, char** args, size_t args_count) { int32_t ai = args_count == 4 ? 1 : 0; player_teleport(from, strtol(args[ai++], NULL, 10), strtol(args[ai++], NULL, 10), strtol(args[ai++], NULL, 10)); } else { - struct player* from = args_count == 1 ? player : player_get_by_name(args[0]); - struct player* to = args_count == 1 ? player_get_by_name(args[0]) : player_get_by_name(args[1]); + struct player* from = args_count == 1 ? player : player_get_by_name(server, args[0]); + struct player* to = args_count == 1 ? player_get_by_name(server, args[0]) : player_get_by_name(server, args[1]); if (from == NULL || to == NULL) { sendMessageToPlayer(player, "[ERROR] No such player found.", "red"); return; @@ -67,13 +67,13 @@ void command_tp(struct player* player, char** args, size_t args_count) { } } -void command_kick(struct player* player, char** args, size_t args_count) { +void command_kick(struct server* server, struct player* player, char** args, size_t args_count) { if (player != NULL) return; if (args_count == 0 || args_count > 2) { sendMessageToPlayer(player, "Usage: /kick OR /kick \"\"", "red"); return; } - struct player* target = player_get_by_name(args[0]); + struct player* target = player_get_by_name(server, args[0]); if (target == NULL) { sendMessageToPlayer(player, "[ERROR] No such player found.", "red"); return; @@ -82,7 +82,7 @@ void command_kick(struct player* player, char** args, size_t args_count) { player_kick(target, reason); } -void command_say(struct player* player, char** args, size_t args_count) { +void command_say(struct server* server, struct player* player, char** args, size_t args_count) { if (player != NULL) return; if (args_count != 1) { sendMessageToPlayer(player, "Usage: /say \"\"", "red"); @@ -91,19 +91,20 @@ void command_say(struct player* player, char** args, size_t args_count) { broadcastf("light_purple", "CONSOLE: %s", args[0]); } -void command_motd(struct player* player, char** args, size_t args_count) { +void command_motd(struct server* server, struct player* player, char** args, size_t args_count) { if (player != NULL) return; if (args_count != 1) { sendMessageToPlayer(NULL, "Usage: /motd \"\"", "red"); return; } sendMessageToPlayer(NULL, "Done.", "default"); - xfree (motd); - motd = xstrdup(args[0], 0); + server->motd = prealloc(global_pool, server->motd, strlen(args[0]) + 1); + server->motd[strlen(args[0])] = 0; + memcpy(server->motd, args[0], strlen(args[0]) + 1); } -void command_list(struct player* player, char** args, size_t args_count) { - char* plist = xmalloc(players->entry_count * 18 + 30); +void command_list(struct server* server, struct player* player, char** args, size_t args_count) { + char* plist = pmalloc(); char* cptr = plist; BEGIN_HASHMAP_ITERATION (players) if (cptr > plist) { diff --git a/src/game.c b/src/game.c index 90568a9..10dd94b 100644 --- a/src/game.c +++ b/src/game.c @@ -5,9 +5,7 @@ * Author: root */ -#include "basin/packet.h" -#include -#include +#include #include #include #include @@ -18,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/main.c b/src/main.c index 445b65d..8dc153d 100644 --- a/src/main.c +++ b/src/main.c @@ -354,7 +354,6 @@ int main(int argc, char* argv[]) { errlog(delog, "Only one server block is supported at this time."); return -1; } - globalChunkQueue = queue_new(0, 1, global_pool); init_materials(); acclog(delog, "Materials Initialized"); init_blocks(); diff --git a/src/player.c b/src/player.c index 28a5ba7..76db43c 100644 --- a/src/player.c +++ b/src/player.c @@ -23,6 +23,16 @@ #include #include +void player_cleanup(struct player* player) { + struct packet* pkt = NULL; + while ((pkt = queue_maybepop(player->incoming_packets)) != NULL) { + pfree(pkt->pool); + } + while ((pkt = queue_maybepop(player->outgoing_packets)) != NULL) { + pfree(pkt->pool); + } +} + struct player* player_new(struct mempool* parent, struct server* server, struct connection* conn, struct world* world, struct entity* entity, char* name, struct uuid uuid, uint8_t gamemode) { struct mempool* pool = mempool_new(); pchild(parent, pool); @@ -46,10 +56,11 @@ struct player* player_new(struct mempool* parent, struct server* server, struct player->loaded_entities = hashmap_thread_new(128, player->pool); player->incoming_packets = queue_new(0, 1, player->pool); player->outgoing_packets = queue_new(0, 1, player->pool); - player->lastSwing = player->server->tick_counter; + player->lastSwing = player->world->tick_counter; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); player->reachDistance = 6.f; + phook(player->pool, player_cleanup, player); return player; } @@ -57,9 +68,8 @@ void player_send_entity_move(struct player* player, struct entity* entity) { double dist = entity_distsq_block(entity, entity->last_x, entity->last_y, entity->last_z); double delta_rotation = (entity->yaw - entity->last_yaw) * (entity->yaw - entity->last_yaw) + (entity->pitch - entity->last_pitch) * (entity->pitch - entity->last_pitch); - //printf("mp = %f, md = %f\n", mp, md); if ((dist > .001 || delta_rotation > .01 || entity->type == ENT_PLAYER)) { - int force_update = player->server->tick_counter % 200 == 0 || (entity->type == ENT_PLAYER && entity->data.player.player->last_teleport_id != 0); + int force_update = player->world->tick_counter % 200 == 0 || (entity->type == ENT_PLAYER && entity->data.player.player->last_teleport_id != 0); if (!force_update && dist <= .001 && delta_rotation <= .01) { struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_ENTITY); pkt->data.play_client.entity.entity_id = entity->id; @@ -140,7 +150,7 @@ void player_tick(struct player* player) { return; }*/ player->chunks_sent = 0; - if (player->server->tick_counter % 200 == 0) { + if (player->world->tick_counter % 200 == 0) { if (player->next_keep_alive != 0) { player->conn->disconnect = 1; return; @@ -148,7 +158,7 @@ void player_tick(struct player* player) { struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_KEEPALIVE); pkt->data.play_client.keepalive.keep_alive_id = rand(); queue_push(player->outgoing_packets, pkt); - } else if (player->server->tick_counter % 200 == 100) { + } else if (player->world->tick_counter % 200 == 100) { struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_TIMEUPDATE); pkt->data.play_client.timeupdate.time_of_day = player->world->time; pkt->data.play_client.timeupdate.world_age = player->world->age; @@ -203,14 +213,14 @@ void player_tick(struct player* player) { int32_t last_chunk_z = ((int32_t) player->entity->last_z >> 4); if (player->loaded_chunks->entry_count == 0 || player->trigger_rechunk) { // || tick_counter % 200 == 0 beginProfilerSection("chunkLoading_tick"); - pthread_mutex_lock(&player->chunkRequests->data_mutex); + pthread_mutex_lock(&player->world->chunk_requests->data_mutex); int first_chunks = player->loaded_chunks->entry_count == 0 || player->trigger_rechunk; if (player->trigger_rechunk) { pthread_rwlock_rdlock(&player->loaded_chunks->rwlock); ITER_MAP(player->loaded_chunks) { struct chunk* chunk = (struct chunk*) value; if (chunk->x < chunk_x - CHUNK_VIEW_DISTANCE || chunk->x > chunk_x + CHUNK_VIEW_DISTANCE || chunk->z < chunk_z - CHUNK_VIEW_DISTANCE || chunk->z > chunk_z + CHUNK_VIEW_DISTANCE) { - struct chunk_request* request = pcalloc(player->world->pool, sizeof(struct chunk_request)); + struct chunk_request* request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); request->chunk_x = chunk->x; request->chunk_z = chunk->z; request->world = player->world; @@ -225,13 +235,13 @@ void player_tick(struct player* player) { int32_t x = chunk_x - r; int32_t z = chunk_z - r; for (int i = 0; i < ((r == 0) ? 1 : (r * 8)); i++) { - if (first_chunks || !contains_hashmap(player->loaded_chunks, chunk_get_key_direct(x, z))) { - struct chunk_request* cr = xmalloc(sizeof(struct chunk_request)); - cr->chunk_x = x; - cr->chunk_z = z; - cr->world = world; - cr->load = 1; - add_queue(player->chunkRequests, cr); + if (first_chunks || !hashmap_getint(player->loaded_chunks, chunk_get_key_direct(x, z))) { + struct chunk_request* request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); + request->chunk_x = x; + request->chunk_z = z; + request->world = player->world; + request->load = 1; + queue_push(player->world->chunk_requests, request); } if (i < 2 * r) x++; else if (i < 4 * r) z++; @@ -239,53 +249,51 @@ void player_tick(struct player* player) { else if (i < 8 * r) z--; } } - pthread_mutex_unlock(&player->chunkRequests->data_mutex); - player->triggerRechunk = 0; - pthread_cond_signal(&chunk_wake); + pthread_mutex_unlock(&player->world->chunk_requests->data_mutex); + player->trigger_rechunk = 0; endProfilerSection("chunkLoading_tick"); } if (last_chunk_x != chunk_x || last_chunk_z != chunk_z) { - pthread_mutex_lock(&player->chunkRequests->data_mutex); + pthread_mutex_lock(&player->world->chunk_requests->data_mutex); for (int32_t fx = last_chunk_x; last_chunk_x < chunk_x ? (fx < chunk_x) : (fx > chunk_x); last_chunk_x < chunk_x ? fx++ : fx--) { for (int32_t fz = last_chunk_z - CHUNK_VIEW_DISTANCE; fz <= last_chunk_z + CHUNK_VIEW_DISTANCE; fz++) { beginProfilerSection("chunkUnloading_live"); - struct chunk_request* cr = xmalloc(sizeof(struct chunk_request)); - cr->chunk_x = last_chunk_x < chunk_x ? (fx - CHUNK_VIEW_DISTANCE) : (fx + CHUNK_VIEW_DISTANCE); - cr->chunk_z = fz; - cr->load = 0; - add_queue(player->chunkRequests, cr); + struct chunk_request* request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); + request->chunk_x = last_chunk_x < chunk_x ? (fx - CHUNK_VIEW_DISTANCE) : (fx + CHUNK_VIEW_DISTANCE); + request->chunk_z = fz; + request->load = 0; + queue_push(player->world->chunk_requests, request); endProfilerSection("chunkUnloading_live"); beginProfilerSection("chunkLoading_live"); - cr = xmalloc(sizeof(struct chunk_request)); - cr->chunk_x = last_chunk_x < chunk_x ? (fx + CHUNK_VIEW_DISTANCE) : (fx - CHUNK_VIEW_DISTANCE); - cr->chunk_z = fz; - cr->world = world; - cr->load = 1; - add_queue(player->chunkRequests, cr); + request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); + request->chunk_x = last_chunk_x < chunk_x ? (fx + CHUNK_VIEW_DISTANCE) : (fx - CHUNK_VIEW_DISTANCE); + request->chunk_z = fz; + request->world = player->world; + request->load = 1; + queue_push(player->world->chunk_requests, request); endProfilerSection("chunkLoading_live"); } } for (int32_t fz = last_chunk_z; last_chunk_z < chunk_z ? (fz < chunk_z) : (fz > chunk_z); last_chunk_z < chunk_z ? fz++ : fz--) { for (int32_t fx = last_chunk_x - CHUNK_VIEW_DISTANCE; fx <= last_chunk_x + CHUNK_VIEW_DISTANCE; fx++) { beginProfilerSection("chunkUnloading_live"); - struct chunk_request* cr = xmalloc(sizeof(struct chunk_request)); - cr->chunk_x = fx; - cr->chunk_z = last_chunk_z < chunk_z ? (fz - CHUNK_VIEW_DISTANCE) : (fz + CHUNK_VIEW_DISTANCE); - cr->load = 0; - add_queue(player->chunkRequests, cr); + struct chunk_request* request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); + request->chunk_x = fx; + request->chunk_z = last_chunk_z < chunk_z ? (fz - CHUNK_VIEW_DISTANCE) : (fz + CHUNK_VIEW_DISTANCE); + request->load = 0; + queue_push(player->world->chunk_requests, request); endProfilerSection("chunkUnloading_live"); beginProfilerSection("chunkLoading_live"); - cr = xmalloc(sizeof(struct chunk_request)); - cr->chunk_x = fx; - cr->chunk_z = last_chunk_z < chunk_z ? (fz + CHUNK_VIEW_DISTANCE) : (fz - CHUNK_VIEW_DISTANCE); - cr->load = 1; - cr->world = world; - add_queue(player->chunkRequests, cr); + request = pcalloc(player->world->chunk_request_pool, sizeof(struct chunk_request)); + request->chunk_x = fx; + request->chunk_z = last_chunk_z < chunk_z ? (fz + CHUNK_VIEW_DISTANCE) : (fz - CHUNK_VIEW_DISTANCE); + request->load = 1; + request->world = player->world; + queue_push(player->world->chunk_requests, request); endProfilerSection("chunkLoading_live"); } } - pthread_mutex_unlock(&player->chunkRequests->data_mutex); - pthread_cond_signal(&chunk_wake); + pthread_mutex_unlock(&player->world->chunk_requests->data_mutex); } endProfilerSection("chunks"); if (player->itemUseDuration > 0) { @@ -297,29 +305,29 @@ void player_tick(struct player* player) { player->entity->usingItemOff = 0; updateMetadata(player->entity); } else if (ihi->maxUseDuration <= player->itemUseDuration) { - if (ihi->onItemUse != NULL) (*ihi->onItemUse)(world, player, player->itemUseHand ? 45 : (36 + player->currentItem), ihs, player->itemUseDuration); + if (ihi->onItemUse != NULL) (*ihi->onItemUse)(player->world, player, (uint8_t) (player->itemUseHand ? 45 : (36 + player->currentItem)), ihs, player->itemUseDuration); player->itemUseDuration = 0; player->entity->usingItemMain = 0; player->entity->usingItemOff = 0; updateMetadata(player->entity); } else { - if (ihi->onItemUseTick != NULL) (*ihi->onItemUseTick)(world, player, player->itemUseHand ? 45 : (36 + player->currentItem), ihs, player->itemUseDuration); + if (ihi->onItemUseTick != NULL) (*ihi->onItemUseTick)(player->world, player, (uint8_t) (player->itemUseHand ? 45 : (36 + player->currentItem)), ihs, player->itemUseDuration); player->itemUseDuration++; } } //if (((int32_t) player->entity->lx >> 4) != pcx || ((int32_t) player->entity->lz >> 4) != pcz || player->loaded_chunks->count < CHUNK_VIEW_DISTANCE * CHUNK_VIEW_DISTANCE * 4 || player->triggerRechunk) { //} if (player->digging >= 0.) { - block bw = world_get_block(world, player->digging_position.x, player->digging_position.y, player->digging_position.z); + block bw = world_get_block(player->world, player->digging_position.x, player->digging_position.y, player->digging_position.z); struct block_info* bi = getBlockInfo(bw); float digspeed = 0.; if (bi->hardness > 0.) { - pthread_mutex_lock(&player->inventory->mut); + pthread_mutex_lock(&player->inventory->mutex); struct slot* ci = inventory_get(player, player->inventory, 36 + player->currentItem); struct item_info* cii = ci == NULL ? NULL : getItemInfo(ci->item); int hasProperTool = (cii == NULL ? 0 : tools_proficient(cii->toolType, cii->harvestLevel, bw)); int hasProperTool2 = (cii == NULL ? 0 : tools_proficient(cii->toolType, 0xFF, bw)); - pthread_mutex_unlock(&player->inventory->mut); + pthread_mutex_unlock(&player->inventory->mutex); int rnt = bi->material->requiresnotool; float ds = hasProperTool2 ? cii->toolProficiency : 1.; //efficiency enchantment @@ -342,52 +350,47 @@ void player_tick(struct player* player) { } player->digging += (player->digging == 0. ? 2. : 1.) * digspeed; BEGIN_BROADCAST_EXCEPT_DIST(player, player->entity, 128.) - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_BLOCKBREAKANIMATION; + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_BLOCKBREAKANIMATION); pkt->data.play_client.blockbreakanimation.entity_id = player->entity->id; memcpy(&pkt->data.play_server.playerdigging.location, &player->digging_position, sizeof(struct encpos)); pkt->data.play_client.blockbreakanimation.destroy_stage = (int8_t) (player->digging * 9); - add_queue(bc_player->outgoing_packets, pkt); + queue_push(bc_player->outgoing_packets, pkt); END_BROADCAST(player->world->players) } beginProfilerSection("entity_transmission"); - if (tick_counter % 20 == 0) { - BEGIN_HASHMAP_ITERATION(player->loaded_entities) - struct entity* ent = (struct entity*) value; - if (entity_distsq(ent, player->entity) > (CHUNK_VIEW_DISTANCE * 16.) * (CHUNK_VIEW_DISTANCE * 16.)) { - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_DESTROYENTITIES; - pkt->data.play_client.destroyentities.count = 1; - pkt->data.play_client.destroyentities.entity_ids = xmalloc(sizeof(int32_t)); - pkt->data.play_client.destroyentities.entity_ids[0] = ent->id; - add_queue(player->outgoing_packets, pkt); - put_hashmap(player->loaded_entities, ent->id, NULL); - put_hashmap(ent->loadingPlayers, player->entity->id, NULL); + if (player->world->tick_counter % 20 == 0) { + pthread_rwlock_wrlock(&player->loaded_entities->rwlock); + ITER_MAP(player->loaded_entities) + { + struct entity* ent = (struct entity*) value; + if (entity_distsq(ent, player->entity) > (CHUNK_VIEW_DISTANCE * 16.) * (CHUNK_VIEW_DISTANCE * 16.)) { + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_DESTROYENTITIES); + pkt->data.play_client.destroyentities.count = 1; + pkt->data.play_client.destroyentities.entity_ids = pmalloc(pkt->pool, sizeof(int32_t)); + pkt->data.play_client.destroyentities.entity_ids[0] = ent->id; + queue_push(player->outgoing_packets, pkt); + hashmap_putint(player->loaded_entities, (uint64_t) ent->id, NULL); + hashmap_putint(ent->loadingPlayers, (uint64_t) player->entity->id, NULL); + } + ITER_MAP_END(); } - END_HASHMAP_ITERATION(player->loaded_entities) + pthread_rwlock_unlock(&player->loaded_entities->rwlock); } endProfilerSection("entity_transmission"); beginProfilerSection("player_transmission"); - //int32_t chunk_x = ((int32_t) player->entity->x) >> 4; - //int32_t chunk_z = ((int32_t) player->entity->z) >> 4; - //for (int32_t icx = chunk_x - CHUNK_VIEW_DISTANCE; icx <= chunk_x + CHUNK_VIEW_DISTANCE; icx++) - //for (int32_t icz = chunk_z - CHUNK_VIEW_DISTANCE; icz <= chunk_z + CHUNK_VIEW_DISTANCE; icz++) { - //struct chunk* ch = world_get_chunk(player->world, icx, icz); - //if (ch != NULL) { - BEGIN_HASHMAP_ITERATION(player->world->entities) - struct entity* ent = (struct entity*) value; - if (ent == player->entity || contains_hashmap(player->loaded_entities, ent->id) || entity_distsq(player->entity, ent) > (CHUNK_VIEW_DISTANCE * 16.) * (CHUNK_VIEW_DISTANCE * 16.)) continue; - if (ent->type == ENT_PLAYER) loadPlayer(player, ent->data.player.player); - else loadEntity(player, ent); - END_HASHMAP_ITERATION(player->world->entities) - //} - //} + ITER_MAP(player->world->entities) { + struct entity* ent = (struct entity*) value; + if (ent == player->entity || hashmap_getint(player->loaded_entities, (uint64_t) ent->id) || entity_distsq(player->entity, ent) > (CHUNK_VIEW_DISTANCE * 16.) * (CHUNK_VIEW_DISTANCE * 16.)) continue; + if (ent->type == ENT_PLAYER) loadPlayer(player, ent->data.player.player); + else loadEntity(player, ent); + ITER_MAP_END(); + } endProfilerSection("player_transmission"); - BEGIN_HASHMAP_ITERATION(plugins) - struct plugin* plugin = value; - if (plugin->tick_player != NULL) (*plugin->tick_player)(player->world, player); - END_HASHMAP_ITERATION(plugins) - //printf("%i\n", player->loaded_chunks->size); + ITER_MAP(plugins) { + struct plugin* plugin = value; + if (plugin->tick_player != NULL) (*plugin->tick_player)(player->world, player); + ITER_MAP_END(); + } } int player_onGround(struct player* player) { @@ -436,18 +439,17 @@ int player_onGround(struct player* player) { } void player_kick(struct player* player, char* message) { - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_DISCONNECT; + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_DISCONNECT); size_t sl = strlen(message); - pkt->data.play_client.disconnect.reason = xmalloc(sl + 512); - snprintf(pkt->data.play_client.disconnect.reason, sl + 512, "{\"text\": \"%s\", \"color\": \"red\"}", message); - add_queue(player->outgoing_packets, pkt); + pkt->data.play_client.disconnect.reason = pmalloc(pkt->pool, sl + 128); + snprintf(pkt->data.play_client.disconnect.reason, sl + 128, "{\"text\": \"%s\", \"color\": \"red\"}", message); + queue_push(player->outgoing_packets, pkt); if (player->conn != NULL) player->conn->disconnect = 1; broadcastf("red", "Kicked Player %s for reason: %s", player->name, message); } float player_getAttackStrength(struct player* player, float adjust) { - float cooldownPeriod = 4.; + float cooldownPeriod = 4f; struct slot* sl = inventory_get(player, player->inventory, 36 + player->currentItem); if (sl != NULL) { struct item_info* ii = getItemInfo(sl->item); @@ -455,9 +457,9 @@ float player_getAttackStrength(struct player* player, float adjust) { cooldownPeriod = ii->attackSpeed; } } - float str = ((float) (tick_counter - player->lastSwing) + adjust) * cooldownPeriod / 20.; - if (str > 1.) str = 1.; - if (str < 0.) str = 0.; + float str = ((float) (player->world->tick_counter - player->lastSwing) + adjust) * cooldownPeriod / 20f; + if (str > 1.) str = 1f; + if (str < 0.) str = 0f; return str; } @@ -468,176 +470,126 @@ void player_teleport(struct player* player, double x, double y, double z) { player->entity->last_x = x; player->entity->last_y = y; player->entity->last_z = z; - player->triggerRechunk = 1; - player->spawnedIn = 0; - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_ENTITYVELOCITY; + player->trigger_rechunk = 1; + player->spawned_in = 0; + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_ENTITYVELOCITY); pkt->data.play_client.entityvelocity.entity_id = player->entity->id; pkt->data.play_client.entityvelocity.velocity_x = 0; pkt->data.play_client.entityvelocity.velocity_y = 0; pkt->data.play_client.entityvelocity.velocity_z = 0; - add_queue(player->outgoing_packets, pkt); - pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_PLAYERPOSITIONANDLOOK; + queue_push(player->outgoing_packets, pkt); + pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_PLAYERPOSITIONANDLOOK); pkt->data.play_client.playerpositionandlook.x = player->entity->x; pkt->data.play_client.playerpositionandlook.y = player->entity->y; pkt->data.play_client.playerpositionandlook.z = player->entity->z; pkt->data.play_client.playerpositionandlook.yaw = player->entity->yaw; pkt->data.play_client.playerpositionandlook.pitch = player->entity->pitch; pkt->data.play_client.playerpositionandlook.flags = 0x0; - pkt->data.play_client.playerpositionandlook.teleport_id = tick_counter; + pkt->data.play_client.playerpositionandlook.teleport_id = (int32_t) player->world->tick_counter; player->last_teleport_id = pkt->data.play_client.playerpositionandlook.teleport_id; - add_queue(player->outgoing_packets, pkt); - /*BEGIN_HASHMAP_ITERATION(player->entity->loadingPlayers) - struct player* bp = value; - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_DESTROYENTITIES; - pkt->data.play_client.destroyentities.count = 1; - pkt->data.play_client.destroyentities.entity_ids = xmalloc(sizeof(int32_t)); - pkt->data.play_client.destroyentities.entity_ids[0] = player->entity->id; - add_queue(bp->outgoing_packets, pkt); - put_hashmap(bp->loaded_entities, player->entity->id, NULL); - pthread_rwlock_unlock(&player->entity->loadingPlayers->data_mutex); - put_hashmap(player->entity->loadingPlayers, bp->entity->id, NULL); - pthread_rwlock_rdlock(&player->entity->loadingPlayers->data_mutex); - END_HASHMAP_ITERATION(player->entity->loadingPlayers) - BEGIN_HASHMAP_ITERATION(player->loaded_entities) - struct entity* be = value; - if (be->type != ENT_PLAYER) continue; - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_DESTROYENTITIES; - pkt->data.play_client.destroyentities.count = 1; - pkt->data.play_client.destroyentities.entity_ids = xmalloc(sizeof(int32_t)); - pkt->data.play_client.destroyentities.entity_ids[0] = be->id; - add_queue(player->outgoing_packets, pkt); - put_hashmap(player->loaded_entities, be->id, NULL); - put_hashmap(be->loadingPlayers, player->entity->id, NULL); - END_HASHMAP_ITERATION(player->loaded_entities)*/ -// if (player->tps > 0) player->tps--; + queue_push(player->outgoing_packets, pkt); } -struct player* player_get_by_name(char* name) { - BEGIN_HASHMAP_ITERATION(players) - struct player* player = (struct player*) value; - if (player != NULL && streq_nocase(name, player->name)) { - BREAK_HASHMAP_ITERATION(players); - return player; +struct player* player_get_by_name(struct server* server, char* name) { + //TODO: this should be a map lookup + pthread_rwlock_rdlock(&server->players_by_entity_id->rwlock); + ITER_MAP (server->players_by_entity_id) { + struct player* player = (struct player*) value; + if (player != NULL && str_eq(name, player->name)) { + pthread_rwlock_unlock(&server->players_by_entity_id->rwlock); + return player; + } + ITER_MAP_END(); } - END_HASHMAP_ITERATION(players) + pthread_rwlock_unlock(&server->players_by_entity_id->rwlock); return NULL; } void player_closeWindow(struct player* player, uint16_t windowID) { - struct inventory* inv = NULL; - if (windowID == 0 && player->openInv == NULL) inv = player->inventory; - else if (player->open_inventory != NULL && windowID == player->open_inventory->windowID) inv = player->openInv; - if (inv != NULL) { - pthread_mutex_lock(&inv->mut); - if (player->inHand != NULL) { - dropPlayerItem(player, player->inHand); - freeSlot(player->inHand); - xfree(player->inHand); - player->inHand = NULL; + struct inventory* inventory = NULL; + if (windowID == 0 && player->open_inventory == NULL) { + inventory = player->inventory; + } else if (player->open_inventory != NULL && windowID == player->open_inventory->window) { + inventory = player->open_inventory; + } + if (inventory != NULL) { + pthread_mutex_lock(&inventory->mutex); + if (player->inventory_holding != NULL) { + dropPlayerItem(player, player->inventory_holding); + player->inventory_holding = NULL; } - if (inv->type == INVTYPE_PLAYERINVENTORY) { + if (inventory->type == INVTYPE_PLAYERINVENTORY) { for (int i = 1; i < 5; i++) { - if (inv->slots[i] != NULL) { - dropPlayerItem(player, inv->slots[i]); - inventory_set_slot(player, inv, i, NULL, 0, 1); + if (inventory->slots[i] != NULL) { + dropPlayerItem(player, inventory->slots[i]); + inventory_set_slot(player, inventory, i, NULL, 0); } } - } else if (inv->type == INVTYPE_WORKBENCH) { + } else if (inventory->type == INVTYPE_WORKBENCH) { for (int i = 1; i < 10; i++) { - if (inv->slots[i] != NULL) { - dropPlayerItem(player, inv->slots[i]); - inventory_set_slot(player, inv, i, NULL, 0, 1); + if (inventory->slots[i] != NULL) { + dropPlayerItem(player, inventory->slots[i]); + inventory_set_slot(player, inventory, i, NULL, 0); } } - pthread_mutex_unlock(&inv->mut); - freeInventory(inv); - inv = NULL; - } else if (inv->type == INVTYPE_CHEST) { - if (inv->tile != NULL) { - BEGIN_BROADCAST_DIST(player->entity, 128.) - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_BLOCKACTION; - pkt->data.play_client.blockaction.location.x = inv->tile->x; - pkt->data.play_client.blockaction.location.y = inv->tile->y; - pkt->data.play_client.blockaction.location.z = inv->tile->z; - pkt->data.play_client.blockaction.action_id = 1; - pkt->data.play_client.blockaction.action_param = inv->players->entry_count - 1; - pkt->data.play_client.blockaction.block_type = world_get_block(player->world, inv->tile->x, inv->tile->y, inv->tile->z) >> 4; - add_queue(bc_player->outgoing_packets, pkt); - END_BROADCAST(player->world->players) + pthread_mutex_unlock(&inventory->mutex); + pfree(inventory->pool); + inventory = NULL; + } else if (inventory->type == INVTYPE_CHEST) { + if (inventory->tile != NULL) { + BEGIN_BROADCAST_DIST(player->entity, 128.){ + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_BLOCKACTION); + pkt->data.play_client.blockaction.location.x = inventory->tile->x; + pkt->data.play_client.blockaction.location.y = inventory->tile->y; + pkt->data.play_client.blockaction.location.z = inventory->tile->z; + pkt->data.play_client.blockaction.action_id = 1; + pkt->data.play_client.blockaction.action_param = (uint8_t) (inventory->watching_players->entry_count - 1); + pkt->data.play_client.blockaction.block_type = world_get_block(player->world, inventory->tile->x, inventory->tile->y, inventory->tile->z) >> 4; + queue_push(bc_player->outgoing_packets, pkt); + END_BROADCAST(player->entity->world->players) + } } } - if (inv != NULL) { - if (inv->type != INVTYPE_PLAYERINVENTORY) put_hashmap(inv->players, player->entity->id, NULL); - pthread_mutex_unlock(&inv->mut); + if (inventory != NULL) { + if (inventory->type != INVTYPE_PLAYERINVENTORY) { + hashmap_putint(inventory->watching_players, (uint64_t) player->entity->id, NULL); + } + pthread_mutex_unlock(&inventory->mutex); } } - player->openInv = NULL; // TODO: free sometimes? + player->open_inventory = NULL; // TODO: free sometimes? } void player_set_gamemode(struct player* player, int gamemode) { if (gamemode != -1) { - player->gamemode = gamemode; - struct packet* pkt = xmalloc(sizeof(struct packet)); + player->gamemode = (uint8_t) gamemode; + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_CHANGEGAMESTATE); pkt->id = PKT_PLAY_CLIENT_CHANGEGAMESTATE; pkt->data.play_client.changegamestate.reason = 3; pkt->data.play_client.changegamestate.value = gamemode; - add_queue(player->outgoing_packets, pkt); + queue_push(player->outgoing_packets, pkt); } - struct packet* pkt = xmalloc(sizeof(struct packet)); - pkt->id = PKT_PLAY_CLIENT_PLAYERABILITIES; - pkt->data.play_client.playerabilities.flags = player->gamemode == 1 ? (0x04 | 0x08) : 0x0; + struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_PLAYERABILITIES); + pkt->data.play_client.playerabilities.flags = (int8_t) (player->gamemode == 1 ? (0x04 | 0x08) : 0x0); pkt->data.play_client.playerabilities.flying_speed = .05; pkt->data.play_client.playerabilities.field_of_view_modifier = .1; - add_queue(player->outgoing_packets, pkt); -} - -void player_free(struct player* player) { - struct packet* pkt = NULL; - while ((pkt = pop_nowait_queue(player->incoming_packets)) != NULL) { - freePacket(STATE_PLAY, 0, pkt); - xfree(pkt); - } - del_queue(player->incoming_packets); - while ((pkt = pop_nowait_queue(player->outgoing_packets)) != NULL) { - freePacket(STATE_PLAY, 1, pkt); - xfree(pkt); - } - del_queue(player->outgoing_packets); - struct chunk_request* cr; - while ((cr = pop_nowait_queue(player->chunkRequests)) != NULL) { - xfree(cr); - } - del_queue(player->chunkRequests); - if (player->inHand != NULL) { - freeSlot(player->inHand); - xfree(player->inHand); - } - del_hashmap(player->loaded_chunks); - del_hashmap(player->loaded_entities); - freeInventory(player->inventory); - xfree(player->inventory); - xfree(player->name); - xfree(player); + queue_push(player->outgoing_packets, pkt); } block player_can_place_block(struct player* player, block blk, int32_t x, int32_t y, int32_t z, uint8_t face) { - struct block_info* bi = getBlockInfo(blk); - block tbb = blk; - if (bi != NULL && bi->onBlockPlacedPlayer != NULL) tbb = (*bi->onBlockPlacedPlayer)(player, player->world, tbb, x, y, z, face); - BEGIN_HASHMAP_ITERATION(plugins) - struct plugin* plugin = value; - if (plugin->onBlockPlacedPlayer != NULL) tbb = (*plugin->onBlockPlacedPlayer)(player, player->world, tbb, x, y, z, face); - END_HASHMAP_ITERATION(plugins) - bi = getBlockInfo(blk); - if (bi != NULL && bi->canBePlaced != NULL && !(*bi->canBePlaced)(player->world, tbb, x, y, z)) { + struct block_info* info = getBlockInfo(blk); + block blk_updated = blk; + if (info != NULL && info->onBlockPlacedPlayer != NULL) blk_updated = (*info->onBlockPlacedPlayer)(player, player->world, blk_updated, x, y, z, face); + ITER_MAP(plugins) { + struct plugin* plugin = value; + if (plugin->onBlockPlacedPlayer != NULL) blk_updated = (*plugin->onBlockPlacedPlayer)(player, player->world, blk_updated, x, y, z, face); + ITER_MAP_END(); + } + info = getBlockInfo(blk); + if (info != NULL && info->canBePlaced != NULL && !(*info->canBePlaced)(player->world, blk_updated, x, y, z)) { return 0; } - block b = world_get_block(player->world, x, y, z); - return (b == 0 || getBlockInfo(b)->material->replacable) ? tbb : 0; + block new_block = world_get_block(player->world, x, y, z); + return (block) ((new_block == 0 || getBlockInfo(new_block)->material->replacable) ? blk_updated : 0); } diff --git a/src/player_packet.c b/src/player_packet.c index b2ff088..7e8ecd7 100644 --- a/src/player_packet.c +++ b/src/player_packet.c @@ -599,12 +599,12 @@ void player_packet_handle_useentity(struct player* player, struct mempool* pool, } } } else if (packet->type == 1) { - if (entity != NULL && entity != player->entity && entity->health > 0. && entity->world == player->world && entity_dist(entity, player->entity) < 4. && (player->server->tick_counter - player->lastSwing) >= 3) { + if (entity != NULL && entity != player->entity && entity->health > 0. && entity->world == player->world && entity_dist(entity, player->entity) < 4. && (player->world->tick_counter - player->lastSwing) >= 3) { pthread_mutex_lock(&player->inventory->mutex); damageEntityWithItem(entity, player->entity, (uint8_t) (36 + player->currentItem), inventory_get(player, player->inventory, 36 + player->currentItem)); pthread_mutex_unlock(&player->inventory->mutex); } - player->lastSwing = player->server->tick_counter; + player->lastSwing = player->world->tick_counter; } } @@ -926,7 +926,7 @@ void player_packet_handle_updatesign(struct player* player, struct mempool* pool } void player_packet_handle_animation(struct player* player, struct mempool* pool, struct pkt_play_server_animation* packet) { - player->lastSwing = player->server->tick_counter; + player->lastSwing = player->world->tick_counter; BEGIN_BROADCAST_EXCEPT_DIST(player, player->entity, CHUNK_VIEW_DISTANCE * 16.){ struct packet* pkt = packet_new(mempool_new(), PKT_PLAY_CLIENT_ANIMATION); pkt->data.play_client.animation.entity_id = player->entity->id; diff --git a/src/world.c b/src/world.c index 975f22d..daeee95 100644 --- a/src/world.c +++ b/src/world.c @@ -162,7 +162,7 @@ void world_chunkload_thread(struct world* world) { world_unload_chunk(request->world, chunk); } } - pprefree(world->pool, request); + pprefree(world->chunk_request_pool, request); /* BEGIN_HASHMAP_ITERATION (players) struct player* player = value; @@ -779,7 +779,9 @@ struct world* world_new(struct server* server) { world->ticksInSecond = 0; world->seed = 9876543; perlin_init(&world->perlin, world->seed); - world->chunk_requests = queue_new(0, 1, world->pool); + world->chunk_request_pool = mempool_new(); + pchild(world->pool, world->chunk_request_pool); + world->chunk_requests = queue_new(0, 1, world->chunk_request_pool); return world; } @@ -860,11 +862,12 @@ void world_tick(struct world* world) { pthread_cond_wait(&world->tick_cond, &world->tick_mut); pthread_mutex_unlock(&world->tick_mut); beginProfilerSection("world_tick"); - if (tick_counter % 20 == 0) { + if (world->tick_counter % 20 == 0) { world->tps = world->ticksInSecond; world->ticksInSecond = 0; } - world->ticksInSecond++; + ++world->tick_counter; + ++world->ticksInSecond; world_pretick(world); beginProfilerSection("player_receive_packet"); pthread_rwlock_rdlock(&world->players->rwlock);