forked from oerkki/voxelands
sane code pt1
This commit is contained in:
parent
e3c50924a6
commit
221f079fe0
|
@ -164,6 +164,11 @@ configure_file(
|
||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
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
|
||||||
|
|
|
@ -0,0 +1,807 @@
|
||||||
|
/************************************************************************
|
||||||
|
* array.c
|
||||||
|
* tausaga - environmental survival game
|
||||||
|
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int array_next_size(int s)
|
||||||
|
{
|
||||||
|
s /= 16;
|
||||||
|
s = (s+1)*16;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialises an array - useful for those created on the stack */
|
||||||
|
void array_init(array_t *a, uint32_t type)
|
||||||
|
{
|
||||||
|
a->type = type;
|
||||||
|
a->length = 0;
|
||||||
|
a->size = 0;
|
||||||
|
a->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a new array of type */
|
||||||
|
array_t *array_create(uint32_t type)
|
||||||
|
{
|
||||||
|
array_t *a;
|
||||||
|
|
||||||
|
a = malloc(sizeof(array_t));
|
||||||
|
a->type = type;
|
||||||
|
a->length = 0;
|
||||||
|
a->size = 0;
|
||||||
|
a->data = NULL;
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a new array as a copy of a */
|
||||||
|
array_t *array_copy(array_t *a)
|
||||||
|
{
|
||||||
|
array_t *r = array_create(ARRAY_TYPE_STRING);
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
int i;
|
||||||
|
r->type = a->type;
|
||||||
|
switch (a->type) {
|
||||||
|
case ARRAY_TYPE_STRING:
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
array_push_string(r,((char**)(a->data))[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARRAY_TYPE_FLOAT:
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
array_push_float(r,((float*)(a->data))[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARRAY_TYPE_INT:
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
array_push_int(r,((uint32_t*)(a->data))[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARRAY_TYPE_PTR:
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
array_push_ptr(r,((uint8_t**)(a->data))[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compare two arrays */
|
||||||
|
int array_cmp(array_t *a1, array_t *a2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char** c1;
|
||||||
|
char** c2;
|
||||||
|
int *i1;
|
||||||
|
int *i2;
|
||||||
|
float *f1;
|
||||||
|
float *f2;
|
||||||
|
if (!a1 || !a2)
|
||||||
|
return -1;
|
||||||
|
if (a1->length != a2->length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_STRING) {
|
||||||
|
c1 = a1->data;
|
||||||
|
c2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (!c1[i] || !c2[i] || strcmp(c1[i],c2[i]))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_INT) {
|
||||||
|
c1 = a1->data;
|
||||||
|
i2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (!c1[i] || i2[i] != strtol(c1[i],NULL,10))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
c1 = a1->data;
|
||||||
|
f2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (!c1[i] || f2[i] != strtof(c1[i],NULL))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_STRING) {
|
||||||
|
i1 = a1->data;
|
||||||
|
c2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (!c2[i] || i1[i] != strtol(c2[i],NULL,10))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_STRING) {
|
||||||
|
f1 = a1->data;
|
||||||
|
c2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (!c2[i] || f1[i] != strtof(c2[i],NULL))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_INT) {
|
||||||
|
i1 = a1->data;
|
||||||
|
i2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (i1[i] != i2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
f1 = a1->data;
|
||||||
|
f2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (f1[i] != f2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
i1 = a1->data;
|
||||||
|
f2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (i1[i] != (int)f2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_INT) {
|
||||||
|
f1 = a1->data;
|
||||||
|
i2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if ((int)f1[i] != i2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else if (a1->type == ARRAY_TYPE_PTR && a2->type == ARRAY_TYPE_PTR) {
|
||||||
|
c1 = a1->data;
|
||||||
|
c2 = a2->data;
|
||||||
|
for (i=0; i<a1->length; i++) {
|
||||||
|
if (c1[i] != c2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* destroy an array */
|
||||||
|
void array_free(array_t *a, int freestruct)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (!a)
|
||||||
|
return;
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
char** p = a->data;
|
||||||
|
for (i=0; i<a->length; i++ ) {
|
||||||
|
if (p[i])
|
||||||
|
free(p[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(a->data);
|
||||||
|
if (freestruct)
|
||||||
|
free(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push an int onto an array */
|
||||||
|
int array_push_int(array_t *a, uint32_t v)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%u",v);
|
||||||
|
return array_push_string(a,sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
return array_push_float(a,(float)v);
|
||||||
|
}else if (a->type != ARRAY_TYPE_INT) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->length++;
|
||||||
|
|
||||||
|
p = a->data;
|
||||||
|
|
||||||
|
if (a->size < a->length) {
|
||||||
|
int s = array_next_size(a->length);
|
||||||
|
p = realloc(a->data,sizeof(uint32_t)*s);
|
||||||
|
if (!p) {
|
||||||
|
a->length--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
a->size = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[a->length-1] = v;
|
||||||
|
a->data = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a float onto an array */
|
||||||
|
int array_push_float(array_t *a, float v)
|
||||||
|
{
|
||||||
|
float *p;
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%f",v);
|
||||||
|
return array_push_string(a,sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
return array_push_int(a,(int)v);
|
||||||
|
}else if (a->type != ARRAY_TYPE_FLOAT) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->length++;
|
||||||
|
|
||||||
|
p = a->data;
|
||||||
|
|
||||||
|
if (a->size < a->length) {
|
||||||
|
int s = array_next_size(a->length);
|
||||||
|
p = realloc(a->data,sizeof(float)*s);
|
||||||
|
if (!p) {
|
||||||
|
a->length--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
a->size = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[a->length-1] = v;
|
||||||
|
a->data = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a string onto an array */
|
||||||
|
int array_push_string(array_t *a, char* v)
|
||||||
|
{
|
||||||
|
char** p;
|
||||||
|
if (a->type != ARRAY_TYPE_STRING)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
a->length++;
|
||||||
|
|
||||||
|
p = a->data;
|
||||||
|
|
||||||
|
if (a->size < a->length) {
|
||||||
|
int s = array_next_size(a->length);
|
||||||
|
p = realloc(a->data,sizeof(char*)*s);
|
||||||
|
if (!p) {
|
||||||
|
a->length--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
a->size = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
p[a->length-1] = strdup(v);
|
||||||
|
}else{
|
||||||
|
p[a->length-1] = NULL;
|
||||||
|
}
|
||||||
|
a->data = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a pointer onto an array */
|
||||||
|
int array_push_ptr(array_t *a, void *v)
|
||||||
|
{
|
||||||
|
char** p;
|
||||||
|
if (a->type != ARRAY_TYPE_PTR)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
a->length++;
|
||||||
|
|
||||||
|
p = a->data;
|
||||||
|
|
||||||
|
if (a->size < a->length) {
|
||||||
|
int s = array_next_size(a->length);
|
||||||
|
p = realloc(a->data,sizeof(char*)*s);
|
||||||
|
if (!p) {
|
||||||
|
a->length--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
a->size = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[a->length-1] = v;
|
||||||
|
|
||||||
|
a->data = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a pointer onto an array if it isn't already in there */
|
||||||
|
int array_push_unique_ptr(array_t *a, void *v)
|
||||||
|
{
|
||||||
|
if (array_find_ptr(a,v) > -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return array_push_ptr(a,v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a colour onto an array *
|
||||||
|
int array_push_colour(array_t *a, colour_t *c)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
r += array_push_float(a,((float)c->r)/255.0);
|
||||||
|
r += array_push_float(a,((float)c->g)/255.0);
|
||||||
|
r += array_push_float(a,((float)c->b)/255.0);
|
||||||
|
r += array_push_float(a,((float)c->a)/255.0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
* push a v3_t onto an array *
|
||||||
|
int array_push_v3t(array_t *a, v3_t *v)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
r += array_push_float(a,v->x);
|
||||||
|
r += array_push_float(a,v->y);
|
||||||
|
r += array_push_float(a,v->z);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
* push a v2_t onto an array *
|
||||||
|
int array_push_v2t(array_t *a, v2_t *v)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
r += array_push_float(a,v->x);
|
||||||
|
r += array_push_float(a,v->y);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
* set the value of array index i to an int value */
|
||||||
|
int array_set_int(array_t *a, uint32_t v, int i)
|
||||||
|
{
|
||||||
|
uint32_t *p = a->data;
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%u",v);
|
||||||
|
return array_set_string(a,sv,i);
|
||||||
|
}else if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
return array_set_float(a,(float)v,i);
|
||||||
|
}else if (a->type != ARRAY_TYPE_INT) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->size <= i) {
|
||||||
|
int k;
|
||||||
|
int l = array_next_size(i+1);
|
||||||
|
|
||||||
|
p = realloc(a->data,sizeof(uint32_t)*l);
|
||||||
|
if (!p)
|
||||||
|
return 1;
|
||||||
|
for (k=a->length; k<l; k++) {
|
||||||
|
p[k] = 0;
|
||||||
|
}
|
||||||
|
a->data = p;
|
||||||
|
a->size = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->length <= i)
|
||||||
|
a->length = i+1;
|
||||||
|
|
||||||
|
p[i] = v;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the value of array index i to a float value */
|
||||||
|
int array_set_float(array_t *a, float v, int i)
|
||||||
|
{
|
||||||
|
float *p = a->data;
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%f",v);
|
||||||
|
return array_set_string(a,sv,i);
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
return array_set_float(a,(uint32_t)v,i);
|
||||||
|
}else if (a->type != ARRAY_TYPE_FLOAT) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->size <= i) {
|
||||||
|
int k;
|
||||||
|
int l = array_next_size(i+1);
|
||||||
|
|
||||||
|
p = realloc(a->data,sizeof(float)*l);
|
||||||
|
if (!p)
|
||||||
|
return 1;
|
||||||
|
for (k=a->length; k<l; k++) {
|
||||||
|
p[k] = 0.0;
|
||||||
|
}
|
||||||
|
a->data = p;
|
||||||
|
a->size = l;
|
||||||
|
}
|
||||||
|
if (a->length <= i)
|
||||||
|
a->length = i+1;
|
||||||
|
|
||||||
|
p[i] = v;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the value of array index i to a string value */
|
||||||
|
int array_set_string(array_t *a, char* v, int i)
|
||||||
|
{
|
||||||
|
char** p = a->data;
|
||||||
|
if (a->type != ARRAY_TYPE_STRING)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (a->size <= i) {
|
||||||
|
int k;
|
||||||
|
int l = array_next_size(i+1);
|
||||||
|
|
||||||
|
p = realloc(a->data,sizeof(char*)*l);
|
||||||
|
if (!p)
|
||||||
|
return 1;
|
||||||
|
for (k=a->length; k<l; k++) {
|
||||||
|
p[k] = NULL;
|
||||||
|
}
|
||||||
|
a->data = p;
|
||||||
|
a->size = l;
|
||||||
|
}
|
||||||
|
if (a->length <= i)
|
||||||
|
a->length = i+1;
|
||||||
|
|
||||||
|
if (p[i])
|
||||||
|
free(p[i]);
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
p[i] = strdup(v);
|
||||||
|
}else{
|
||||||
|
p[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the value of array index i to a ponter value */
|
||||||
|
int array_set_ptr(array_t *a, void* v, int i)
|
||||||
|
{
|
||||||
|
char** p = a->data;
|
||||||
|
if (a->type != ARRAY_TYPE_PTR)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (a->size <= i) {
|
||||||
|
int k;
|
||||||
|
int l = array_next_size(i+1);
|
||||||
|
|
||||||
|
p = realloc(a->data,sizeof(char*)*l);
|
||||||
|
if (!p)
|
||||||
|
return 1;
|
||||||
|
for (k=a->length; k<l; k++) {
|
||||||
|
p[k] = NULL;
|
||||||
|
}
|
||||||
|
a->data = p;
|
||||||
|
a->size = l;
|
||||||
|
}
|
||||||
|
if (a->length <= i)
|
||||||
|
a->length = i+1;
|
||||||
|
|
||||||
|
p[i] = v;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert a pointer onto the first NULL index of an array */
|
||||||
|
int array_insert_ptr(array_t *a, void *v)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t** p;
|
||||||
|
|
||||||
|
if (a->type != ARRAY_TYPE_PTR)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
p = a->data;
|
||||||
|
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (!p[i]) {
|
||||||
|
p[i] = v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_push_ptr(a,v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop an int off the top of an array */
|
||||||
|
uint32_t array_pop_int(array_t *a)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
if (!a->length)
|
||||||
|
return 0;
|
||||||
|
a->length--;
|
||||||
|
return ((uint32_t*)(a->data))[a->length];
|
||||||
|
}else if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
float v = array_pop_float(a);
|
||||||
|
return (uint32_t)v;
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
uint32_t v;
|
||||||
|
char* s = array_pop_string(a);
|
||||||
|
v = strtol(s,NULL,10);
|
||||||
|
free(s);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop a float off the top of an array */
|
||||||
|
float array_pop_float(array_t *a)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
if (!a->length)
|
||||||
|
return 0;
|
||||||
|
a->length--;
|
||||||
|
return ((float*)(a->data))[a->length];
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
uint32_t v = array_pop_int(a);
|
||||||
|
return (float)v;
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
float v;
|
||||||
|
char* s = array_pop_string(a);
|
||||||
|
v = strtof(s,NULL);
|
||||||
|
free(s);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop a string off the top of an array */
|
||||||
|
char* array_pop_string(array_t *a)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
float v = array_pop_float(a);
|
||||||
|
char sv[20];
|
||||||
|
if (!a->length)
|
||||||
|
return NULL;
|
||||||
|
sprintf(sv,"%f",v);
|
||||||
|
return strdup(sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
uint32_t v = array_pop_int(a);
|
||||||
|
char sv[20];
|
||||||
|
if (!a->length)
|
||||||
|
return NULL;
|
||||||
|
sprintf(sv,"%u",v);
|
||||||
|
return strdup(sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
if (!a->length)
|
||||||
|
return NULL;
|
||||||
|
a->length--;
|
||||||
|
return ((char**)(a->data))[a->length];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop a pointer off the top of an array */
|
||||||
|
void *array_pop_ptr(array_t *a)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_PTR && a->length) {
|
||||||
|
a->length--;
|
||||||
|
return ((char**)(a->data))[a->length];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get an int value from an array */
|
||||||
|
uint32_t array_get_int(array_t *a, int i)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
if (a->length <= i)
|
||||||
|
return 0;
|
||||||
|
return ((uint32_t*)(a->data))[i];
|
||||||
|
}else if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
float v = array_get_float(a,i);
|
||||||
|
return (uint32_t)v;
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
uint32_t v;
|
||||||
|
char* s = array_get_string(a,i);
|
||||||
|
v = strtol(s,NULL,10);
|
||||||
|
free(s);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a float value from an array */
|
||||||
|
float array_get_float(array_t *a, int i)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
if (a->length <= i)
|
||||||
|
return 0.0;
|
||||||
|
return ((float*)(a->data))[i];
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
uint32_t v = array_get_int(a,i);
|
||||||
|
return (float)v;
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
float v;
|
||||||
|
char* s = array_get_string(a,i);
|
||||||
|
v = strtof(s,NULL);
|
||||||
|
free(s);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a string value from an array */
|
||||||
|
char* array_get_string(array_t *a, int i)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
float v = array_get_float(a,i);
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%f",v);
|
||||||
|
return strdup(sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
uint32_t v = array_get_int(a,i);
|
||||||
|
char sv[20];
|
||||||
|
sprintf(sv,"%u",v);
|
||||||
|
return strdup(sv);
|
||||||
|
}else if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
if (a->length <= i)
|
||||||
|
return NULL;
|
||||||
|
return ((char**)(a->data))[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer from an array */
|
||||||
|
void *array_get_ptr(array_t *a, int i)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_PTR && a->length > i) {
|
||||||
|
return ((char**)(a->data))[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the index of an int value in an array */
|
||||||
|
int array_find_int(array_t *a, uint32_t v)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_INT) {
|
||||||
|
int i;
|
||||||
|
uint32_t *p = a->data;
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (p[i] == v)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the index of a float value in an array */
|
||||||
|
int array_find_float(array_t *a, float v)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_FLOAT) {
|
||||||
|
int i;
|
||||||
|
float *p = a->data;
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (p[i] == v)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the index of a string value in an array */
|
||||||
|
int array_find_string(array_t *a, char* v)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
int i;
|
||||||
|
char** p = a->data;
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (!strcmp(p[i],v))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the index of a pointer in an array */
|
||||||
|
int array_find_ptr(array_t *a, void *v)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_PTR) {
|
||||||
|
int i;
|
||||||
|
uint8_t* cv = v;
|
||||||
|
uint8_t** p = a->data;
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (p[i] == cv)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove a string value from an array */
|
||||||
|
int array_remove_string(array_t *a, char* v)
|
||||||
|
{
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
int i;
|
||||||
|
char** p = a->data;
|
||||||
|
for (i=0; i<a->length; i++) {
|
||||||
|
if (!strcmp(p[i],v)) {
|
||||||
|
free(p[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a->length--;
|
||||||
|
for (; i<a->length; i++) {
|
||||||
|
p[i] = p[i+1];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split a string into an array, at a separator character */
|
||||||
|
/* TODO: if strings is non-zero, then don't split within "" or '' */
|
||||||
|
/* TODO: utf8 support */
|
||||||
|
array_t *array_split(char* str, char* s, int strings)
|
||||||
|
{
|
||||||
|
char buff[1024];
|
||||||
|
int i;
|
||||||
|
int o = 0;
|
||||||
|
int l;
|
||||||
|
array_t *r;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
r = array_create(ARRAY_TYPE_STRING);
|
||||||
|
|
||||||
|
l = strlen(s);
|
||||||
|
|
||||||
|
for (i=0; str[i]; i++) {
|
||||||
|
if (!strncmp(str+i,s,l)) {
|
||||||
|
buff[o] = 0;
|
||||||
|
array_push_string(r,buff);
|
||||||
|
o = 0;
|
||||||
|
i += l-1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buff[o++] = str[i];
|
||||||
|
}
|
||||||
|
buff[o] = 0;
|
||||||
|
array_push_string(r,buff);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* join an array into a string, using a glue character */
|
||||||
|
char* array_join(array_t *a, char* glue, int start)
|
||||||
|
{
|
||||||
|
char* str = NULL;
|
||||||
|
int l = 0;
|
||||||
|
if (!glue)
|
||||||
|
glue = " ";
|
||||||
|
if (a->type == ARRAY_TYPE_STRING) {
|
||||||
|
int i;
|
||||||
|
int gl = strlen(glue);
|
||||||
|
for (i=start; i<a->length; i++) {
|
||||||
|
l += strlen(((char**)(a->data))[i])+gl;
|
||||||
|
}
|
||||||
|
if (l) {
|
||||||
|
str = malloc(l+1);
|
||||||
|
str[0] = 0;
|
||||||
|
for (i=start; i<a->length; i++) {
|
||||||
|
if (i > start)
|
||||||
|
strcat(str,glue);
|
||||||
|
strcat(str,((char**)(a->data))[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef _ARRAY_H_
|
||||||
|
#define _ARRAY_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef _HAVE_ARRAY_TYPE
|
||||||
|
#define _HAVE_ARRAY_TYPE
|
||||||
|
typedef struct array_s {
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t size;
|
||||||
|
void *data;
|
||||||
|
} array_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define ARRAY_TYPE_NONE 0
|
||||||
|
#define ARRAY_TYPE_INT 1
|
||||||
|
#define ARRAY_TYPE_STRING 2
|
||||||
|
#define ARRAY_TYPE_FLOAT 3
|
||||||
|
#define ARRAY_TYPE_PTR 4
|
||||||
|
|
||||||
|
/* defined in array.c */
|
||||||
|
void array_init(array_t *a, uint32_t type);
|
||||||
|
array_t *array_create(uint32_t type);
|
||||||
|
array_t *array_copy(array_t *a);
|
||||||
|
int array_cmp(array_t *a1, array_t *a2);
|
||||||
|
void array_free(array_t *a, int freestruct);
|
||||||
|
int array_push_int(array_t *a, uint32_t v);
|
||||||
|
int array_push_float(array_t *a, float v);
|
||||||
|
int array_push_string(array_t *a, char* v);
|
||||||
|
int array_push_ptr(array_t *a, void *v);
|
||||||
|
int array_push_unique_ptr(array_t *a, void *v);
|
||||||
|
/*
|
||||||
|
int array_push_colour(array_t *a, colour_t *c);
|
||||||
|
int array_push_v3t(array_t *a, v3_t *v);
|
||||||
|
int array_push_v2t(array_t *a, v2_t *v);
|
||||||
|
*/
|
||||||
|
int array_set_int(array_t *a, uint32_t v, int i);
|
||||||
|
int array_set_float(array_t *a, float v, int i);
|
||||||
|
int array_set_string(array_t *a, char* v, int i);
|
||||||
|
int array_set_ptr(array_t *a, void* v, int i);
|
||||||
|
int array_insert_ptr(array_t *a, void *v);
|
||||||
|
uint32_t array_pop_int(array_t *a);
|
||||||
|
float array_pop_float(array_t *a);
|
||||||
|
char* array_pop_string(array_t *a);
|
||||||
|
void *array_pop_ptr(array_t *a);
|
||||||
|
uint32_t array_get_int(array_t *a, int i);
|
||||||
|
float array_get_float(array_t *a, int i);
|
||||||
|
char* array_get_string(array_t *a, int i);
|
||||||
|
void *array_get_ptr(array_t *a, int i);
|
||||||
|
int array_find_int(array_t *a, uint32_t v);
|
||||||
|
int array_find_float(array_t *a, float v);
|
||||||
|
int array_find_string(array_t *a, char* v);
|
||||||
|
int array_find_ptr(array_t *a, void *v);
|
||||||
|
int array_remove_string(array_t *a, char* v);
|
||||||
|
array_t *array_split(char* str, char* s, int strings);
|
||||||
|
char* array_join(array_t *a, char* glue, int start);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -153,6 +153,7 @@ GUICharDefMenu::~GUICharDefMenu()
|
||||||
|
|
||||||
void GUICharDefMenu::removeChildren()
|
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++) {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
10
src/client.h
10
src/client.h
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 != "") {
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/************************************************************************
|
||||||
|
* crypto.c
|
||||||
|
* tausaga - environmental survival game
|
||||||
|
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* defined in base64.c */
|
||||||
|
int base64_lencode(char *source, size_t sourcelen, char *target, size_t targetlen);
|
||||||
|
size_t base64_ldecode(char *source, char *target, size_t targetlen);
|
||||||
|
|
||||||
|
uint32_t hash(char *str_param)
|
||||||
|
{
|
||||||
|
uint32_t hval = 0;
|
||||||
|
uint32_t g;
|
||||||
|
const char *s = str_param;
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
hval <<= 4;
|
||||||
|
hval += (unsigned char) *s++;
|
||||||
|
g = hval & ((uint32_t) 0xf << 28);
|
||||||
|
if (g != 0) {
|
||||||
|
hval ^= g >> 24;
|
||||||
|
hval ^= g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base64 encode a string */
|
||||||
|
char* base64_encode(char* str)
|
||||||
|
{
|
||||||
|
int sl;
|
||||||
|
int tl;
|
||||||
|
char* ret;
|
||||||
|
int el;
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sl = strlen(str);
|
||||||
|
tl = ((sl+2)/3*4)+5;
|
||||||
|
|
||||||
|
ret = malloc(tl);
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
el = base64_lencode(str, sl, ret, tl);
|
||||||
|
if (!el) {
|
||||||
|
free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decode a base64 string */
|
||||||
|
char* base64_decode(char* str)
|
||||||
|
{
|
||||||
|
int sl;
|
||||||
|
int tl;
|
||||||
|
char* ret;
|
||||||
|
int dl;
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sl = strlen(str);
|
||||||
|
tl = (sl/4*3)+5;
|
||||||
|
ret = malloc(tl);
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dl = base64_ldecode(str, ret, tl);
|
||||||
|
if (!dl) {
|
||||||
|
free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret[dl] = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef _CRYPTO_H_
|
||||||
|
#define _CRYPTO_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint32_t hash(char* str);
|
||||||
|
char* base64_encode(char* str);
|
||||||
|
char* base64_decode(char* str);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,203 @@
|
||||||
|
/************************************************************************
|
||||||
|
* crypto_base64.c
|
||||||
|
* tausaga - environmental survival game
|
||||||
|
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char* b64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
/* encode three bytes using base64 */
|
||||||
|
static void s_base64_encode_triple(unsigned char triple[3], unsigned char result[4])
|
||||||
|
{
|
||||||
|
int tripleValue;
|
||||||
|
int i;
|
||||||
|
int v;
|
||||||
|
|
||||||
|
tripleValue = triple[0];
|
||||||
|
tripleValue *= 256;
|
||||||
|
tripleValue += triple[1];
|
||||||
|
tripleValue *= 256;
|
||||||
|
tripleValue += triple[2];
|
||||||
|
|
||||||
|
for (i=0; i<4; i++) {
|
||||||
|
v = tripleValue%64;
|
||||||
|
if (v < 0) {
|
||||||
|
v *= -1;
|
||||||
|
}
|
||||||
|
if (v > 63) {
|
||||||
|
result[3-i] = '=';
|
||||||
|
}else{
|
||||||
|
result[3-i] = b64_chars[v];
|
||||||
|
}
|
||||||
|
tripleValue /= 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the value of a base64 encoding character */
|
||||||
|
static int s_base64_char_value(unsigned char c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' && c <= 'Z')
|
||||||
|
return c-'A';
|
||||||
|
if (c >= 'a' && c <= 'z')
|
||||||
|
return c-'a'+26;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c-'0'+2*26;
|
||||||
|
if (c == '+')
|
||||||
|
return 2*26+10;
|
||||||
|
if (c == '/')
|
||||||
|
return 2*26+11;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decode a 4 char base64 encoded byte triple */
|
||||||
|
static int s_base64_decode_triple(unsigned char quadruple[4], unsigned char *result)
|
||||||
|
{
|
||||||
|
int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
|
||||||
|
int char_value[4];
|
||||||
|
|
||||||
|
for (i=0; i<4; i++) {
|
||||||
|
char_value[i] = s_base64_char_value(quadruple[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the characters are valid */
|
||||||
|
for (i=3; i>=0; i--) {
|
||||||
|
if (char_value[i]<0) {
|
||||||
|
if (only_equals_yet && quadruple[i]=='=') {
|
||||||
|
/* we will ignore this character anyway, make it something
|
||||||
|
* that does not break our calculations */
|
||||||
|
char_value[i]=0;
|
||||||
|
bytes_to_decode--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* after we got a real character, no other '=' are allowed anymore */
|
||||||
|
only_equals_yet = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we got "====" as input, bytes_to_decode is -1 */
|
||||||
|
if (bytes_to_decode < 0)
|
||||||
|
bytes_to_decode = 0;
|
||||||
|
|
||||||
|
/* make one big value out of the partial values */
|
||||||
|
triple_value = char_value[0];
|
||||||
|
triple_value *= 64;
|
||||||
|
triple_value += char_value[1];
|
||||||
|
triple_value *= 64;
|
||||||
|
triple_value += char_value[2];
|
||||||
|
triple_value *= 64;
|
||||||
|
triple_value += char_value[3];
|
||||||
|
|
||||||
|
/* break the big value into bytes */
|
||||||
|
for (i=bytes_to_decode; i<3; i++) {
|
||||||
|
triple_value /= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=bytes_to_decode-1; i>=0; i--) {
|
||||||
|
result[i] = triple_value%256;
|
||||||
|
triple_value /= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_to_decode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encode an array of bytes using base64 */
|
||||||
|
int base64_lencode(char *source, size_t sourcelen, char *target, size_t targetlen)
|
||||||
|
{
|
||||||
|
/* check if the result will fit in the target buffer */
|
||||||
|
if ((sourcelen+2)/3*4 > targetlen-1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* encode all full triples */
|
||||||
|
while (sourcelen >= 3) {
|
||||||
|
s_base64_encode_triple((unsigned char*)source, (unsigned char*)target);
|
||||||
|
sourcelen -= 3;
|
||||||
|
source += 3;
|
||||||
|
target += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encode the last one or two characters */
|
||||||
|
if (sourcelen > 0) {
|
||||||
|
unsigned char temp[3];
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
memcpy(temp, source, sourcelen);
|
||||||
|
s_base64_encode_triple((unsigned char*)temp, (unsigned char*)target);
|
||||||
|
target[3] = '=';
|
||||||
|
if (sourcelen == 1)
|
||||||
|
target[2] = '=';
|
||||||
|
|
||||||
|
target += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* terminate the string */
|
||||||
|
target[0] = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decode base64 encoded data */
|
||||||
|
size_t base64_ldecode(char *source, char *target, size_t targetlen)
|
||||||
|
{
|
||||||
|
char *src, *tmpptr;
|
||||||
|
char quadruple[4], tmpresult[3];
|
||||||
|
int i, tmplen = 3;
|
||||||
|
size_t converted = 0;
|
||||||
|
|
||||||
|
/* concatinate '===' to the source to handle unpadded base64 data */
|
||||||
|
src = malloc(strlen(source)+5);
|
||||||
|
if (!src)
|
||||||
|
return -1;
|
||||||
|
strcpy(src, source);
|
||||||
|
strcat(src, "====");
|
||||||
|
tmpptr = src;
|
||||||
|
|
||||||
|
/* convert as long as we get a full result */
|
||||||
|
while (tmplen == 3) {
|
||||||
|
/* get 4 characters to convert */
|
||||||
|
for (i=0; i<4; i++) {
|
||||||
|
/* skip invalid characters - we won't reach the end */
|
||||||
|
while (*tmpptr != '=' && s_base64_char_value(*tmpptr)<0) {
|
||||||
|
tmpptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
quadruple[i] = *(tmpptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert the characters */
|
||||||
|
tmplen = s_base64_decode_triple((unsigned char*)quadruple, (unsigned char*)tmpresult);
|
||||||
|
|
||||||
|
/* check if the fit in the result buffer */
|
||||||
|
if (targetlen < tmplen) {
|
||||||
|
free(src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put the partial result in the result buffer */
|
||||||
|
memcpy(target, tmpresult, tmplen);
|
||||||
|
target += tmplen;
|
||||||
|
targetlen -= tmplen;
|
||||||
|
converted += tmplen;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(src);
|
||||||
|
return converted;
|
||||||
|
}
|
|
@ -41,6 +41,8 @@
|
||||||
#include "server.h"
|
#include "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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
38
src/http.cpp
38
src/http.cpp
|
@ -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;
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
/************************************************************************
|
||||||
|
* list.c
|
||||||
|
* tausaga - environmental survival game
|
||||||
|
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* comparison functions:
|
||||||
|
* return 0 to insert
|
||||||
|
* return 1 to insert later
|
||||||
|
* return -1 to not insert at all
|
||||||
|
*/
|
||||||
|
static int list_cmp_default(void *e1, void *e2)
|
||||||
|
{
|
||||||
|
return ((*((int*)((ref_t*)e1)->ref))<(*((int*)((ref_t*)e2)->ref)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the element count in a list */
|
||||||
|
int list_count(void *list)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
|
||||||
|
while (l) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the last element in a list */
|
||||||
|
void *list_last(void *list)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
if (l) {
|
||||||
|
while (l->next) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push an element onto a list */
|
||||||
|
void *list_push(void *list, void *el)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
|
||||||
|
if (l) {
|
||||||
|
while (l->next) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
l->next = e;
|
||||||
|
e->prev = l;
|
||||||
|
e->next = NULL;
|
||||||
|
return *((ref_t**)list);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((ref_t**)list) = e;
|
||||||
|
e->next = NULL;
|
||||||
|
e->prev = NULL;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append a list to another list */
|
||||||
|
void *list_append(void *list, void *el)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
|
||||||
|
if (l) {
|
||||||
|
while (l->next) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
l->next = e;
|
||||||
|
e->prev = l;
|
||||||
|
return *((ref_t**)list);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((ref_t**)list) = e;
|
||||||
|
e->prev = NULL;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shove an element onto the start of a list */
|
||||||
|
void *list_shove(void *list, void *el)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
|
||||||
|
if (l)
|
||||||
|
l->prev = e;
|
||||||
|
|
||||||
|
*((ref_t**)list) = e;
|
||||||
|
e->next = l;
|
||||||
|
e->prev = NULL;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove an element form a list */
|
||||||
|
void *list_remove(void *list, void *el)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
|
||||||
|
if (!e->prev) {
|
||||||
|
*(ref_t**)list = e->next;
|
||||||
|
l = *((ref_t**)list);
|
||||||
|
if (l)
|
||||||
|
l->prev = NULL;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->prev->next = e->next;
|
||||||
|
if (e->next)
|
||||||
|
e->next->prev = e->prev;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the last element from a list */
|
||||||
|
void *list_pop(void *list)
|
||||||
|
{
|
||||||
|
ref_t *e = *((ref_t**)list);
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (e->next) {
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->prev) {
|
||||||
|
e->prev->next = e->next;
|
||||||
|
}else{
|
||||||
|
*((ref_t**)list) = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->next)
|
||||||
|
e->next->prev = e->prev;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the first element from a list */
|
||||||
|
void *list_pull(void *list)
|
||||||
|
{
|
||||||
|
ref_t *e = *((ref_t**)list);
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*((ref_t**)list) = e->next;
|
||||||
|
if (*((ref_t**)list))
|
||||||
|
e->next->prev = NULL;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert an element into a list before ne */
|
||||||
|
void *list_insert(void *list, void *el, void *ne)
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
ref_t *n = ne;
|
||||||
|
|
||||||
|
if (n == l || !n)
|
||||||
|
return list_shove(list,el);
|
||||||
|
|
||||||
|
e->prev = n->prev;
|
||||||
|
e->next = n;
|
||||||
|
n->prev = e;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert an element into a list based on a compare function - return 1 to insert before */
|
||||||
|
void *list_insert_cmp(void *list, void *el, int (*list_cmp)(void *e1, void *e2))
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = el;
|
||||||
|
ref_t *p = l;
|
||||||
|
ref_t *r = NULL;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (!l)
|
||||||
|
return list_push(list,el);
|
||||||
|
|
||||||
|
if (!list_cmp)
|
||||||
|
list_cmp = list_cmp_default;
|
||||||
|
|
||||||
|
((ref_t*)el)->next = NULL;
|
||||||
|
((ref_t*)el)->prev = NULL;
|
||||||
|
|
||||||
|
while (p && (c = list_cmp(e,p) > 0)) {
|
||||||
|
r = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c < 0)
|
||||||
|
return l;
|
||||||
|
|
||||||
|
if (!r)
|
||||||
|
return list_shove(list,el);
|
||||||
|
|
||||||
|
e->prev = r;
|
||||||
|
e->next = r->next;
|
||||||
|
r->next = e;
|
||||||
|
if (e->next)
|
||||||
|
e->next->prev = e;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resort a list, based on a compare function */
|
||||||
|
void *list_resort_cmp(void *list, int (*list_cmp)(void *e1, void* e2))
|
||||||
|
{
|
||||||
|
ref_t *l = *((ref_t**)list);
|
||||||
|
ref_t *e = l;
|
||||||
|
ref_t *n;
|
||||||
|
|
||||||
|
l = NULL;
|
||||||
|
|
||||||
|
if (!list_cmp)
|
||||||
|
list_cmp = list_cmp_default;
|
||||||
|
|
||||||
|
while (e) {
|
||||||
|
n = e->next;
|
||||||
|
l = list_insert_cmp(&l,e,list_cmp);
|
||||||
|
e = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef _LIST_H_
|
||||||
|
#define _LIST_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _HAVE_REF_TYPE
|
||||||
|
#define _HAVE_REF_TYPE
|
||||||
|
typedef struct ref_s {
|
||||||
|
struct ref_s *prev;
|
||||||
|
struct ref_s *next;
|
||||||
|
void *ref;
|
||||||
|
} ref_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* defined in list.c */
|
||||||
|
int list_count(void *list);
|
||||||
|
void *list_last(void *list);
|
||||||
|
void *list_push(void *list, void *el);
|
||||||
|
void *list_append(void *list, void *el);
|
||||||
|
void *list_shove(void *list, void *el);
|
||||||
|
void *list_remove(void *list, void *el);
|
||||||
|
void *list_pop(void *list);
|
||||||
|
void *list_pull(void *list);
|
||||||
|
void *list_insert(void *list, void *el, void *n);
|
||||||
|
void *list_insert_cmp(void *list, void *el, int (*list_cmp)(void *e1, void *e2));
|
||||||
|
void *list_resort_cmp(void *list, int (*list_cmp)(void *e1, void* e2));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,170 @@
|
||||||
|
/************************************************************************
|
||||||
|
* nvp.c
|
||||||
|
* tausaga - environmental survival game
|
||||||
|
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
#include "nvp.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* comparison functions:
|
||||||
|
* return 0 to insert
|
||||||
|
* return 1 to insert later
|
||||||
|
* return -1 to not insert at all
|
||||||
|
*/
|
||||||
|
static int nvp_insert_cmp(void *e1, void *e2)
|
||||||
|
{
|
||||||
|
nvp_t *n1 = e1;
|
||||||
|
nvp_t *n2 = e2;
|
||||||
|
|
||||||
|
if (n2->h > n1->h)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free memory of an nvp list, if data is non-zero, data is also freed */
|
||||||
|
void nvp_free(nvp_t **list, int data)
|
||||||
|
{
|
||||||
|
nvp_t *n;
|
||||||
|
while ((n = list_pop(list))) {
|
||||||
|
if (n->name)
|
||||||
|
free(n->name);
|
||||||
|
if (n->value)
|
||||||
|
free(n->value);
|
||||||
|
if (data && n->data)
|
||||||
|
free(n->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a name/value pair */
|
||||||
|
nvp_t *nvp_get(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = *list;
|
||||||
|
unsigned int h = hash(name);
|
||||||
|
while (c) {
|
||||||
|
if (c->h > h)
|
||||||
|
return NULL;
|
||||||
|
if (c->h == h && !strcmp(c->name,name))
|
||||||
|
return c;
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the value of a name/value pair */
|
||||||
|
char* nvp_get_str(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = nvp_get(list,name);
|
||||||
|
if (c)
|
||||||
|
return c->value;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the value of a name/value pair as an int value */
|
||||||
|
int nvp_get_int(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = nvp_get(list,name);
|
||||||
|
if (c)
|
||||||
|
return strtol(c->value,NULL,10);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the value of a name/value pair as a float value */
|
||||||
|
float nvp_get_float(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = nvp_get(list,name);
|
||||||
|
if (c)
|
||||||
|
return strtof(c->value,NULL);
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the value of a name/value pair as a boolean value */
|
||||||
|
int nvp_get_bool(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = nvp_get(list,name);
|
||||||
|
if (c && (!strcmp(c->value,"1") || !strcmp(c->value,"true")))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a name/value pair's data value */
|
||||||
|
void *nvp_get_data(nvp_t **list, char* name)
|
||||||
|
{
|
||||||
|
nvp_t *c = nvp_get(list,name);
|
||||||
|
if (c)
|
||||||
|
return c->data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the value of a name/value pair */
|
||||||
|
void nvp_set(nvp_t **list, char* name, char* value, void *data)
|
||||||
|
{
|
||||||
|
nvp_t *c = *list;
|
||||||
|
unsigned int h = hash(name);
|
||||||
|
|
||||||
|
while (c) {
|
||||||
|
if (c->h > h)
|
||||||
|
break;
|
||||||
|
if (c->h == h && !strcmp(c->name,name)) {
|
||||||
|
if (c->value) {
|
||||||
|
free(c->value);
|
||||||
|
c->value = NULL;
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
c->value = strdup(value);
|
||||||
|
if (data)
|
||||||
|
c->data = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value && !data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c = malloc(sizeof(nvp_t));
|
||||||
|
c->name = strdup(name);
|
||||||
|
c->h = h;
|
||||||
|
if (value) {
|
||||||
|
c->value = strdup(value);
|
||||||
|
}else{
|
||||||
|
c->value = NULL;
|
||||||
|
}
|
||||||
|
c->data = data;
|
||||||
|
|
||||||
|
*list = list_insert_cmp(list,c,nvp_insert_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a name/value pair to an int value */
|
||||||
|
void nvp_set_int(nvp_t **list, char* name, int value)
|
||||||
|
{
|
||||||
|
char str[20];
|
||||||
|
sprintf(str,"%d",value);
|
||||||
|
nvp_set(list,name,str,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a name/value pair to a float value */
|
||||||
|
void nvp_set_float(nvp_t **list, char* name, float value)
|
||||||
|
{
|
||||||
|
char str[20];
|
||||||
|
sprintf(str,"%f",value);
|
||||||
|
nvp_set(list,name,str,NULL);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef _NVP_H_
|
||||||
|
#define _NVP_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _HAVE_NVP_TYPE
|
||||||
|
#define _HAVE_NVP_TYPE
|
||||||
|
typedef struct nvp_s {
|
||||||
|
struct nvp_s *prev;
|
||||||
|
struct nvp_s *next;
|
||||||
|
char* name;
|
||||||
|
unsigned int h;
|
||||||
|
char* value;
|
||||||
|
void *data;
|
||||||
|
} nvp_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* defined in nvp.c */
|
||||||
|
void nvp_free(nvp_t **list, int data);
|
||||||
|
nvp_t *nvp_get(nvp_t **list, char* name);
|
||||||
|
char* nvp_get_str(nvp_t **list, char* name);
|
||||||
|
int nvp_get_int(nvp_t **list, char* name);
|
||||||
|
float nvp_get_float(nvp_t **list, char* name);
|
||||||
|
int nvp_get_bool(nvp_t **list, char* name);
|
||||||
|
void *nvp_get_data(nvp_t **list, char* name);
|
||||||
|
void nvp_set(nvp_t **list, char* name, char* value, void *data);
|
||||||
|
void nvp_set_int(nvp_t **list, char* name, int value);
|
||||||
|
void nvp_set_float(nvp_t **list, char* name, float value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -4858,16 +4858,16 @@ core::list<PlayerInfo> Server::getPlayerInfo()
|
||||||
|
|
||||||
core::list<PlayerInfo> list;
|
core::list<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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue