Created
December 7, 2010 21:01
-
-
Save kev009/732405 to your computer and use it in GitHub Desktop.
chunk test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2010 Kevin M. Bowling, <[email protected]>, USA | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
#include <config.h> | |
#include <assert.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include "craftd-config.h" | |
#include "network.h" | |
#include "network-private.h" | |
#include "packets.h" | |
// Hack zlib in to test chunk sending | |
#include <stdio.h> | |
#include <zlib.h> | |
/** | |
* This internal method checks login predicates, populates the rest of the | |
* Player List entry, and sends the initial packet stream to spawn the player. | |
* | |
* @remarks Scope: private | |
* | |
* @param player Player List player pointer | |
* @param username inbound username from client login packet | |
* @param ver inbound version from client login packet | |
*/ | |
void | |
process_login(struct PL_entry *player, mcstring_t *username, uint32_t ver) | |
{ | |
// TODO: Future, async check of minecraft.net for user validity | |
// TODO: Future, check against local ACL | |
/* Check if the client version is compatible with the craftd version */ | |
if (ver != PROTOCOL_VERSION) | |
{ | |
const char *dconmsg = "Client version is incompatible with this server."; | |
send_kick(player, mcstring_create(strlen(dconmsg), dconmsg) ); | |
return; | |
} | |
/* Otherwise, finish populating their Player List entry */ | |
pthread_rwlock_wrlock(&player->rwlock); | |
mcstring_copy(&player->username, username); | |
pthread_rwlock_unlock(&player->rwlock); | |
send_loginresp(player); | |
send_prechunk(player, 0, 0, true); // TODO: pull spwan position from file | |
send_chunk(player, 0, 0, 0, 16, 128, 16); // TODO: pull spawn position | |
send_spawnpos(player, 7, 64, 7); // TODO: pull spawn position from file | |
//send inv | |
send_movelook(player, 7, 0, 64, 7, 0, 0, 0); //TODO: pull position from file | |
return; | |
} | |
/** | |
* Internal method that sends a login response packet | |
* | |
* @remarks Scope: private | |
* | |
* @param player Player List player pointer | |
*/ | |
void | |
send_loginresp(struct PL_entry *player) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
uint8_t pid = PID_LOGIN; | |
int32_t entityid = htonl(1); // TODO generate player entity IDs | |
int16_t unused1 = htons(0); // Future server name? mcstring. | |
int16_t unused2 = htons(0); // Future MOTD? mcstring. | |
int64_t mapseed = htonll(0); | |
int8_t dimension = 0; | |
evbuffer_add(output, &pid, sizeof(pid)); | |
evbuffer_add(output, &entityid, sizeof(entityid)); | |
evbuffer_add(output, &unused1, sizeof(unused1)); | |
evbuffer_add(output, &unused2, sizeof(unused2)); | |
evbuffer_add(output, &mapseed, sizeof(mapseed)); | |
evbuffer_add(output, &dimension, sizeof(dimension)); | |
return; | |
} | |
/** | |
* Send a prechunk packet to the player | |
* | |
* @remarks Scope: public API method | |
* | |
* @param player Player List player pointer | |
* @param x chunk x coordinate | |
* @param z chunk z coordinate | |
* @param mode unload (false) or load (true) the specified chunk | |
*/ | |
void | |
send_prechunk(struct PL_entry *player, int32_t x, int32_t z, bool mode) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
int8_t pid = PID_PRECHUNK; | |
int32_t n_x = htonl(x); | |
int32_t n_z = htonl(z); | |
uint8_t n_mode = mode; | |
evbuffer_add(output, &pid, sizeof(pid)); | |
evbuffer_add(output, &n_x, sizeof(n_x)); | |
evbuffer_add(output, &n_z, sizeof(n_z)); | |
evbuffer_add(output, &n_mode, sizeof(n_mode)); | |
return; | |
} | |
/** | |
* Send the specified chunk to the player | |
* | |
* @remarks Scope: public API method | |
* @remarks Internally and over the network size{x,y,z} are -1 over the wire | |
* | |
* @param player Player List player pointer | |
* @param x global chunk x coordinate | |
* @param y global chunk y coordinate | |
* @param z global chunk z coordinate | |
* @param sizex actual x size | |
* @param sizey actual y size | |
* @param sizez actual z size | |
*/ | |
void | |
send_chunk(struct PL_entry *player, int32_t x, int16_t y, int32_t z, | |
uint8_t sizex, uint8_t sizey, uint8_t sizez) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
struct evbuffer *tempbuf = evbuffer_new(); | |
int8_t pid = PID_MAPCHUNK; | |
int32_t n_x = htonl(x); | |
int16_t n_y = htons(y); | |
int32_t n_z = htonl(z); | |
/* Check that the chunk size is greater than zero since the protocol must | |
* subtract one before sending. If so, do it. | |
*/ | |
assert(sizex > 0 && sizey > 0 && sizez > 0); | |
assert(sizex <= 128 && sizey <= 128 && sizez <= 128); | |
--sizex; | |
--sizey; | |
--sizez; | |
// Hack in zlib support for test | |
uint8_t *mapdata = (uint8_t*)Malloc(MAX_CHUNKARRAY); | |
memset(mapdata, 0, MAX_CHUNKARRAY); | |
for(int i=0; i<=32768; i+=128) | |
mapdata[i] = 0x01; // Stone | |
memset(&mapdata[32768+16384], 10, 16384); | |
uLongf written = MAX_CHUNKARRAY; | |
Bytef *buffer = (Bytef*)Malloc(MAX_CHUNKARRAY); | |
if (compress(buffer, &written, &mapdata[0], MAX_CHUNKARRAY) != Z_OK) | |
assert(false); | |
int32_t n_written = htonl(written); | |
evbuffer_add(tempbuf, &pid, sizeof(pid)); | |
evbuffer_add(tempbuf, &n_x, sizeof(n_x)); | |
evbuffer_add(tempbuf, &n_y, sizeof(n_y)); | |
evbuffer_add(tempbuf, &n_z, sizeof(n_z)); | |
evbuffer_add(tempbuf, &sizex, sizeof(sizex)); | |
evbuffer_add(tempbuf, &sizey, sizeof(sizey)); | |
evbuffer_add(tempbuf, &sizez, sizeof(sizez)); | |
evbuffer_add(tempbuf, &n_written, sizeof(n_written)); | |
evbuffer_add(tempbuf, buffer, written); | |
evbuffer_add_buffer(output, tempbuf); | |
evbuffer_free(tempbuf); | |
free(mapdata); | |
free(buffer); | |
return; | |
} | |
/** | |
* Send the client their spawn position. Can also be used to later update | |
* their compass bearing. | |
* | |
* @param player Player List player pointer | |
* @param x global chunk x coordinate | |
* @param y global chunk y coordinate | |
* @param z global chunk z coordinate | |
*/ | |
void | |
send_spawnpos(struct PL_entry *player, int32_t x, int32_t y, int32_t z) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
int8_t pid = PID_SPAWNPOS; | |
int32_t n_x = htonl(x); | |
int32_t n_y = htonl(y); | |
int32_t n_z = htonl(z); | |
evbuffer_add(output, &pid, sizeof(pid)); | |
evbuffer_add(output, &n_x, sizeof(n_x)); | |
evbuffer_add(output, &n_y, sizeof(n_y)); | |
evbuffer_add(output, &n_z, sizeof(n_z)); | |
return; | |
} | |
/** | |
* Send a combined move+look packet to the player. | |
* | |
* @remarks Scope: public API method | |
* @remarks Note flip-flopped y and stance from client. -_- Notch. | |
* | |
* @param player Player List player pointer | |
* @param x absolute x coordinate | |
* @param stance modify player bounding box | |
* @param y absolute y coordinate | |
* @param z absolute z coordinate | |
* @param yaw rotation on the x-axis | |
* @param pitch rotation on the y-axis | |
* @param flying on the ground or in the air (like 0x0A) | |
*/ | |
void | |
send_movelook(struct PL_entry *player, double x, double stance, double y, | |
double z, float yaw, float pitch, bool flying) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
int8_t pid = PID_PLAYERMOVELOOK; | |
double n_x = Cswapd(x); | |
double n_stance = Cswapd(stance); | |
double n_y = Cswapd(y); | |
double n_z = Cswapd(z); | |
float n_yaw = Cswapf(yaw); | |
float n_pitch = Cswapf(pitch); | |
int8_t n_flying = flying; // Cast to int8 to ensure it is 1 byte | |
evbuffer_add(output, &pid, sizeof(pid)); | |
evbuffer_add(output, &n_x, sizeof(n_x)); | |
evbuffer_add(output, &n_y, sizeof(n_y)); | |
evbuffer_add(output, &n_stance, sizeof(n_stance)); | |
evbuffer_add(output, &n_z, sizeof(n_z)); | |
evbuffer_add(output, &n_yaw, sizeof(n_yaw)); | |
evbuffer_add(output, &n_pitch, sizeof(n_pitch)); | |
evbuffer_add(output, &n_flying, sizeof(n_flying)); | |
return; | |
} | |
/** | |
* Kick the specified player | |
* | |
* @remarks Scope: public API method | |
* | |
* @param player Player List player pointer | |
* @param dconmsg Pointer to an mcstring with the kick message | |
*/ | |
void | |
send_kick(struct PL_entry *player, mcstring_t *dconmsg) | |
{ | |
struct evbuffer *output = bufferevent_get_output(player->bev); | |
uint8_t pid = PID_DISCONNECT; | |
int16_t slen = htons(dconmsg->slen); | |
evbuffer_add(output, &pid, sizeof(pid)); | |
evbuffer_add(output, &slen, sizeof(slen)); | |
evbuffer_add(output, dconmsg->str, dconmsg->slen); | |
mcstring_free(dconmsg); | |
/* TODO forcefully close the socket and perform manual cleanup if the client | |
* doesn't voluntarily disconnect | |
*/ | |
return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment