sane code pt1

This commit is contained in:
darkrose 2017-03-28 18:42:12 +10:00
parent e3c50924a6
commit 221f079fe0
19 changed files with 1953 additions and 178 deletions

View File

@ -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

807
src/array.c Normal file
View File

@ -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;
}

68
src/array.h Normal file
View File

@ -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

View File

@ -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++) {

View File

@ -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
}

View File

@ -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;
};

View File

@ -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 != "") {

98
src/crypto.c Normal file
View File

@ -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;
}

18
src/crypto.h Normal file
View File

@ -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

203
src/crypto_base64.c Normal file
View File

@ -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;
}

View File

@ -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;
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; 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;
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)
continue;
}
newlist = array_create(ARRAY_TYPE_PTR);
newlist.push_back(player);
for (i=0; i<m_players->length; 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<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);
}

View File

@ -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;

View File

@ -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;

255
src/list.c Normal file
View File

@ -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;
}

34
src/list.h Normal file
View File

@ -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

170
src/nvp.c Normal file
View File

@ -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);
}

36
src/nvp.h Normal file
View File

@ -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

View File

@ -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());

View File

@ -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);