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 set(common_SRCS
array.c
list.c
nvp.c
crypto.c
crypto_base64.c
log.cpp log.cpp
content_sao.cpp content_sao.cpp
mapgen.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() void GUICharDefMenu::removeChildren()
{ {
/* irrlicht internal */
const core::list<gui::IGUIElement*> &children = getChildren(); const core::list<gui::IGUIElement*> &children = getChildren();
core::list<gui::IGUIElement*> children_copy; core::list<gui::IGUIElement*> children_copy;
for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i != children.end(); i++) { 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_craftitem.h"
#include "content_mob.h" #include "content_mob.h"
#include "array.h"
/* /*
QueuedMeshUpdate QueuedMeshUpdate
*/ */
@ -58,7 +60,7 @@ QueuedMeshUpdate::QueuedMeshUpdate():
QueuedMeshUpdate::~QueuedMeshUpdate() QueuedMeshUpdate::~QueuedMeshUpdate()
{ {
if(data) if (data)
delete data; delete data;
} }
@ -68,18 +70,18 @@ QueuedMeshUpdate::~QueuedMeshUpdate()
MeshUpdateQueue::MeshUpdateQueue() MeshUpdateQueue::MeshUpdateQueue()
{ {
m_queue = NULL;
m_mutex.Init(); m_mutex.Init();
} }
MeshUpdateQueue::~MeshUpdateQueue() MeshUpdateQueue::~MeshUpdateQueue()
{ {
QueuedMeshUpdate *i;
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
core::list<QueuedMeshUpdate*>::Iterator i; while (m_queue != NULL) {
for(i=m_queue.begin(); i!=m_queue.end(); i++) i = (QueuedMeshUpdate*)list_pull(&m_queue);
{ delete i;
QueuedMeshUpdate *q = *i;
delete q;
} }
} }
@ -98,9 +100,8 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se
Find if block is already in queue. Find if block is already in queue.
If it is, update the data and quit. If it is, update the data and quit.
*/ */
core::list<QueuedMeshUpdate*>::Iterator i; QueuedMeshUpdate* q = m_queue;
for (i=m_queue.begin(); i!=m_queue.end(); i++) { while (q) {
QueuedMeshUpdate *q = *i;
if (q->p == p) { if (q->p == p) {
if (q->data && data->m_refresh_only) { if (q->data && data->m_refresh_only) {
q->data->m_daynight_ratio = data->m_daynight_ratio; 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; q->ack_block_to_server = true;
return; return;
} }
q = q->next;
} }
/* /*
Add the block Add the block
*/ */
QueuedMeshUpdate *q = new QueuedMeshUpdate; q = new QueuedMeshUpdate;
q->p = p; q->p = p;
q->data = data; q->data = data;
q->ack_block_to_server = ack_block_to_server; 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 // Returned pointer must be deleted
@ -132,12 +135,7 @@ QueuedMeshUpdate * MeshUpdateQueue::pop()
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
core::list<QueuedMeshUpdate*>::Iterator i = m_queue.begin(); return (QueuedMeshUpdate*)list_pull(&m_queue);
if(i == m_queue.end())
return NULL;
QueuedMeshUpdate *q = *i;
m_queue.erase(i);
return q;
} }
/* /*
@ -927,11 +925,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
u16 field_count = readU16(is); u16 field_count = readU16(is);
// peer_ids // 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++) { for (u16 i=0; i<player_count; i++) {
u16 peer_id = readU16(is); u16 peer_id = readU16(is);
players_alive.push_back(peer_id); array_push_int(&players_alive,peer_id);
is.read(pname,PLAYERNAME_SIZE); is.read(pname,PLAYERNAME_SIZE);
pname[PLAYERNAME_SIZE-1] = '\0'; pname[PLAYERNAME_SIZE-1] = '\0';
chardef = deSerializeString(is); 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 Remove those players from the environment that
weren't listed by the server. weren't listed by the server.
*/ */
core::list<Player*> players = m_env.getPlayers(); array_t *players = m_env.getPlayers();
core::list<Player*>::Iterator ip; Player *player;
for (ip=players.begin(); ip!=players.end(); ip++) { uint32_t i;
for (i=0; i<players->length; i++) {
player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
// Ignore local player // Ignore local player
if ((*ip)->isLocal()) if (player->isLocal())
continue; continue;
// Warn about a special case // 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; infostream<<"Client: Removing dead player with id=0"<<std::endl;
bool is_alive = false; if (array_find_int(&players_alive,player->peer_id) > -1)
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)
continue; continue;
infostream<<"Removing dead player "<<(*ip)->peer_id infostream<<"Removing dead player "<<player->peer_id<<std::endl;
<<std::endl; m_env.removePlayer(player->peer_id);
m_env.removePlayer((*ip)->peer_id);
} }
} //envlock } //envlock
} }

View File

@ -38,6 +38,8 @@
#include "utility.h" // For IntervalLimiter #include "utility.h" // For IntervalLimiter
#include "sound.h" #include "sound.h"
#include "list.h"
struct MeshMakeData; struct MeshMakeData;
class ClientNotReadyException : public BaseException class ClientNotReadyException : public BaseException
@ -50,6 +52,8 @@ public:
struct QueuedMeshUpdate struct QueuedMeshUpdate
{ {
struct QueuedMeshUpdate *prev;
struct QueuedMeshUpdate *next;
v3s16 p; v3s16 p;
MeshMakeData *data; MeshMakeData *data;
bool ack_block_to_server; bool ack_block_to_server;
@ -80,11 +84,13 @@ public:
u32 size() u32 size()
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
return m_queue.size(); if (m_queue == NULL)
return 0;
return list_count(&m_queue);
} }
private: private:
core::list<QueuedMeshUpdate*> m_queue; QueuedMeshUpdate* m_queue;
JMutex m_mutex; JMutex m_mutex;
}; };

View File

@ -32,6 +32,8 @@
#include "nodemetadata.h" #include "nodemetadata.h"
#include "mapblock.h" #include "mapblock.h"
#include "array.h"
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
/* Some helper functions */ /* 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 */ /* don't do anything if there's no nearby player */
if (m_disturbing_player == "") { if (m_disturbing_player == "") {
float distance = 40*BS; float distance = 40*BS;
core::list<Player*> players = m_env->getPlayers(true); array_t *players = m_env->getPlayers(true);
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { Player *player;
Player *player = *i; uint32_t i;
for (i=0; i<players->length; i++) {
player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
v3f playerpos = player->getPosition(); v3f playerpos = player->getPosition();
f32 dist = m_base_position.getDistanceFrom(playerpos); f32 dist = m_base_position.getDistanceFrom(playerpos);
if (dist < distance) if (dist < distance)
distance = dist; distance = dist;
} }
array_free(players,1);
if (distance > 32*BS) { if (distance > 32*BS) {
/* kill of anything that shouldn't be on its own */ /* kill of anything that shouldn't be on its own */
if ( if (
@ -292,9 +299,13 @@ void MobSAO::step(float dtime, bool send_recommended)
) { ) {
m_disturbing_player = ""; m_disturbing_player = "";
// Check connected players // Check connected players
core::list<Player*> players = m_env->getPlayers(true); array_t *players = m_env->getPlayers(true);
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { Player *player;
Player *player = *i; uint32_t i;
for (i=0; i<players->length; i++) {
player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
v3f playerpos = player->getPosition(); v3f playerpos = player->getPosition();
f32 dist = m_base_position.getDistanceFrom(playerpos); f32 dist = m_base_position.getDistanceFrom(playerpos);
if (dist < BS*16) { if (dist < BS*16) {
@ -309,6 +320,7 @@ void MobSAO::step(float dtime, bool send_recommended)
} }
} }
} }
array_free(players,1);
} }
} }
if (m_disturbing_player != "") { 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 "server.h"
#include "client.h" #include "client.h"
#include "nvp.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
Environment::Environment(): Environment::Environment():
@ -50,16 +52,23 @@ Environment::Environment():
m_time_of_day_speed(0), m_time_of_day_speed(0),
m_time_counter(0) m_time_counter(0)
{ {
m_players = array_create(ARRAY_TYPE_PTR);
} }
Environment::~Environment() Environment::~Environment()
{ {
// Deallocate players // Deallocate players
for(core::list<Player*>::Iterator i = m_players.begin(); Player *player;
i != m_players.end(); i++) uint32_t i;
{ for (i=0; i<m_players->length; i++) {
delete (*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) void Environment::addPlayer(Player *player)
@ -76,36 +85,41 @@ void Environment::addPlayer(Player *player)
// Name has to be unique. // Name has to be unique.
if (getPlayer(player->getName()) != NULL) if (getPlayer(player->getName()) != NULL)
return; return;
// Add.
m_players.push_back(player); array_insert_ptr(m_players,player);
} }
void Environment::removePlayer(u16 peer_id) void Environment::removePlayer(u16 peer_id)
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
re_search: Player *player;
for(core::list<Player*>::Iterator i = m_players.begin(); uint32_t i;
i != m_players.end(); i++) int k;
{
Player *player = *i;
if(player->peer_id != peer_id)
continue;
delete player; do {
m_players.erase(i); k = 0;
// See if there is an another one for (i=0; i<m_players->length; i++) {
// (shouldn't be, but just to be sure) player = (Player*)array_get_ptr(m_players,i);
goto re_search; 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) Player * Environment::getPlayer(u16 peer_id)
{ {
for(core::list<Player*>::Iterator i = m_players.begin(); Player *player;
i != m_players.end(); i++) uint32_t i;
{ for (i=0; i<m_players->length; i++) {
Player *player = *i; player = (Player*)array_get_ptr(m_players,i);
if(player->peer_id == peer_id) if (!player)
continue;
if (player->peer_id == peer_id)
return player; return player;
} }
return NULL; return NULL;
@ -113,11 +127,13 @@ Player * Environment::getPlayer(u16 peer_id)
Player * Environment::getPlayer(const char *name) Player * Environment::getPlayer(const char *name)
{ {
for(core::list<Player*>::Iterator i = m_players.begin(); Player *player;
i != m_players.end(); i++) uint32_t i;
{ for (i=0; i<m_players->length; i++) {
Player *player = *i; player = (Player*)array_get_ptr(m_players,i);
if(strcmp(player->getName(), name) == 0) if (!player)
continue;
if (!strcmp(player->getName(), name))
return player; return player;
} }
return NULL; return NULL;
@ -125,36 +141,26 @@ Player * Environment::getPlayer(const char *name)
Player * Environment::getRandomConnectedPlayer() Player * Environment::getRandomConnectedPlayer()
{ {
core::list<Player*> connected_players = getPlayers(true); array_t *connected_players = getPlayers(true);
u32 chosen_one = myrand() % connected_players.size(); uint32_t i = myrand() % connected_players->length;
u32 j = 0; Player *r = (Player*)array_get_ptr(connected_players,i);
for(core::list<Player*>::Iterator array_free(connected_players,1);
i = connected_players.begin(); return r;
i != connected_players.end(); i++)
{
if(j == chosen_one)
{
Player *player = *i;
return player;
}
j++;
}
return NULL;
} }
Player * Environment::getNearestConnectedPlayer(v3f pos) Player * Environment::getNearestConnectedPlayer(v3f pos)
{ {
core::list<Player*> connected_players = getPlayers(true); array_t *connected_players = getPlayers(true);
f32 nearest_d = 0; float nearest_d = 0;
Player *nearest_player = NULL; Player *nearest_player = NULL;
for(core::list<Player*>::Iterator Player *player;
i = connected_players.begin(); uint32_t i;
i != connected_players.end(); i++) for (i=0; i<connected_players->length; i++) {
{ player = (Player*)array_get_ptr(connected_players,i);
Player *player = *i; if (!player)
f32 d = player->getPosition().getDistanceFrom(pos); continue;
if(d < nearest_d || nearest_player == NULL) float d = player->getPosition().getDistanceFrom(pos);
{ if (d < nearest_d || nearest_player == NULL) {
nearest_d = d; nearest_d = d;
nearest_player = player; nearest_player = player;
} }
@ -162,28 +168,28 @@ Player * Environment::getNearestConnectedPlayer(v3f pos)
return nearest_player; return nearest_player;
} }
core::list<Player*> Environment::getPlayers() array_t *Environment::getPlayers()
{ {
return m_players; return m_players;
} }
core::list<Player*> Environment::getPlayers(bool ignore_disconnected) array_t *Environment::getPlayers(bool ignore_disconnected)
{ {
core::list<Player*> newlist; array_t *newlist;
for(core::list<Player*>::Iterator uint32_t i;
i = m_players.begin(); Player *player;
i != m_players.end(); i++)
{
Player *player = *i;
if(ignore_disconnected) newlist = array_create(ARRAY_TYPE_PTR);
{
// Ignore disconnected players
if(player->peer_id == 0)
continue;
}
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; return newlist;
} }
@ -191,10 +197,12 @@ core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
void Environment::printPlayers(std::ostream &o) void Environment::printPlayers(std::ostream &o)
{ {
o<<"Players in environment:"<<std::endl; o<<"Players in environment:"<<std::endl;
for(core::list<Player*>::Iterator i = m_players.begin(); uint32_t i;
i != m_players.end(); i++) Player *player;
{ for (i=0; i<m_players->length; i++) {
Player *player = *i; player = (Player*)array_get_ptr(m_players,i);
if (!player)
continue;
o<<"Player peer_id="<<player->peer_id<<std::endl; 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"; std::string players_path = savedir + "/players";
fs::CreateDir(players_path); 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); 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) if (player_files[i].dir)
continue; continue;
@ -354,7 +364,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
// Search for the player // Search for the player
std::string playername = testplayer.getName(); std::string playername = testplayer.getName();
Player *player = getPlayer(playername.c_str()); player = getPlayer(playername.c_str());
if (player == NULL) { if (player == NULL) {
fs::RecursiveDelete(path); fs::RecursiveDelete(path);
continue; continue;
@ -371,13 +381,15 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
continue; continue;
} }
player->serialize(os); 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++) { for (i=0; i<m_players->length; i++) {
Player *player = *i; player = (Player*)array_get_ptr(m_players,i);
if (saved_players.find(player) != NULL) if (!player)
continue;
if (nvp_get(&saved_players, (char*)player->getName()) != NULL)
continue; continue;
std::string playername = player->getName(); std::string playername = player->getName();
// Don't save unnamed player // Don't save unnamed player
@ -412,11 +424,12 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
continue; continue;
} }
player->serialize(os); 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) 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); ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
int pc = 0; int pc = 0;
for (core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player;
Player *player = *i; 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 // Ignore disconnected players
if (player->peer_id == 0) if (player->peer_id == 0)
@ -1113,8 +1130,12 @@ void ServerEnvironment::step(float dtime)
} }
// wake up // wake up
addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),""); addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),"");
for (core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player;
Player *player = *i; 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 // Ignore disconnected players
if (player->peer_id == 0) if (player->peer_id == 0)
@ -1131,8 +1152,12 @@ void ServerEnvironment::step(float dtime)
}else if (m_players_sleeping) { }else if (m_players_sleeping) {
// wake up // wake up
addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),""); addEnvEvent(ENV_EVENT_WAKE,v3f(0,0,0),"");
for (core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player;
Player *player = *i; 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 // Ignore disconnected players
if (player->peer_id == 0) if (player->peer_id == 0)
@ -4106,8 +4131,12 @@ void ClientEnvironment::step(float dtime)
/* /*
Stuff that can be done in an arbitarily large 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;
Player *player = *i; 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(); v3f playerpos = player->getPosition();
/* /*
@ -4455,10 +4484,12 @@ void ClientEnvironment::updateObjectsCameraOffset(v3s16 camera_offset)
obj->updateCameraOffset(camera_offset); obj->updateCameraOffset(camera_offset);
} }
for (core::list<Player*>::Iterator i = m_players.begin(); Player *player;
i != m_players.end(); i++) uint32_t i;
{ for (i=0; i<m_players->length; i++) {
Player *player = *i; player = (Player*)array_get_ptr(m_players,i);
if (!player)
continue;
if (!player->isLocal()) if (!player->isLocal())
((RemotePlayer*)player)->updateCameraOffset(camera_offset); ((RemotePlayer*)player)->updateCameraOffset(camera_offset);
} }

View File

@ -48,6 +48,8 @@
#include "utility.h" #include "utility.h"
#include "activeobject.h" #include "activeobject.h"
#include "array.h"
class Server; class Server;
class ServerActiveObject; class ServerActiveObject;
@ -142,8 +144,8 @@ public:
Player * getPlayer(const char *name); Player * getPlayer(const char *name);
Player * getRandomConnectedPlayer(); Player * getRandomConnectedPlayer();
Player * getNearestConnectedPlayer(v3f pos); Player * getNearestConnectedPlayer(v3f pos);
core::list<Player*> getPlayers(); array_t *getPlayers();
core::list<Player*> getPlayers(bool ignore_disconnected); array_t *getPlayers(bool ignore_disconnected);
void printPlayers(std::ostream &o); void printPlayers(std::ostream &o);
virtual bool propogateEnergy(u8 level, v3s16 powersrc, v3s16 signalsrc, v3s16 pos, core::map<v3s16,MapBlock*> &modified_blocks) {return false;}; 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: protected:
// peer_ids in here should be unique, except that there may be many 0s // 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; u32 m_time;
// Time of day in milli-hours (0-23999); determines day and night // Time of day in milli-hours (0-23999); determines day and night
u32 m_time_of_day; u32 m_time_of_day;

View File

@ -211,18 +211,20 @@ int HTTPRemoteClient::handlePlayer()
/* player list */ /* player list */
std::string u1 = m_recv_headers.getUrl(1); std::string u1 = m_recv_headers.getUrl(1);
if (u1 == "" || u1.substr(0,5) == "page-") { 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 html("<h1>Players</h1>\n");
std::string pagination(""); std::string pagination("");
int player_skip = 0; int player_skip = 0;
if (players.size() > 50) { if (players->length > 50) {
int current_page = 1; int current_page = 1;
if (u1.substr(0,5) == "page-") { if (u1.substr(0,5) == "page-") {
current_page = mystoi(u1.substr(5)); current_page = mystoi(u1.substr(5));
if (current_page < 1) if (current_page < 1)
current_page = 1; current_page = 1;
} }
int total_pages = (players.size()/50)+1; int total_pages = (players->length/50)+1;
if (total_pages < 1) if (total_pages < 1)
total_pages = 1; total_pages = 1;
if (current_page > total_pages) if (current_page > total_pages)
@ -240,12 +242,14 @@ int HTTPRemoteClient::handlePlayer()
} }
html += pagination; html += pagination;
int p = 0; 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) if (p < player_skip)
continue; continue;
if (p > player_skip+50) if (p > player_skip+50)
break; break;
Player *player = *i; player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
html += http_player_interface(player,m_server,false); html += http_player_interface(player,m_server,false);
} }
html += pagination; html += pagination;
@ -331,15 +335,20 @@ int HTTPRemoteClient::handleAPI()
send((char*)txt.c_str()); send((char*)txt.c_str());
return 1; return 1;
}else if (u1 == "players") { }else if (u1 == "players") {
core::list<Player*> players = m_server->getGameServer()->getPlayers(true); array_t *players = m_server->getGameServer()->getPlayers(true);
std::string txt = itos(players.size())+"\n"; std::string txt = itos(players->length)+"\n";
int c = 0; int c = 0;
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { Player *player;
Player *player = *i; uint32_t i;
for (i=0; i<players->length; i++) {
player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
if (c++) if (c++)
txt += ", "; txt += ", ";
txt += player->getName(); txt += player->getName();
} }
array_free(players,1);
send((char*)txt.c_str()); send((char*)txt.c_str());
return 1; return 1;
}else if (u1 == "public") { }else if (u1 == "public") {
@ -365,9 +374,13 @@ int HTTPRemoteClient::handleIndex()
html += "</h2><p><strong>Version: </strong>"; html += "</h2><p><strong>Version: </strong>";
html += VERSION_STRING; html += VERSION_STRING;
html += "<br /><strong><a href=\"/player\" class=\"secret\">Players</a>: </strong>"; html += "<br /><strong><a href=\"/player\" class=\"secret\">Players</a>: </strong>";
core::list<Player*> players = m_server->getGameServer()->getPlayers(true); array_t *players = m_server->getGameServer()->getPlayers(true);
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { Player *player;
Player *player = *i; uint32_t i;
for (i=0; i<players->length; i++) {
player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
if (c++) if (c++)
html += ", "; html += ", ";
html += "<a href=\"/player/"; html += "<a href=\"/player/";
@ -376,6 +389,7 @@ int HTTPRemoteClient::handleIndex()
html += player->getName(); html += player->getName();
html += "</a>"; html += "</a>";
} }
array_free(players,1);
html += "</div>"; html += "</div>";
sendHTML((char*)html.c_str()); sendHTML((char*)html.c_str());
return 1; 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<PlayerInfo> list;
core::list<Player*> players = m_env.getPlayers(); array_t *players = m_env.getPlayers();
core::list<Player*>::Iterator i; Player *player;
for(i = players.begin(); uint32_t i;
i != players.end(); i++) for (i=0; i<players->length; i++) {
{ player = (Player*)array_get_ptr(players,i);
if (!player)
continue;
PlayerInfo info; PlayerInfo info;
Player *player = *i;
try{ try{
// Copy info from connection to info struct // Copy info from connection to info struct
info.id = player->peer_id; info.id = player->peer_id;
@ -5004,19 +5004,23 @@ void Server::SendPlayerInfo(float dtime)
os.write((char*)buf, 2); os.write((char*)buf, 2);
// Get connected players // 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 // players ignore their own data, so don't bother sending for one player
if (players.size() < 2) if (players->length < 2)
return; return;
// Write player count // Write player count
u16 playercount = players.size(); u16 playercount = players->length;
writeU16(buf, playercount); writeU16(buf, playercount);
os.write((char*)buf, 2); os.write((char*)buf, 2);
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { ServerRemotePlayer *player;
ServerRemotePlayer *player = (ServerRemotePlayer*)(*i); 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); writeU16(os, player->peer_id);
writeV3F1000(os, player->getPosition()); writeV3F1000(os, player->getPosition());
@ -5027,6 +5031,8 @@ void Server::SendPlayerInfo(float dtime)
writeU16(os, player->pointed_id); writeU16(os, player->pointed_id);
} }
array_free(players,1);
// Make data buffer // Make data buffer
std::string s = os.str(); std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size()); SharedBuffer<u8> data((u8*)s.c_str(), s.size());
@ -5039,17 +5045,21 @@ void Server::SendPlayerData()
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
// Get connected players // 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); std::ostringstream os(std::ios_base::binary);
writeU16(os, TOCLIENT_PLAYERDATA); writeU16(os, TOCLIENT_PLAYERDATA);
writeU16(os,(u16)players.size()); writeU16(os,(u16)players->length);
// this is the number of serialized strings sent below // this is the number of serialized strings sent below
writeU16(os,1); writeU16(os,1);
char name[PLAYERNAME_SIZE]; char name[PLAYERNAME_SIZE];
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) { Player *player;
Player *player = *i; 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); writeU16(os, player->peer_id);
memset(name, 0, PLAYERNAME_SIZE); memset(name, 0, PLAYERNAME_SIZE);
@ -5059,6 +5069,8 @@ void Server::SendPlayerData()
// serialized strings can be added here // serialized strings can be added here
} }
array_free(players,1);
std::string s = os.str(); std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size()); SharedBuffer<u8> data((u8*)s.c_str(), s.size());
@ -5127,15 +5139,21 @@ void Server::SendPlayerItems()
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary); 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, TOCLIENT_PLAYERITEMS);
writeU16(os, players.size()); writeU16(os, players->length);
writeU16(os, 8); writeU16(os, 8);
for (core::list<Player *>::Iterator i = players.begin(); i != players.end(); i++) {
Player *p = *i; Player *player;
writeU16(os, p->peer_id); uint32_t i;
InventoryItem *item = (InventoryItem*)p->getWieldItem(); 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) { if (item == NULL) {
writeU16(os,CONTENT_IGNORE); writeU16(os,CONTENT_IGNORE);
}else{ }else{
@ -5143,7 +5161,7 @@ void Server::SendPlayerItems()
} }
const char* list[7] = {"hat","shirt","pants","boots","decorative","jacket","belt"}; const char* list[7] = {"hat","shirt","pants","boots","decorative","jacket","belt"};
for (int j=0; j<7; j++) { for (int j=0; j<7; j++) {
InventoryList *l = p->inventory.getList(list[j]); InventoryList *l = player->inventory.getList(list[j]);
if (l == NULL) if (l == NULL)
continue; continue;
InventoryItem *itm = l->getItem(0); InventoryItem *itm = l->getItem(0);
@ -5155,6 +5173,8 @@ void Server::SendPlayerItems()
} }
} }
array_free(players,1);
// Make data buffer // Make data buffer
std::string s = os.str(); std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size()); 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);} bool userExists(const char *name) {return m_authmanager.exists(name);}
Player *getPlayer(std::string name) {return m_env.getPlayer(name.c_str());} Player *getPlayer(std::string name) {return m_env.getPlayer(name.c_str());}
core::list<Player*> getPlayers() {return m_env.getPlayers();} array_t *getPlayers() {return m_env.getPlayers();}
core::list<Player*> getPlayers(bool ign_disconnected) {return m_env.getPlayers(ign_disconnected);} array_t *getPlayers(bool ign_disconnected) {return m_env.getPlayers(ign_disconnected);}
uint64_t getPlayerPrivs(Player *player); uint64_t getPlayerPrivs(Player *player);