0

added slime overlay, colors chunks green if slimes can spawn

This commit is contained in:
Aaron Griffith
2012-06-05 23:18:15 -04:00
parent f4a1c32d1a
commit 05bfaaf967
8 changed files with 150 additions and 8 deletions

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the Minecraft Overviewer.
*
* Minecraft Overviewer 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.
*
* Minecraft Overviewer 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 the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "overlay.h"
#include <math.h>
typedef struct {
/* inherits from overlay */
RenderPrimitiveOverlay parent;
long seed;
} RenderPrimitiveSlime;
/*
* random_* are a re-implementation of java's Random() class
* since Minecraft's slime algorithm depends on it
* http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html
*/
static void random_set_seed(long *seed, long new_seed) {
*seed = (new_seed ^ 0x5deece66dL) & ((1L << 48) - 1);
}
static int random_next(long *seed, int bits) {
*seed = (*seed * 0x5deece66dL + 0xbL) & ((1L << 48) - 1);
return (int)(*seed >> (48 - bits));
}
static int random_next_int(long *seed, int n) {
int bits, val;
if (n <= 0) {
/* invalid */
return 0;
}
if ((n & -n) == n) {
/* n is a power of two */
return (int)((n * (long)random_next(seed, 31)) >> 31);
}
do {
bits = random_next(seed, 31);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
static int is_slime(long map_seed, long chunkx, long chunkz) {
/* lots of magic numbers, but they're all correct! I swear! */
long seed;
random_set_seed(&seed, map_seed + (chunkx * chunkx * 0x4c1906L) + (chunkx * 0x5ac0dbL) + (chunkz * chunkz * 0x4307a7L) + (chunkz * 0x5f24fL) ^ 0x3ad8025fL);
return (random_next_int(&seed, 10) == 0);
}
static void get_color(void *data, RenderState *state,
unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a) {
RenderPrimitiveSlime *self = (RenderPrimitiveSlime *)data;
/* set a nice, pretty green color */
*r = 40;
*g = 230;
*b = 40;
/* default to no overlay, until told otherwise */
*a = 0;
if (is_slime(self->seed, state->chunkx, state->chunkz)) {
/* slimes can spawn! */
*a = 240;
}
}
static int
overlay_slime_start(void *data, RenderState *state, PyObject *support) {
RenderPrimitiveSlime *self;
PyObject *pyseed;
/* first, chain up */
int ret = primitive_overlay.start(data, state, support);
if (ret != 0)
return ret;
/* now do custom initializations */
self = (RenderPrimitiveSlime *)data;
self->parent.get_color = get_color;
pyseed = PyObject_GetAttrString(state->world, "seed");
if (!pyseed)
return 1;
self->seed = PyInt_AsLong(pyseed);
Py_DECREF(pyseed);
if (PyErr_Occurred())
return 1;
return 0;
}
static void
overlay_slime_finish(void *data, RenderState *state) {
/* chain up */
primitive_overlay.finish(data, state);
}
RenderPrimitiveInterface primitive_overlay_slime = {
"overlay-slime",
sizeof(RenderPrimitiveSlime),
overlay_slime_start,
overlay_slime_finish,
NULL,
NULL,
overlay_draw,
};