From 221f079fe034319f2d012debc0d986eeb3a5f49f Mon Sep 17 00:00:00 2001 From: darkrose Date: Tue, 28 Mar 2017 18:42:12 +1000 Subject: [PATCH] sane code pt1 --- src/CMakeLists.txt | 5 + src/array.c | 807 ++++++++++++++++++++++++++++++++++++++ src/array.h | 68 ++++ src/character_creator.cpp | 1 + src/client.cpp | 67 ++-- src/client.h | 10 +- src/content_sao.cpp | 24 +- src/crypto.c | 98 +++++ src/crypto.h | 18 + src/crypto_base64.c | 203 ++++++++++ src/environment.cpp | 219 ++++++----- src/environment.h | 8 +- src/http.cpp | 38 +- src/list.c | 255 ++++++++++++ src/list.h | 34 ++ src/nvp.c | 170 ++++++++ src/nvp.h | 36 ++ src/server.cpp | 66 ++-- src/server.h | 4 +- 19 files changed, 1953 insertions(+), 178 deletions(-) create mode 100644 src/array.c create mode 100644 src/array.h create mode 100644 src/crypto.c create mode 100644 src/crypto.h create mode 100644 src/crypto_base64.c create mode 100644 src/list.c create mode 100644 src/list.h create mode 100644 src/nvp.c create mode 100644 src/nvp.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index abbc690..d6afbb3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -164,6 +164,11 @@ configure_file( ) set(common_SRCS + array.c + list.c + nvp.c + crypto.c + crypto_base64.c log.cpp content_sao.cpp mapgen.cpp diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..dd4c025 --- /dev/null +++ b/src/array.c @@ -0,0 +1,807 @@ +/************************************************************************ +* array.c +* tausaga - environmental survival game +* Copyright (C) Lisa 'darkrose' Milne 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +************************************************************************/ + +#include "array.h" + +#include +#include +#include + + +static int array_next_size(int s) +{ + s /= 16; + s = (s+1)*16; + return s; +} + +/* initialises an array - useful for those created on the stack */ +void array_init(array_t *a, uint32_t type) +{ + a->type = type; + a->length = 0; + a->size = 0; + a->data = NULL; +} + +/* create a new array of type */ +array_t *array_create(uint32_t type) +{ + array_t *a; + + a = malloc(sizeof(array_t)); + a->type = type; + a->length = 0; + a->size = 0; + a->data = NULL; + + return a; +} + +/* create a new array as a copy of a */ +array_t *array_copy(array_t *a) +{ + array_t *r = array_create(ARRAY_TYPE_STRING); + + if (a) { + int i; + r->type = a->type; + switch (a->type) { + case ARRAY_TYPE_STRING: + for (i=0; ilength; i++) { + array_push_string(r,((char**)(a->data))[i]); + } + break; + case ARRAY_TYPE_FLOAT: + for (i=0; ilength; i++) { + array_push_float(r,((float*)(a->data))[i]); + } + break; + case ARRAY_TYPE_INT: + for (i=0; ilength; i++) { + array_push_int(r,((uint32_t*)(a->data))[i]); + } + break; + case ARRAY_TYPE_PTR: + for (i=0; ilength; i++) { + array_push_ptr(r,((uint8_t**)(a->data))[i]); + } + break; + default:; + } + } + + return r; +} + +/* compare two arrays */ +int array_cmp(array_t *a1, array_t *a2) +{ + int i; + char** c1; + char** c2; + int *i1; + int *i2; + float *f1; + float *f2; + if (!a1 || !a2) + return -1; + if (a1->length != a2->length) + return -1; + + if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_STRING) { + c1 = a1->data; + c2 = a2->data; + for (i=0; ilength; i++) { + if (!c1[i] || !c2[i] || strcmp(c1[i],c2[i])) + return 1; + } + }else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_INT) { + c1 = a1->data; + i2 = a2->data; + for (i=0; ilength; i++) { + if (!c1[i] || i2[i] != strtol(c1[i],NULL,10)) + return 1; + } + }else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_FLOAT) { + c1 = a1->data; + f2 = a2->data; + for (i=0; ilength; i++) { + if (!c1[i] || f2[i] != strtof(c1[i],NULL)) + return 1; + } + }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_STRING) { + i1 = a1->data; + c2 = a2->data; + for (i=0; ilength; i++) { + if (!c2[i] || i1[i] != strtol(c2[i],NULL,10)) + return 1; + } + }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_STRING) { + f1 = a1->data; + c2 = a2->data; + for (i=0; ilength; i++) { + if (!c2[i] || f1[i] != strtof(c2[i],NULL)) + return 1; + } + }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_INT) { + i1 = a1->data; + i2 = a2->data; + for (i=0; ilength; i++) { + if (i1[i] != i2[i]) + return 1; + } + }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_FLOAT) { + f1 = a1->data; + f2 = a2->data; + for (i=0; ilength; i++) { + if (f1[i] != f2[i]) + return 1; + } + }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_FLOAT) { + i1 = a1->data; + f2 = a2->data; + for (i=0; ilength; i++) { + if (i1[i] != (int)f2[i]) + return 1; + } + }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_INT) { + f1 = a1->data; + i2 = a2->data; + for (i=0; ilength; i++) { + if ((int)f1[i] != i2[i]) + return 1; + } + }else if (a1->type == ARRAY_TYPE_PTR && a2->type == ARRAY_TYPE_PTR) { + c1 = a1->data; + c2 = a2->data; + for (i=0; ilength; i++) { + if (c1[i] != c2[i]) + return 1; + } + } + + return 0; +} + +/* destroy an array */ +void array_free(array_t *a, int freestruct) +{ + int i; + if (!a) + return; + if (a->type == ARRAY_TYPE_STRING) { + char** p = a->data; + for (i=0; ilength; i++ ) { + if (p[i]) + free(p[i]); + } + } + free(a->data); + if (freestruct) + free(a); +} + +/* push an int onto an array */ +int array_push_int(array_t *a, uint32_t v) +{ + uint32_t *p; + if (a->type == ARRAY_TYPE_STRING) { + char sv[20]; + sprintf(sv,"%u",v); + return array_push_string(a,sv); + }else if (a->type == ARRAY_TYPE_FLOAT) { + return array_push_float(a,(float)v); + }else if (a->type != ARRAY_TYPE_INT) { + return 1; + } + + a->length++; + + p = a->data; + + if (a->size < a->length) { + int s = array_next_size(a->length); + p = realloc(a->data,sizeof(uint32_t)*s); + if (!p) { + a->length--; + return 1; + } + a->size = s; + } + + p[a->length-1] = v; + a->data = p; + + return 0; +} + +/* push a float onto an array */ +int array_push_float(array_t *a, float v) +{ + float *p; + if (a->type == ARRAY_TYPE_STRING) { + char sv[20]; + sprintf(sv,"%f",v); + return array_push_string(a,sv); + }else if (a->type == ARRAY_TYPE_INT) { + return array_push_int(a,(int)v); + }else if (a->type != ARRAY_TYPE_FLOAT) { + return 1; + } + + a->length++; + + p = a->data; + + if (a->size < a->length) { + int s = array_next_size(a->length); + p = realloc(a->data,sizeof(float)*s); + if (!p) { + a->length--; + return 1; + } + a->size = s; + } + + p[a->length-1] = v; + a->data = p; + + return 0; +} + +/* push a string onto an array */ +int array_push_string(array_t *a, char* v) +{ + char** p; + if (a->type != ARRAY_TYPE_STRING) + return 1; + + a->length++; + + p = a->data; + + if (a->size < a->length) { + int s = array_next_size(a->length); + p = realloc(a->data,sizeof(char*)*s); + if (!p) { + a->length--; + return 1; + } + a->size = s; + } + + if (v) { + p[a->length-1] = strdup(v); + }else{ + p[a->length-1] = NULL; + } + a->data = p; + + return 0; +} + +/* push a pointer onto an array */ +int array_push_ptr(array_t *a, void *v) +{ + char** p; + if (a->type != ARRAY_TYPE_PTR) + return 1; + + a->length++; + + p = a->data; + + if (a->size < a->length) { + int s = array_next_size(a->length); + p = realloc(a->data,sizeof(char*)*s); + if (!p) { + a->length--; + return 1; + } + a->size = s; + } + + p[a->length-1] = v; + + a->data = p; + + return 0; +} + +/* push a pointer onto an array if it isn't already in there */ +int array_push_unique_ptr(array_t *a, void *v) +{ + if (array_find_ptr(a,v) > -1) + return 0; + + return array_push_ptr(a,v); +} + +/* push a colour onto an array * +int array_push_colour(array_t *a, colour_t *c) +{ + int r = 0; + r += array_push_float(a,((float)c->r)/255.0); + r += array_push_float(a,((float)c->g)/255.0); + r += array_push_float(a,((float)c->b)/255.0); + r += array_push_float(a,((float)c->a)/255.0); + return r; +} + +* push a v3_t onto an array * +int array_push_v3t(array_t *a, v3_t *v) +{ + int r = 0; + r += array_push_float(a,v->x); + r += array_push_float(a,v->y); + r += array_push_float(a,v->z); + return r; +} + +* push a v2_t onto an array * +int array_push_v2t(array_t *a, v2_t *v) +{ + int r = 0; + r += array_push_float(a,v->x); + r += array_push_float(a,v->y); + return r; +} + +* set the value of array index i to an int value */ +int array_set_int(array_t *a, uint32_t v, int i) +{ + uint32_t *p = a->data; + if (a->type == ARRAY_TYPE_STRING) { + char sv[20]; + sprintf(sv,"%u",v); + return array_set_string(a,sv,i); + }else if (a->type == ARRAY_TYPE_FLOAT) { + return array_set_float(a,(float)v,i); + }else if (a->type != ARRAY_TYPE_INT) { + return 1; + } + + if (a->size <= i) { + int k; + int l = array_next_size(i+1); + + p = realloc(a->data,sizeof(uint32_t)*l); + if (!p) + return 1; + for (k=a->length; kdata = p; + a->size = l; + } + + if (a->length <= i) + a->length = i+1; + + p[i] = v; + + return 0; +} + +/* set the value of array index i to a float value */ +int array_set_float(array_t *a, float v, int i) +{ + float *p = a->data; + if (a->type == ARRAY_TYPE_STRING) { + char sv[20]; + sprintf(sv,"%f",v); + return array_set_string(a,sv,i); + }else if (a->type == ARRAY_TYPE_INT) { + return array_set_float(a,(uint32_t)v,i); + }else if (a->type != ARRAY_TYPE_FLOAT) { + return 1; + } + + if (a->size <= i) { + int k; + int l = array_next_size(i+1); + + p = realloc(a->data,sizeof(float)*l); + if (!p) + return 1; + for (k=a->length; kdata = p; + a->size = l; + } + if (a->length <= i) + a->length = i+1; + + p[i] = v; + + return 0; +} + +/* set the value of array index i to a string value */ +int array_set_string(array_t *a, char* v, int i) +{ + char** p = a->data; + if (a->type != ARRAY_TYPE_STRING) + return 1; + + if (a->size <= i) { + int k; + int l = array_next_size(i+1); + + p = realloc(a->data,sizeof(char*)*l); + if (!p) + return 1; + for (k=a->length; kdata = p; + a->size = l; + } + if (a->length <= i) + a->length = i+1; + + if (p[i]) + free(p[i]); + + if (v) { + p[i] = strdup(v); + }else{ + p[i] = NULL; + } + + return 0; +} + +/* set the value of array index i to a ponter value */ +int array_set_ptr(array_t *a, void* v, int i) +{ + char** p = a->data; + if (a->type != ARRAY_TYPE_PTR) + return 1; + + if (a->size <= i) { + int k; + int l = array_next_size(i+1); + + p = realloc(a->data,sizeof(char*)*l); + if (!p) + return 1; + for (k=a->length; kdata = p; + a->size = l; + } + if (a->length <= i) + a->length = i+1; + + p[i] = v; + + return 0; +} + +/* insert a pointer onto the first NULL index of an array */ +int array_insert_ptr(array_t *a, void *v) +{ + int i; + uint8_t** p; + + if (a->type != ARRAY_TYPE_PTR) + return 1; + + p = a->data; + + for (i=0; ilength; i++) { + if (!p[i]) { + p[i] = v; + return 0; + } + } + + return array_push_ptr(a,v); +} + +/* pop an int off the top of an array */ +uint32_t array_pop_int(array_t *a) +{ + if (a->type == ARRAY_TYPE_INT) { + if (!a->length) + return 0; + a->length--; + return ((uint32_t*)(a->data))[a->length]; + }else if (a->type == ARRAY_TYPE_FLOAT) { + float v = array_pop_float(a); + return (uint32_t)v; + }else if (a->type == ARRAY_TYPE_STRING) { + uint32_t v; + char* s = array_pop_string(a); + v = strtol(s,NULL,10); + free(s); + return v; + } + return 0; +} + +/* pop a float off the top of an array */ +float array_pop_float(array_t *a) +{ + if (a->type == ARRAY_TYPE_FLOAT) { + if (!a->length) + return 0; + a->length--; + return ((float*)(a->data))[a->length]; + }else if (a->type == ARRAY_TYPE_INT) { + uint32_t v = array_pop_int(a); + return (float)v; + }else if (a->type == ARRAY_TYPE_STRING) { + float v; + char* s = array_pop_string(a); + v = strtof(s,NULL); + free(s); + return v; + } + return 0.0; +} + +/* pop a string off the top of an array */ +char* array_pop_string(array_t *a) +{ + if (a->type == ARRAY_TYPE_FLOAT) { + float v = array_pop_float(a); + char sv[20]; + if (!a->length) + return NULL; + sprintf(sv,"%f",v); + return strdup(sv); + }else if (a->type == ARRAY_TYPE_INT) { + uint32_t v = array_pop_int(a); + char sv[20]; + if (!a->length) + return NULL; + sprintf(sv,"%u",v); + return strdup(sv); + }else if (a->type == ARRAY_TYPE_STRING) { + if (!a->length) + return NULL; + a->length--; + return ((char**)(a->data))[a->length]; + } + return NULL; +} + +/* pop a pointer off the top of an array */ +void *array_pop_ptr(array_t *a) +{ + if (a->type == ARRAY_TYPE_PTR && a->length) { + a->length--; + return ((char**)(a->data))[a->length]; + } + return NULL; +} + +/* get an int value from an array */ +uint32_t array_get_int(array_t *a, int i) +{ + if (a->type == ARRAY_TYPE_INT) { + if (a->length <= i) + return 0; + return ((uint32_t*)(a->data))[i]; + }else if (a->type == ARRAY_TYPE_FLOAT) { + float v = array_get_float(a,i); + return (uint32_t)v; + }else if (a->type == ARRAY_TYPE_STRING) { + uint32_t v; + char* s = array_get_string(a,i); + v = strtol(s,NULL,10); + free(s); + return v; + } + return 0; +} + +/* get a float value from an array */ +float array_get_float(array_t *a, int i) +{ + if (a->type == ARRAY_TYPE_FLOAT) { + if (a->length <= i) + return 0.0; + return ((float*)(a->data))[i]; + }else if (a->type == ARRAY_TYPE_INT) { + uint32_t v = array_get_int(a,i); + return (float)v; + }else if (a->type == ARRAY_TYPE_STRING) { + float v; + char* s = array_get_string(a,i); + v = strtof(s,NULL); + free(s); + return v; + } + return 0.0; +} + +/* get a string value from an array */ +char* array_get_string(array_t *a, int i) +{ + if (a->type == ARRAY_TYPE_FLOAT) { + float v = array_get_float(a,i); + char sv[20]; + sprintf(sv,"%f",v); + return strdup(sv); + }else if (a->type == ARRAY_TYPE_INT) { + uint32_t v = array_get_int(a,i); + char sv[20]; + sprintf(sv,"%u",v); + return strdup(sv); + }else if (a->type == ARRAY_TYPE_STRING) { + if (a->length <= i) + return NULL; + return ((char**)(a->data))[i]; + } + return NULL; +} + +/* get a pointer from an array */ +void *array_get_ptr(array_t *a, int i) +{ + if (a->type == ARRAY_TYPE_PTR && a->length > i) { + return ((char**)(a->data))[i]; + } + return NULL; +} + +/* find the index of an int value in an array */ +int array_find_int(array_t *a, uint32_t v) +{ + if (a->type == ARRAY_TYPE_INT) { + int i; + uint32_t *p = a->data; + for (i=0; ilength; i++) { + if (p[i] == v) + return i; + } + } + return -1; +} + +/* find the index of a float value in an array */ +int array_find_float(array_t *a, float v) +{ + if (a->type == ARRAY_TYPE_FLOAT) { + int i; + float *p = a->data; + for (i=0; ilength; i++) { + if (p[i] == v) + return i; + } + } + return -1; +} + +/* find the index of a string value in an array */ +int array_find_string(array_t *a, char* v) +{ + if (a->type == ARRAY_TYPE_STRING) { + int i; + char** p = a->data; + for (i=0; ilength; i++) { + if (!strcmp(p[i],v)) + return i; + } + } + return -1; +} + +/* find the index of a pointer in an array */ +int array_find_ptr(array_t *a, void *v) +{ + if (a->type == ARRAY_TYPE_PTR) { + int i; + uint8_t* cv = v; + uint8_t** p = a->data; + for (i=0; ilength; i++) { + if (p[i] == cv) + return i; + } + } + return -1; +} + +/* remove a string value from an array */ +int array_remove_string(array_t *a, char* v) +{ + if (a->type == ARRAY_TYPE_STRING) { + int i; + char** p = a->data; + for (i=0; ilength; i++) { + if (!strcmp(p[i],v)) { + free(p[i]); + break; + } + } + a->length--; + for (; ilength; i++) { + p[i] = p[i+1]; + } + return 0; + } + return 1; +} + +/* split a string into an array, at a separator character */ +/* TODO: if strings is non-zero, then don't split within "" or '' */ +/* TODO: utf8 support */ +array_t *array_split(char* str, char* s, int strings) +{ + char buff[1024]; + int i; + int o = 0; + int l; + array_t *r; + + if (!str) + return NULL; + + r = array_create(ARRAY_TYPE_STRING); + + l = strlen(s); + + for (i=0; str[i]; i++) { + if (!strncmp(str+i,s,l)) { + buff[o] = 0; + array_push_string(r,buff); + o = 0; + i += l-1; + continue; + } + buff[o++] = str[i]; + } + buff[o] = 0; + array_push_string(r,buff); + + return r; +} + +/* join an array into a string, using a glue character */ +char* array_join(array_t *a, char* glue, int start) +{ + char* str = NULL; + int l = 0; + if (!glue) + glue = " "; + if (a->type == ARRAY_TYPE_STRING) { + int i; + int gl = strlen(glue); + for (i=start; ilength; i++) { + l += strlen(((char**)(a->data))[i])+gl; + } + if (l) { + str = malloc(l+1); + str[0] = 0; + for (i=start; ilength; i++) { + if (i > start) + strcat(str,glue); + strcat(str,((char**)(a->data))[i]); + } + } + } + + return str; +} diff --git a/src/array.h b/src/array.h new file mode 100644 index 0000000..4d84027 --- /dev/null +++ b/src/array.h @@ -0,0 +1,68 @@ +#ifndef _ARRAY_H_ +#define _ARRAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef _HAVE_ARRAY_TYPE +#define _HAVE_ARRAY_TYPE +typedef struct array_s { + uint32_t type; + uint32_t length; + uint32_t size; + void *data; +} array_t; +#endif + + +#define ARRAY_TYPE_NONE 0 +#define ARRAY_TYPE_INT 1 +#define ARRAY_TYPE_STRING 2 +#define ARRAY_TYPE_FLOAT 3 +#define ARRAY_TYPE_PTR 4 + +/* defined in array.c */ +void array_init(array_t *a, uint32_t type); +array_t *array_create(uint32_t type); +array_t *array_copy(array_t *a); +int array_cmp(array_t *a1, array_t *a2); +void array_free(array_t *a, int freestruct); +int array_push_int(array_t *a, uint32_t v); +int array_push_float(array_t *a, float v); +int array_push_string(array_t *a, char* v); +int array_push_ptr(array_t *a, void *v); +int array_push_unique_ptr(array_t *a, void *v); +/* +int array_push_colour(array_t *a, colour_t *c); +int array_push_v3t(array_t *a, v3_t *v); +int array_push_v2t(array_t *a, v2_t *v); +*/ +int array_set_int(array_t *a, uint32_t v, int i); +int array_set_float(array_t *a, float v, int i); +int array_set_string(array_t *a, char* v, int i); +int array_set_ptr(array_t *a, void* v, int i); +int array_insert_ptr(array_t *a, void *v); +uint32_t array_pop_int(array_t *a); +float array_pop_float(array_t *a); +char* array_pop_string(array_t *a); +void *array_pop_ptr(array_t *a); +uint32_t array_get_int(array_t *a, int i); +float array_get_float(array_t *a, int i); +char* array_get_string(array_t *a, int i); +void *array_get_ptr(array_t *a, int i); +int array_find_int(array_t *a, uint32_t v); +int array_find_float(array_t *a, float v); +int array_find_string(array_t *a, char* v); +int array_find_ptr(array_t *a, void *v); +int array_remove_string(array_t *a, char* v); +array_t *array_split(char* str, char* s, int strings); +char* array_join(array_t *a, char* glue, int start); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/character_creator.cpp b/src/character_creator.cpp index f1344de..5a8e233 100644 --- a/src/character_creator.cpp +++ b/src/character_creator.cpp @@ -153,6 +153,7 @@ GUICharDefMenu::~GUICharDefMenu() void GUICharDefMenu::removeChildren() { + /* irrlicht internal */ const core::list &children = getChildren(); core::list children_copy; for (core::list::ConstIterator i = children.begin(); i != children.end(); i++) { diff --git a/src/client.cpp b/src/client.cpp index ec538d7..bf08a49 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -45,6 +45,8 @@ #include "content_craftitem.h" #include "content_mob.h" +#include "array.h" + /* QueuedMeshUpdate */ @@ -58,7 +60,7 @@ QueuedMeshUpdate::QueuedMeshUpdate(): QueuedMeshUpdate::~QueuedMeshUpdate() { - if(data) + if (data) delete data; } @@ -68,18 +70,18 @@ QueuedMeshUpdate::~QueuedMeshUpdate() MeshUpdateQueue::MeshUpdateQueue() { + m_queue = NULL; m_mutex.Init(); } MeshUpdateQueue::~MeshUpdateQueue() { + QueuedMeshUpdate *i; JMutexAutoLock lock(m_mutex); - core::list::Iterator i; - for(i=m_queue.begin(); i!=m_queue.end(); i++) - { - QueuedMeshUpdate *q = *i; - delete q; + while (m_queue != NULL) { + i = (QueuedMeshUpdate*)list_pull(&m_queue); + delete i; } } @@ -98,9 +100,8 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se Find if block is already in queue. If it is, update the data and quit. */ - core::list::Iterator i; - for (i=m_queue.begin(); i!=m_queue.end(); i++) { - QueuedMeshUpdate *q = *i; + QueuedMeshUpdate* q = m_queue; + while (q) { if (q->p == p) { if (q->data && data->m_refresh_only) { q->data->m_daynight_ratio = data->m_daynight_ratio; @@ -114,16 +115,18 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se q->ack_block_to_server = true; return; } + q = q->next; } /* Add the block */ - QueuedMeshUpdate *q = new QueuedMeshUpdate; + q = new QueuedMeshUpdate; q->p = p; q->data = data; q->ack_block_to_server = ack_block_to_server; - m_queue.push_back(q); + + m_queue = (QueuedMeshUpdate*)list_push(&m_queue,q); } // Returned pointer must be deleted @@ -132,12 +135,7 @@ QueuedMeshUpdate * MeshUpdateQueue::pop() { JMutexAutoLock lock(m_mutex); - core::list::Iterator i = m_queue.begin(); - if(i == m_queue.end()) - return NULL; - QueuedMeshUpdate *q = *i; - m_queue.erase(i); - return q; + return (QueuedMeshUpdate*)list_pull(&m_queue); } /* @@ -927,11 +925,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u16 field_count = readU16(is); // peer_ids - core::list players_alive; + array_t players_alive; + array_init(&players_alive,ARRAY_TYPE_INT); for (u16 i=0; i players = m_env.getPlayers(); - core::list::Iterator ip; - for (ip=players.begin(); ip!=players.end(); ip++) { + array_t *players = m_env.getPlayers(); + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; // Ignore local player - if ((*ip)->isLocal()) + if (player->isLocal()) continue; // Warn about a special case - if ((*ip)->peer_id == 0) + if (player->peer_id == 0) infostream<<"Client: Removing dead player with id=0"<::Iterator i; - for (i=players_alive.begin(); i!=players_alive.end(); i++) { - if ((*ip)->peer_id == *i) { - is_alive = true; - break; - } - } - if (is_alive) + if (array_find_int(&players_alive,player->peer_id) > -1) continue; - infostream<<"Removing dead player "<<(*ip)->peer_id - <peer_id); + infostream<<"Removing dead player "<peer_id<peer_id); } } //envlock } diff --git a/src/client.h b/src/client.h index 1a46572..5f1c5b0 100644 --- a/src/client.h +++ b/src/client.h @@ -38,6 +38,8 @@ #include "utility.h" // For IntervalLimiter #include "sound.h" +#include "list.h" + struct MeshMakeData; class ClientNotReadyException : public BaseException @@ -50,6 +52,8 @@ public: struct QueuedMeshUpdate { + struct QueuedMeshUpdate *prev; + struct QueuedMeshUpdate *next; v3s16 p; MeshMakeData *data; bool ack_block_to_server; @@ -80,11 +84,13 @@ public: u32 size() { JMutexAutoLock lock(m_mutex); - return m_queue.size(); + if (m_queue == NULL) + return 0; + return list_count(&m_queue); } private: - core::list m_queue; + QueuedMeshUpdate* m_queue; JMutex m_mutex; }; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 5643320..fd8f20e 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -32,6 +32,8 @@ #include "nodemetadata.h" #include "mapblock.h" +#include "array.h" + core::map ServerActiveObject::m_types; /* Some helper functions */ @@ -218,14 +220,19 @@ void MobSAO::step(float dtime, bool send_recommended) /* don't do anything if there's no nearby player */ if (m_disturbing_player == "") { float distance = 40*BS; - core::list players = m_env->getPlayers(true); - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *player = *i; + array_t *players = m_env->getPlayers(true); + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; v3f playerpos = player->getPosition(); f32 dist = m_base_position.getDistanceFrom(playerpos); if (dist < distance) distance = dist; } + array_free(players,1); if (distance > 32*BS) { /* kill of anything that shouldn't be on its own */ if ( @@ -292,9 +299,13 @@ void MobSAO::step(float dtime, bool send_recommended) ) { m_disturbing_player = ""; // Check connected players - core::list players = m_env->getPlayers(true); - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *player = *i; + array_t *players = m_env->getPlayers(true); + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; v3f playerpos = player->getPosition(); f32 dist = m_base_position.getDistanceFrom(playerpos); if (dist < BS*16) { @@ -309,6 +320,7 @@ void MobSAO::step(float dtime, bool send_recommended) } } } + array_free(players,1); } } if (m_disturbing_player != "") { diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index 0000000..ed2103b --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,98 @@ +/************************************************************************ +* crypto.c +* tausaga - environmental survival game +* Copyright (C) Lisa 'darkrose' Milne 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +************************************************************************/ + +#include "crypto.h" + +#include +#include + +/* defined in base64.c */ +int base64_lencode(char *source, size_t sourcelen, char *target, size_t targetlen); +size_t base64_ldecode(char *source, char *target, size_t targetlen); + +uint32_t hash(char *str_param) +{ + uint32_t hval = 0; + uint32_t g; + const char *s = str_param; + + while (*s) { + hval <<= 4; + hval += (unsigned char) *s++; + g = hval & ((uint32_t) 0xf << 28); + if (g != 0) { + hval ^= g >> 24; + hval ^= g; + } + } + + return hval; +} + +/* base64 encode a string */ +char* base64_encode(char* str) +{ + int sl; + int tl; + char* ret; + int el; + if (!str) + return NULL; + + sl = strlen(str); + tl = ((sl+2)/3*4)+5; + + ret = malloc(tl); + if (!ret) + return NULL; + + el = base64_lencode(str, sl, ret, tl); + if (!el) { + free(ret); + return NULL; + } + + return ret; +} + +/* decode a base64 string */ +char* base64_decode(char* str) +{ + int sl; + int tl; + char* ret; + int dl; + if (!str) + return NULL; + + sl = strlen(str); + tl = (sl/4*3)+5; + ret = malloc(tl); + if (!ret) + return NULL; + + dl = base64_ldecode(str, ret, tl); + if (!dl) { + free(ret); + return NULL; + } + ret[dl] = 0; + + return ret; +} diff --git a/src/crypto.h b/src/crypto.h new file mode 100644 index 0000000..3be1441 --- /dev/null +++ b/src/crypto.h @@ -0,0 +1,18 @@ +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +uint32_t hash(char* str); +char* base64_encode(char* str); +char* base64_decode(char* str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/crypto_base64.c b/src/crypto_base64.c new file mode 100644 index 0000000..617cd04 --- /dev/null +++ b/src/crypto_base64.c @@ -0,0 +1,203 @@ +/************************************************************************ +* crypto_base64.c +* tausaga - environmental survival game +* Copyright (C) Lisa 'darkrose' Milne 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +************************************************************************/ + +#include "crypto.h" + +#include +#include +#include + +static const char* b64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* encode three bytes using base64 */ +static void s_base64_encode_triple(unsigned char triple[3], unsigned char result[4]) +{ + int tripleValue; + int i; + int v; + + tripleValue = triple[0]; + tripleValue *= 256; + tripleValue += triple[1]; + tripleValue *= 256; + tripleValue += triple[2]; + + for (i=0; i<4; i++) { + v = tripleValue%64; + if (v < 0) { + v *= -1; + } + if (v > 63) { + result[3-i] = '='; + }else{ + result[3-i] = b64_chars[v]; + } + tripleValue /= 64; + } +} + +/* get the value of a base64 encoding character */ +static int s_base64_char_value(unsigned char c) +{ + if (c >= 'A' && c <= 'Z') + return c-'A'; + if (c >= 'a' && c <= 'z') + return c-'a'+26; + if (c >= '0' && c <= '9') + return c-'0'+2*26; + if (c == '+') + return 2*26+10; + if (c == '/') + return 2*26+11; + return -1; +} + +/* decode a 4 char base64 encoded byte triple */ +static int s_base64_decode_triple(unsigned char quadruple[4], unsigned char *result) +{ + int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1; + int char_value[4]; + + for (i=0; i<4; i++) { + char_value[i] = s_base64_char_value(quadruple[i]); + } + + /* check if the characters are valid */ + for (i=3; i>=0; i--) { + if (char_value[i]<0) { + if (only_equals_yet && quadruple[i]=='=') { + /* we will ignore this character anyway, make it something + * that does not break our calculations */ + char_value[i]=0; + bytes_to_decode--; + continue; + } + return 0; + } + /* after we got a real character, no other '=' are allowed anymore */ + only_equals_yet = 0; + } + + /* if we got "====" as input, bytes_to_decode is -1 */ + if (bytes_to_decode < 0) + bytes_to_decode = 0; + + /* make one big value out of the partial values */ + triple_value = char_value[0]; + triple_value *= 64; + triple_value += char_value[1]; + triple_value *= 64; + triple_value += char_value[2]; + triple_value *= 64; + triple_value += char_value[3]; + + /* break the big value into bytes */ + for (i=bytes_to_decode; i<3; i++) { + triple_value /= 256; + } + + for (i=bytes_to_decode-1; i>=0; i--) { + result[i] = triple_value%256; + triple_value /= 256; + } + + return bytes_to_decode; +} + +/* encode an array of bytes using base64 */ +int base64_lencode(char *source, size_t sourcelen, char *target, size_t targetlen) +{ + /* check if the result will fit in the target buffer */ + if ((sourcelen+2)/3*4 > targetlen-1) + return 0; + + /* encode all full triples */ + while (sourcelen >= 3) { + s_base64_encode_triple((unsigned char*)source, (unsigned char*)target); + sourcelen -= 3; + source += 3; + target += 4; + } + + /* encode the last one or two characters */ + if (sourcelen > 0) { + unsigned char temp[3]; + memset(temp, 0, sizeof(temp)); + memcpy(temp, source, sourcelen); + s_base64_encode_triple((unsigned char*)temp, (unsigned char*)target); + target[3] = '='; + if (sourcelen == 1) + target[2] = '='; + + target += 4; + } + + /* terminate the string */ + target[0] = 0; + + return 1; +} + +/* decode base64 encoded data */ +size_t base64_ldecode(char *source, char *target, size_t targetlen) +{ + char *src, *tmpptr; + char quadruple[4], tmpresult[3]; + int i, tmplen = 3; + size_t converted = 0; + + /* concatinate '===' to the source to handle unpadded base64 data */ + src = malloc(strlen(source)+5); + if (!src) + return -1; + strcpy(src, source); + strcat(src, "===="); + tmpptr = src; + + /* convert as long as we get a full result */ + while (tmplen == 3) { + /* get 4 characters to convert */ + for (i=0; i<4; i++) { + /* skip invalid characters - we won't reach the end */ + while (*tmpptr != '=' && s_base64_char_value(*tmpptr)<0) { + tmpptr++; + } + + quadruple[i] = *(tmpptr++); + } + + /* convert the characters */ + tmplen = s_base64_decode_triple((unsigned char*)quadruple, (unsigned char*)tmpresult); + + /* check if the fit in the result buffer */ + if (targetlen < tmplen) { + free(src); + return -1; + } + + /* put the partial result in the result buffer */ + memcpy(target, tmpresult, tmplen); + target += tmplen; + targetlen -= tmplen; + converted += tmplen; + } + + free(src); + return converted; +} diff --git a/src/environment.cpp b/src/environment.cpp index a0b1060..7b799e3 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -41,6 +41,8 @@ #include "server.h" #include "client.h" +#include "nvp.h" + #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" Environment::Environment(): @@ -50,16 +52,23 @@ Environment::Environment(): m_time_of_day_speed(0), m_time_counter(0) { + m_players = array_create(ARRAY_TYPE_PTR); } Environment::~Environment() { // Deallocate players - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - delete (*i); + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + array_set_ptr(m_players,NULL,i); + delete player; } + + array_free(m_players,1); } void Environment::addPlayer(Player *player) @@ -76,36 +85,41 @@ void Environment::addPlayer(Player *player) // Name has to be unique. if (getPlayer(player->getName()) != NULL) return; - // Add. - m_players.push_back(player); + + array_insert_ptr(m_players,player); } void Environment::removePlayer(u16 peer_id) { DSTACK(__FUNCTION_NAME); -re_search: - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - if(player->peer_id != peer_id) - continue; + Player *player; + uint32_t i; + int k; - delete player; - m_players.erase(i); - // See if there is an another one - // (shouldn't be, but just to be sure) - goto re_search; - } + do { + k = 0; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + if (player->peer_id != peer_id) + continue; + array_set_ptr(m_players,NULL,i); + delete player; + k = 1; + } + } while (k > 0); } Player * Environment::getPlayer(u16 peer_id) { - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - if(player->peer_id == peer_id) + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + if (player->peer_id == peer_id) return player; } return NULL; @@ -113,11 +127,13 @@ Player * Environment::getPlayer(u16 peer_id) Player * Environment::getPlayer(const char *name) { - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - if(strcmp(player->getName(), name) == 0) + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + if (!strcmp(player->getName(), name)) return player; } return NULL; @@ -125,36 +141,26 @@ Player * Environment::getPlayer(const char *name) Player * Environment::getRandomConnectedPlayer() { - core::list connected_players = getPlayers(true); - u32 chosen_one = myrand() % connected_players.size(); - u32 j = 0; - for(core::list::Iterator - i = connected_players.begin(); - i != connected_players.end(); i++) - { - if(j == chosen_one) - { - Player *player = *i; - return player; - } - j++; - } - return NULL; + array_t *connected_players = getPlayers(true); + uint32_t i = myrand() % connected_players->length; + Player *r = (Player*)array_get_ptr(connected_players,i); + array_free(connected_players,1); + return r; } Player * Environment::getNearestConnectedPlayer(v3f pos) { - core::list connected_players = getPlayers(true); - f32 nearest_d = 0; + array_t *connected_players = getPlayers(true); + float nearest_d = 0; Player *nearest_player = NULL; - for(core::list::Iterator - i = connected_players.begin(); - i != connected_players.end(); i++) - { - Player *player = *i; - f32 d = player->getPosition().getDistanceFrom(pos); - if(d < nearest_d || nearest_player == NULL) - { + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(connected_players,i); + if (!player) + continue; + float d = player->getPosition().getDistanceFrom(pos); + if (d < nearest_d || nearest_player == NULL) { nearest_d = d; nearest_player = player; } @@ -162,28 +168,28 @@ Player * Environment::getNearestConnectedPlayer(v3f pos) return nearest_player; } -core::list Environment::getPlayers() +array_t *Environment::getPlayers() { return m_players; } -core::list Environment::getPlayers(bool ignore_disconnected) +array_t *Environment::getPlayers(bool ignore_disconnected) { - core::list newlist; - for(core::list::Iterator - i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; + array_t *newlist; + uint32_t i; + Player *player; - if(ignore_disconnected) - { - // Ignore disconnected players - if(player->peer_id == 0) - continue; - } + newlist = array_create(ARRAY_TYPE_PTR); - newlist.push_back(player); + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + + if (ignore_disconnected && player->peer_id == 0) + continue; + + array_push_ptr(newlist,player); } return newlist; } @@ -191,10 +197,12 @@ core::list Environment::getPlayers(bool ignore_disconnected) void Environment::printPlayers(std::ostream &o) { o<<"Players in environment:"<::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; + uint32_t i; + Player *player; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; o<<"Player peer_id="<peer_id< saved_players; + nvp_t *saved_players = NULL; std::vector player_files = fs::GetDirListing(players_path); - for (u32 i=0; iserialize(os); - saved_players.insert(player, true); + nvp_set(&saved_players, (char*)player->getName(), (char*)player->getName(), player); } } - for (core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { - Player *player = *i; - if (saved_players.find(player) != NULL) + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; + if (nvp_get(&saved_players, (char*)player->getName()) != NULL) continue; std::string playername = player->getName(); // Don't save unnamed player @@ -412,11 +424,12 @@ void ServerEnvironment::serializePlayers(const std::string &savedir) continue; } player->serialize(os); - saved_players.insert(player, true); + nvp_set(&saved_players, (char*)player->getName(), (char*)player->getName(), player); } } - //infostream<<"Saved "<::Iterator i = m_players.begin(); i != m_players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; // Ignore disconnected players if (player->peer_id == 0) @@ -1113,8 +1130,12 @@ void ServerEnvironment::step(float dtime) } // wake up addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),""); - for (core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; // Ignore disconnected players if (player->peer_id == 0) @@ -1131,8 +1152,12 @@ void ServerEnvironment::step(float dtime) }else if (m_players_sleeping) { // wake up addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),""); - for (core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; // Ignore disconnected players if (player->peer_id == 0) @@ -4106,8 +4131,12 @@ void ClientEnvironment::step(float dtime) /* Stuff that can be done in an arbitarily large dtime */ - for (core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; v3f playerpos = player->getPosition(); /* @@ -4455,10 +4484,12 @@ void ClientEnvironment::updateObjectsCameraOffset(v3s16 camera_offset) obj->updateCameraOffset(camera_offset); } - for (core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(m_players,i); + if (!player) + continue; if (!player->isLocal()) ((RemotePlayer*)player)->updateCameraOffset(camera_offset); } diff --git a/src/environment.h b/src/environment.h index 8a6216e..fcfa347 100644 --- a/src/environment.h +++ b/src/environment.h @@ -48,6 +48,8 @@ #include "utility.h" #include "activeobject.h" +#include "array.h" + class Server; class ServerActiveObject; @@ -142,8 +144,8 @@ public: Player * getPlayer(const char *name); Player * getRandomConnectedPlayer(); Player * getNearestConnectedPlayer(v3f pos); - core::list getPlayers(); - core::list getPlayers(bool ignore_disconnected); + array_t *getPlayers(); + array_t *getPlayers(bool ignore_disconnected); void printPlayers(std::ostream &o); virtual bool propogateEnergy(u8 level, v3s16 powersrc, v3s16 signalsrc, v3s16 pos, core::map &modified_blocks) {return false;}; @@ -216,7 +218,7 @@ public: protected: // peer_ids in here should be unique, except that there may be many 0s - core::list m_players; + array_t *m_players; u32 m_time; // Time of day in milli-hours (0-23999); determines day and night u32 m_time_of_day; diff --git a/src/http.cpp b/src/http.cpp index b26e49d..cb801cd 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -211,18 +211,20 @@ int HTTPRemoteClient::handlePlayer() /* player list */ std::string u1 = m_recv_headers.getUrl(1); if (u1 == "" || u1.substr(0,5) == "page-") { - core::list players = m_server->getGameServer()->getPlayers(); + array_t *players = m_server->getGameServer()->getPlayers(); + Player *player; + uint32_t i; std::string html("

Players

\n"); std::string pagination(""); int player_skip = 0; - if (players.size() > 50) { + if (players->length > 50) { int current_page = 1; if (u1.substr(0,5) == "page-") { current_page = mystoi(u1.substr(5)); if (current_page < 1) current_page = 1; } - int total_pages = (players.size()/50)+1; + int total_pages = (players->length/50)+1; if (total_pages < 1) total_pages = 1; if (current_page > total_pages) @@ -240,12 +242,14 @@ int HTTPRemoteClient::handlePlayer() } html += pagination; int p = 0; - for (core::list::Iterator i = players.begin(); i != players.end(); i++,p++) { + for (i=0; ilength; i++,p++) { if (p < player_skip) continue; if (p > player_skip+50) break; - Player *player = *i; + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; html += http_player_interface(player,m_server,false); } html += pagination; @@ -331,15 +335,20 @@ int HTTPRemoteClient::handleAPI() send((char*)txt.c_str()); return 1; }else if (u1 == "players") { - core::list players = m_server->getGameServer()->getPlayers(true); - std::string txt = itos(players.size())+"\n"; + array_t *players = m_server->getGameServer()->getPlayers(true); + std::string txt = itos(players->length)+"\n"; int c = 0; - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; if (c++) txt += ", "; txt += player->getName(); } + array_free(players,1); send((char*)txt.c_str()); return 1; }else if (u1 == "public") { @@ -365,9 +374,13 @@ int HTTPRemoteClient::handleIndex() html += "

Version: "; html += VERSION_STRING; html += "
Players: "; - core::list players = m_server->getGameServer()->getPlayers(true); - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *player = *i; + array_t *players = m_server->getGameServer()->getPlayers(true); + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; if (c++) html += ", "; html += "getName(); html += ""; } + array_free(players,1); html += ""; sendHTML((char*)html.c_str()); return 1; diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..4341aee --- /dev/null +++ b/src/list.c @@ -0,0 +1,255 @@ +/************************************************************************ +* list.c +* tausaga - environmental survival game +* Copyright (C) Lisa 'darkrose' Milne 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +************************************************************************/ + +#include "list.h" + +#include + +/* comparison functions: + * return 0 to insert + * return 1 to insert later + * return -1 to not insert at all + */ +static int list_cmp_default(void *e1, void *e2) +{ + return ((*((int*)((ref_t*)e1)->ref))<(*((int*)((ref_t*)e2)->ref))); +} + +/* get the element count in a list */ +int list_count(void *list) +{ + int c = 0; + ref_t *l = *((ref_t**)list); + + while (l) { + l = l->next; + } + + return c; +} + +/* get the last element in a list */ +void *list_last(void *list) +{ + ref_t *l = *((ref_t**)list); + if (l) { + while (l->next) { + l = l->next; + } + } + + return l; +} + +/* push an element onto a list */ +void *list_push(void *list, void *el) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + + if (l) { + while (l->next) { + l = l->next; + } + l->next = e; + e->prev = l; + e->next = NULL; + return *((ref_t**)list); + } + + *((ref_t**)list) = e; + e->next = NULL; + e->prev = NULL; + + return e; +} + +/* append a list to another list */ +void *list_append(void *list, void *el) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + + if (l) { + while (l->next) { + l = l->next; + } + l->next = e; + e->prev = l; + return *((ref_t**)list); + } + + *((ref_t**)list) = e; + e->prev = NULL; + + return e; +} + +/* shove an element onto the start of a list */ +void *list_shove(void *list, void *el) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + + if (l) + l->prev = e; + + *((ref_t**)list) = e; + e->next = l; + e->prev = NULL; + + return e; +} + +/* remove an element form a list */ +void *list_remove(void *list, void *el) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + + if (!e->prev) { + *(ref_t**)list = e->next; + l = *((ref_t**)list); + if (l) + l->prev = NULL; + + return l; + } + + e->prev->next = e->next; + if (e->next) + e->next->prev = e->prev; + + return l; +} + +/* remove the last element from a list */ +void *list_pop(void *list) +{ + ref_t *e = *((ref_t**)list); + + if (!e) + return NULL; + + while (e->next) { + e = e->next; + } + + if (e->prev) { + e->prev->next = e->next; + }else{ + *((ref_t**)list) = e->next; + } + + if (e->next) + e->next->prev = e->prev; + + return e; +} + +/* remove the first element from a list */ +void *list_pull(void *list) +{ + ref_t *e = *((ref_t**)list); + + if (!e) + return NULL; + + *((ref_t**)list) = e->next; + if (*((ref_t**)list)) + e->next->prev = NULL; + + return e; +} + +/* insert an element into a list before ne */ +void *list_insert(void *list, void *el, void *ne) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + ref_t *n = ne; + + if (n == l || !n) + return list_shove(list,el); + + e->prev = n->prev; + e->next = n; + n->prev = e; + + return l; +} + +/* insert an element into a list based on a compare function - return 1 to insert before */ +void *list_insert_cmp(void *list, void *el, int (*list_cmp)(void *e1, void *e2)) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = el; + ref_t *p = l; + ref_t *r = NULL; + int c; + + if (!l) + return list_push(list,el); + + if (!list_cmp) + list_cmp = list_cmp_default; + + ((ref_t*)el)->next = NULL; + ((ref_t*)el)->prev = NULL; + + while (p && (c = list_cmp(e,p) > 0)) { + r = p; + p = p->next; + } + + if (c < 0) + return l; + + if (!r) + return list_shove(list,el); + + e->prev = r; + e->next = r->next; + r->next = e; + if (e->next) + e->next->prev = e; + + return l; +} + +/* resort a list, based on a compare function */ +void *list_resort_cmp(void *list, int (*list_cmp)(void *e1, void* e2)) +{ + ref_t *l = *((ref_t**)list); + ref_t *e = l; + ref_t *n; + + l = NULL; + + if (!list_cmp) + list_cmp = list_cmp_default; + + while (e) { + n = e->next; + l = list_insert_cmp(&l,e,list_cmp); + e = n; + } + + return l; +} diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..520fa34 --- /dev/null +++ b/src/list.h @@ -0,0 +1,34 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _HAVE_REF_TYPE +#define _HAVE_REF_TYPE +typedef struct ref_s { + struct ref_s *prev; + struct ref_s *next; + void *ref; +} ref_t; +#endif + +/* defined in list.c */ +int list_count(void *list); +void *list_last(void *list); +void *list_push(void *list, void *el); +void *list_append(void *list, void *el); +void *list_shove(void *list, void *el); +void *list_remove(void *list, void *el); +void *list_pop(void *list); +void *list_pull(void *list); +void *list_insert(void *list, void *el, void *n); +void *list_insert_cmp(void *list, void *el, int (*list_cmp)(void *e1, void *e2)); +void *list_resort_cmp(void *list, int (*list_cmp)(void *e1, void* e2)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/nvp.c b/src/nvp.c new file mode 100644 index 0000000..0ed9e05 --- /dev/null +++ b/src/nvp.c @@ -0,0 +1,170 @@ +/************************************************************************ +* nvp.c +* tausaga - environmental survival game +* Copyright (C) Lisa 'darkrose' Milne 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +************************************************************************/ + +#include "list.h" +#include "nvp.h" +#include "crypto.h" + +#include +#include +#include + +/* comparison functions: + * return 0 to insert + * return 1 to insert later + * return -1 to not insert at all + */ +static int nvp_insert_cmp(void *e1, void *e2) +{ + nvp_t *n1 = e1; + nvp_t *n2 = e2; + + if (n2->h > n1->h) + return 0; + return 1; +} + +/* free memory of an nvp list, if data is non-zero, data is also freed */ +void nvp_free(nvp_t **list, int data) +{ + nvp_t *n; + while ((n = list_pop(list))) { + if (n->name) + free(n->name); + if (n->value) + free(n->value); + if (data && n->data) + free(n->data); + } +} + +/* get a name/value pair */ +nvp_t *nvp_get(nvp_t **list, char* name) +{ + nvp_t *c = *list; + unsigned int h = hash(name); + while (c) { + if (c->h > h) + return NULL; + if (c->h == h && !strcmp(c->name,name)) + return c; + c = c->next; + } + return NULL; +} + +/* get the value of a name/value pair */ +char* nvp_get_str(nvp_t **list, char* name) +{ + nvp_t *c = nvp_get(list,name); + if (c) + return c->value; + return NULL; +} + +/* get the value of a name/value pair as an int value */ +int nvp_get_int(nvp_t **list, char* name) +{ + nvp_t *c = nvp_get(list,name); + if (c) + return strtol(c->value,NULL,10); + return 0; +} + +/* get the value of a name/value pair as a float value */ +float nvp_get_float(nvp_t **list, char* name) +{ + nvp_t *c = nvp_get(list,name); + if (c) + return strtof(c->value,NULL); + return 0.0; +} + +/* get the value of a name/value pair as a boolean value */ +int nvp_get_bool(nvp_t **list, char* name) +{ + nvp_t *c = nvp_get(list,name); + if (c && (!strcmp(c->value,"1") || !strcmp(c->value,"true"))) + return 1; + return 0; +} + +/* get a name/value pair's data value */ +void *nvp_get_data(nvp_t **list, char* name) +{ + nvp_t *c = nvp_get(list,name); + if (c) + return c->data; + return NULL; +} + +/* set the value of a name/value pair */ +void nvp_set(nvp_t **list, char* name, char* value, void *data) +{ + nvp_t *c = *list; + unsigned int h = hash(name); + + while (c) { + if (c->h > h) + break; + if (c->h == h && !strcmp(c->name,name)) { + if (c->value) { + free(c->value); + c->value = NULL; + } + if (value) + c->value = strdup(value); + if (data) + c->data = data; + return; + } + c = c->next; + } + + if (!value && !data) + return; + + c = malloc(sizeof(nvp_t)); + c->name = strdup(name); + c->h = h; + if (value) { + c->value = strdup(value); + }else{ + c->value = NULL; + } + c->data = data; + + *list = list_insert_cmp(list,c,nvp_insert_cmp); +} + +/* set a name/value pair to an int value */ +void nvp_set_int(nvp_t **list, char* name, int value) +{ + char str[20]; + sprintf(str,"%d",value); + nvp_set(list,name,str,NULL); +} + +/* set a name/value pair to a float value */ +void nvp_set_float(nvp_t **list, char* name, float value) +{ + char str[20]; + sprintf(str,"%f",value); + nvp_set(list,name,str,NULL); +} diff --git a/src/nvp.h b/src/nvp.h new file mode 100644 index 0000000..f67c204 --- /dev/null +++ b/src/nvp.h @@ -0,0 +1,36 @@ +#ifndef _NVP_H_ +#define _NVP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _HAVE_NVP_TYPE +#define _HAVE_NVP_TYPE +typedef struct nvp_s { + struct nvp_s *prev; + struct nvp_s *next; + char* name; + unsigned int h; + char* value; + void *data; +} nvp_t; +#endif + +/* defined in nvp.c */ +void nvp_free(nvp_t **list, int data); +nvp_t *nvp_get(nvp_t **list, char* name); +char* nvp_get_str(nvp_t **list, char* name); +int nvp_get_int(nvp_t **list, char* name); +float nvp_get_float(nvp_t **list, char* name); +int nvp_get_bool(nvp_t **list, char* name); +void *nvp_get_data(nvp_t **list, char* name); +void nvp_set(nvp_t **list, char* name, char* value, void *data); +void nvp_set_int(nvp_t **list, char* name, int value); +void nvp_set_float(nvp_t **list, char* name, float value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/server.cpp b/src/server.cpp index 619fbd1..3620ed2 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4858,16 +4858,16 @@ core::list Server::getPlayerInfo() core::list list; - core::list players = m_env.getPlayers(); + array_t *players = m_env.getPlayers(); - core::list::Iterator i; - for(i = players.begin(); - i != players.end(); i++) - { + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; PlayerInfo info; - Player *player = *i; - try{ // Copy info from connection to info struct info.id = player->peer_id; @@ -5004,19 +5004,23 @@ void Server::SendPlayerInfo(float dtime) os.write((char*)buf, 2); // Get connected players - core::list players = m_env.getPlayers(true); + array_t *players = m_env.getPlayers(true); // players ignore their own data, so don't bother sending for one player - if (players.size() < 2) + if (players->length < 2) return; // Write player count - u16 playercount = players.size(); + u16 playercount = players->length; writeU16(buf, playercount); os.write((char*)buf, 2); - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - ServerRemotePlayer *player = (ServerRemotePlayer*)(*i); + ServerRemotePlayer *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (ServerRemotePlayer*)array_get_ptr(players,i); + if (!player) + continue; writeU16(os, player->peer_id); writeV3F1000(os, player->getPosition()); @@ -5027,6 +5031,8 @@ void Server::SendPlayerInfo(float dtime) writeU16(os, player->pointed_id); } + array_free(players,1); + // Make data buffer std::string s = os.str(); SharedBuffer data((u8*)s.c_str(), s.size()); @@ -5039,17 +5045,21 @@ void Server::SendPlayerData() DSTACK(__FUNCTION_NAME); // Get connected players - core::list players = m_env.getPlayers(true); + array_t *players = m_env.getPlayers(true); std::ostringstream os(std::ios_base::binary); writeU16(os, TOCLIENT_PLAYERDATA); - writeU16(os,(u16)players.size()); + writeU16(os,(u16)players->length); // this is the number of serialized strings sent below writeU16(os,1); char name[PLAYERNAME_SIZE]; - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *player = *i; + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; writeU16(os, player->peer_id); memset(name, 0, PLAYERNAME_SIZE); @@ -5059,6 +5069,8 @@ void Server::SendPlayerData() // serialized strings can be added here } + array_free(players,1); + std::string s = os.str(); SharedBuffer data((u8*)s.c_str(), s.size()); @@ -5127,15 +5139,21 @@ void Server::SendPlayerItems() DSTACK(__FUNCTION_NAME); std::ostringstream os(std::ios_base::binary); - core::list players = m_env.getPlayers(true); + array_t *players = m_env.getPlayers(true); writeU16(os, TOCLIENT_PLAYERITEMS); - writeU16(os, players.size()); + writeU16(os, players->length); writeU16(os, 8); - for (core::list::Iterator i = players.begin(); i != players.end(); i++) { - Player *p = *i; - writeU16(os, p->peer_id); - InventoryItem *item = (InventoryItem*)p->getWieldItem(); + + Player *player; + uint32_t i; + for (i=0; ilength; i++) { + player = (Player*)array_get_ptr(players,i); + if (!player) + continue; + + writeU16(os, player->peer_id); + InventoryItem *item = (InventoryItem*)player->getWieldItem(); if (item == NULL) { writeU16(os,CONTENT_IGNORE); }else{ @@ -5143,7 +5161,7 @@ void Server::SendPlayerItems() } const char* list[7] = {"hat","shirt","pants","boots","decorative","jacket","belt"}; for (int j=0; j<7; j++) { - InventoryList *l = p->inventory.getList(list[j]); + InventoryList *l = player->inventory.getList(list[j]); if (l == NULL) continue; InventoryItem *itm = l->getItem(0); @@ -5155,6 +5173,8 @@ void Server::SendPlayerItems() } } + array_free(players,1); + // Make data buffer std::string s = os.str(); SharedBuffer data((u8*)s.c_str(), s.size()); diff --git a/src/server.h b/src/server.h index 57f1b03..c8e3554 100644 --- a/src/server.h +++ b/src/server.h @@ -444,8 +444,8 @@ public: bool userExists(const char *name) {return m_authmanager.exists(name);} Player *getPlayer(std::string name) {return m_env.getPlayer(name.c_str());} - core::list getPlayers() {return m_env.getPlayers();} - core::list getPlayers(bool ign_disconnected) {return m_env.getPlayers(ign_disconnected);} + array_t *getPlayers() {return m_env.getPlayers();} + array_t *getPlayers(bool ign_disconnected) {return m_env.getPlayers(ign_disconnected);} uint64_t getPlayerPrivs(Player *player);