forked from oerkki/voxelands
sane code pt1
This commit is contained in:
parent
e3c50924a6
commit
221f079fe0
|
@ -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
|
||||
|
|
|
@ -0,0 +1,807 @@
|
|||
/************************************************************************
|
||||
* array.c
|
||||
* tausaga - environmental survival game
|
||||
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
************************************************************************/
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
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; i<a->length; i++) {
|
||||
array_push_string(r,((char**)(a->data))[i]);
|
||||
}
|
||||
break;
|
||||
case ARRAY_TYPE_FLOAT:
|
||||
for (i=0; i<a->length; i++) {
|
||||
array_push_float(r,((float*)(a->data))[i]);
|
||||
}
|
||||
break;
|
||||
case ARRAY_TYPE_INT:
|
||||
for (i=0; i<a->length; i++) {
|
||||
array_push_int(r,((uint32_t*)(a->data))[i]);
|
||||
}
|
||||
break;
|
||||
case ARRAY_TYPE_PTR:
|
||||
for (i=0; i<a->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a1->length; 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; i<a->length; 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; k<l; k++) {
|
||||
p[k] = 0;
|
||||
}
|
||||
a->data = 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; k<l; k++) {
|
||||
p[k] = 0.0;
|
||||
}
|
||||
a->data = 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; k<l; k++) {
|
||||
p[k] = NULL;
|
||||
}
|
||||
a->data = 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; k<l; k++) {
|
||||
p[k] = NULL;
|
||||
}
|
||||
a->data = 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; i<a->length; 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; i<a->length; 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; i<a->length; 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; i<a->length; 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; i<a->length; 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; i<a->length; i++) {
|
||||
if (!strcmp(p[i],v)) {
|
||||
free(p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
a->length--;
|
||||
for (; i<a->length; 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; i<a->length; i++) {
|
||||
l += strlen(((char**)(a->data))[i])+gl;
|
||||
}
|
||||
if (l) {
|
||||
str = malloc(l+1);
|
||||
str[0] = 0;
|
||||
for (i=start; i<a->length; i++) {
|
||||
if (i > start)
|
||||
strcat(str,glue);
|
||||
strcat(str,((char**)(a->data))[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef _ARRAY_H_
|
||||
#define _ARRAY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
|
@ -153,6 +153,7 @@ GUICharDefMenu::~GUICharDefMenu()
|
|||
|
||||
void GUICharDefMenu::removeChildren()
|
||||
{
|
||||
/* irrlicht internal */
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i != children.end(); i++) {
|
||||
|
|
|
@ -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<QueuedMeshUpdate*>::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<QueuedMeshUpdate*>::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<QueuedMeshUpdate*>::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<u16> players_alive;
|
||||
array_t players_alive;
|
||||
array_init(&players_alive,ARRAY_TYPE_INT);
|
||||
for (u16 i=0; i<player_count; i++) {
|
||||
u16 peer_id = readU16(is);
|
||||
|
||||
players_alive.push_back(peer_id);
|
||||
array_push_int(&players_alive,peer_id);
|
||||
|
||||
is.read(pname,PLAYERNAME_SIZE);
|
||||
pname[PLAYERNAME_SIZE-1] = '\0';
|
||||
chardef = deSerializeString(is);
|
||||
|
@ -965,30 +965,25 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
Remove those players from the environment that
|
||||
weren't listed by the server.
|
||||
*/
|
||||
core::list<Player*> players = m_env.getPlayers();
|
||||
core::list<Player*>::Iterator ip;
|
||||
for (ip=players.begin(); ip!=players.end(); ip++) {
|
||||
array_t *players = m_env.getPlayers();
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<players->length; 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"<<std::endl;
|
||||
|
||||
bool is_alive = false;
|
||||
core::list<u16>::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
|
||||
<<std::endl;
|
||||
m_env.removePlayer((*ip)->peer_id);
|
||||
infostream<<"Removing dead player "<<player->peer_id<<std::endl;
|
||||
m_env.removePlayer(player->peer_id);
|
||||
}
|
||||
} //envlock
|
||||
}
|
||||
|
|
10
src/client.h
10
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<QueuedMeshUpdate*> m_queue;
|
||||
QueuedMeshUpdate* m_queue;
|
||||
JMutex m_mutex;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "nodemetadata.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
#include "array.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> 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<Player*> players = m_env->getPlayers(true);
|
||||
for (core::list<Player*>::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; i<players->length; 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<Player*> players = m_env->getPlayers(true);
|
||||
for (core::list<Player*>::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; i<players->length; 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 != "") {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/************************************************************************
|
||||
* crypto.c
|
||||
* tausaga - environmental survival game
|
||||
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
************************************************************************/
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t hash(char* str);
|
||||
char* base64_encode(char* str);
|
||||
char* base64_decode(char* str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,203 @@
|
|||
/************************************************************************
|
||||
* crypto_base64.c
|
||||
* tausaga - environmental survival game
|
||||
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
************************************************************************/
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
delete (*i);
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; 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<Player*>::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;
|
||||
|
||||
do {
|
||||
k = 0;
|
||||
for (i=0; i<m_players->length; 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;
|
||||
m_players.erase(i);
|
||||
// See if there is an another one
|
||||
// (shouldn't be, but just to be sure)
|
||||
goto re_search;
|
||||
k = 1;
|
||||
}
|
||||
} while (k > 0);
|
||||
}
|
||||
|
||||
Player * Environment::getPlayer(u16 peer_id)
|
||||
{
|
||||
for(core::list<Player*>::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; i<m_players->length; 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<Player*>::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; i<m_players->length; 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<Player*> connected_players = getPlayers(true);
|
||||
u32 chosen_one = myrand() % connected_players.size();
|
||||
u32 j = 0;
|
||||
for(core::list<Player*>::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<Player*> 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<Player*>::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; i<connected_players->length; 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<Player*> Environment::getPlayers()
|
||||
array_t *Environment::getPlayers()
|
||||
{
|
||||
return m_players;
|
||||
}
|
||||
|
||||
core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
||||
array_t *Environment::getPlayers(bool ignore_disconnected)
|
||||
{
|
||||
core::list<Player*> newlist;
|
||||
for(core::list<Player*>::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)
|
||||
newlist = array_create(ARRAY_TYPE_PTR);
|
||||
|
||||
for (i=0; i<m_players->length; i++) {
|
||||
player = (Player*)array_get_ptr(m_players,i);
|
||||
if (!player)
|
||||
continue;
|
||||
}
|
||||
|
||||
newlist.push_back(player);
|
||||
if (ignore_disconnected && player->peer_id == 0)
|
||||
continue;
|
||||
|
||||
array_push_ptr(newlist,player);
|
||||
}
|
||||
return newlist;
|
||||
}
|
||||
|
@ -191,10 +197,12 @@ core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
|||
void Environment::printPlayers(std::ostream &o)
|
||||
{
|
||||
o<<"Players in environment:"<<std::endl;
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
uint32_t i;
|
||||
Player *player;
|
||||
for (i=0; i<m_players->length; i++) {
|
||||
player = (Player*)array_get_ptr(m_players,i);
|
||||
if (!player)
|
||||
continue;
|
||||
o<<"Player peer_id="<<player->peer_id<<std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -327,11 +335,13 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
{
|
||||
std::string players_path = savedir + "/players";
|
||||
fs::CreateDir(players_path);
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
|
||||
core::map<Player*, bool> saved_players;
|
||||
nvp_t *saved_players = NULL;
|
||||
|
||||
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
|
||||
for (u32 i=0; i<player_files.size(); i++) {
|
||||
for (i=0; i<player_files.size(); i++) {
|
||||
if (player_files[i].dir)
|
||||
continue;
|
||||
|
||||
|
@ -354,7 +364,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
|
||||
// Search for the player
|
||||
std::string playername = testplayer.getName();
|
||||
Player *player = getPlayer(playername.c_str());
|
||||
player = getPlayer(playername.c_str());
|
||||
if (player == NULL) {
|
||||
fs::RecursiveDelete(path);
|
||||
continue;
|
||||
|
@ -371,13 +381,15 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
for (core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) {
|
||||
Player *player = *i;
|
||||
if (saved_players.find(player) != NULL)
|
||||
for (i=0; i<m_players->length; 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 "<<saved_players.size()<<" players."<<std::endl;
|
||||
nvp_free(&saved_players,0);
|
||||
|
||||
}
|
||||
|
||||
void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
|
@ -1041,8 +1054,12 @@ void ServerEnvironment::step(float dtime)
|
|||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
|
||||
int pc = 0;
|
||||
for (core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; 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<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; 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<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; 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<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; 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<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<m_players->length; i++) {
|
||||
player = (Player*)array_get_ptr(m_players,i);
|
||||
if (!player)
|
||||
continue;
|
||||
if (!player->isLocal())
|
||||
((RemotePlayer*)player)->updateCameraOffset(camera_offset);
|
||||
}
|
||||
|
|
|
@ -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<Player*> getPlayers();
|
||||
core::list<Player*> 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<v3s16,MapBlock*> &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<Player*> 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;
|
||||
|
|
38
src/http.cpp
38
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<Player*> players = m_server->getGameServer()->getPlayers();
|
||||
array_t *players = m_server->getGameServer()->getPlayers();
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
std::string html("<h1>Players</h1>\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<Player*>::Iterator i = players.begin(); i != players.end(); i++,p++) {
|
||||
for (i=0; i<players->length; 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<Player*> 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<Player*>::Iterator i = players.begin(); i != players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<players->length; 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 += "</h2><p><strong>Version: </strong>";
|
||||
html += VERSION_STRING;
|
||||
html += "<br /><strong><a href=\"/player\" class=\"secret\">Players</a>: </strong>";
|
||||
core::list<Player*> players = m_server->getGameServer()->getPlayers(true);
|
||||
for (core::list<Player*>::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; i<players->length; i++) {
|
||||
player = (Player*)array_get_ptr(players,i);
|
||||
if (!player)
|
||||
continue;
|
||||
if (c++)
|
||||
html += ", ";
|
||||
html += "<a href=\"/player/";
|
||||
|
@ -376,6 +389,7 @@ int HTTPRemoteClient::handleIndex()
|
|||
html += player->getName();
|
||||
html += "</a>";
|
||||
}
|
||||
array_free(players,1);
|
||||
html += "</div>";
|
||||
sendHTML((char*)html.c_str());
|
||||
return 1;
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/************************************************************************
|
||||
* list.c
|
||||
* tausaga - environmental survival game
|
||||
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
************************************************************************/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,170 @@
|
|||
/************************************************************************
|
||||
* nvp.c
|
||||
* tausaga - environmental survival game
|
||||
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
************************************************************************/
|
||||
|
||||
#include "list.h"
|
||||
#include "nvp.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -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
|
|
@ -4858,16 +4858,16 @@ core::list<PlayerInfo> Server::getPlayerInfo()
|
|||
|
||||
core::list<PlayerInfo> list;
|
||||
|
||||
core::list<Player*> players = m_env.getPlayers();
|
||||
array_t *players = m_env.getPlayers();
|
||||
|
||||
core::list<Player*>::Iterator i;
|
||||
for(i = players.begin();
|
||||
i != players.end(); i++)
|
||||
{
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<players->length; 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<Player*> 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<Player*>::Iterator i = players.begin(); i != players.end(); i++) {
|
||||
ServerRemotePlayer *player = (ServerRemotePlayer*)(*i);
|
||||
ServerRemotePlayer *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<players->length; 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<u8> data((u8*)s.c_str(), s.size());
|
||||
|
@ -5039,17 +5045,21 @@ void Server::SendPlayerData()
|
|||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// Get connected players
|
||||
core::list<Player*> 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<Player*>::Iterator i = players.begin(); i != players.end(); i++) {
|
||||
Player *player = *i;
|
||||
Player *player;
|
||||
uint32_t i;
|
||||
for (i=0; i<players->length; 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<u8> 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<Player *> 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<Player *>::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; i<players->length; 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<u8> data((u8*)s.c_str(), s.size());
|
||||
|
|
|
@ -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<Player*> getPlayers() {return m_env.getPlayers();}
|
||||
core::list<Player*> 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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue