1
0
mirror of https://github.com/luanti-org/luanti.git synced 2025-10-23 20:55:43 +02:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
poet.nohit
2015-03-23 22:50:08 -06:00
31 changed files with 633 additions and 393 deletions

View File

@@ -311,7 +311,7 @@ $(OPENSSL_LIB): $(OPENSSL_TIMESTAMP)
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-openssl; \
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN} --system=linux-x86_64; \
--install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
CC=${CROSS_PREFIX}gcc ./Configure android-${TARGET_ARCH} no-idea no-seed -no-sha0 -DL_ENDIAN;\
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \
@@ -359,7 +359,7 @@ $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-leveldb; \
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN} --system=linux-x86_64; \
--install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \
@@ -518,7 +518,7 @@ $(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB)
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-curl; \
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN} --system=linux-x86_64; \
--install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \

View File

@@ -74,6 +74,7 @@ IF(GETTEXT_FOUND)
SET(GETTEXT_MO_DEST_PATH ${LOCALEDIR}/<locale>/LC_MESSAGES)
FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*")
LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES minetest.pot)
LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES timestamp)
MACRO(SET_MO_PATHS _buildvar _destvar _locale)
STRING(REPLACE "<locale>" ${_locale} ${_buildvar} ${GETTEXT_MO_BUILD_PATH})
STRING(REPLACE "<locale>" ${_locale} ${_destvar} ${GETTEXT_MO_DEST_PATH})

View File

@@ -2336,7 +2336,6 @@ This is basically a reference to a C++ `ServerActiveObject`
* `right_click(clicker)`; `clicker` is another `ObjectRef`
* `get_hp()`: returns number of hitpoints (2 * number of hearts)
* `set_hp(hp)`: set number of hitpoints (2 * number of hearts)
* `apply_damage(damage)`: set amount of damage to object. If damage < 0, heal the target
* `get_inventory()`: returns an `InvRef`
* `get_wield_list()`: returns the name of the inventory list the wielded item is in
* `get_wield_index()`: returns the index of the wielded item
@@ -2515,7 +2514,8 @@ an itemstring, a table or `nil`.
Returns taken `ItemStack`.
### `PseudoRandom`
A pseudorandom number generator.
A 16-bit pseudorandom number generator.
Uses a well-known LCG algorithm introduced by K&R.
It can be created via `PseudoRandom(seed)`.
@@ -2525,6 +2525,19 @@ It can be created via `PseudoRandom(seed)`.
* `((max - min) == 32767) or ((max-min) <= 6553))` must be true
due to the simple implementation making bad distribution otherwise.
### `PcgRandom`
A 32-bit pseudorandom number generator.
Uses PCG32, an algorithm of the permuted congruential generator family, offering very strong randomness.
It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`.
#### Methods
* `next()`: return next integer random number [`-2147483648`...`2147483647`]
* `next(min, max)`: return next integer random number [`min`...`max`]
* `rand_normal_dist(min, max, num_trials=6)`: return normally distributed random number [`min`...`max`]
* This is only a rough approximation of a normal distribution with mean=(max-min)/2 and variance=1
* Increasing num_trials improves accuracy of the approximation
### `PerlinNoise`
A perlin noise generator.
It can be created via `PerlinNoise(seed, octaves, persistence, scale)`

View File

@@ -197,7 +197,7 @@
# which PNG optimizers usually discard, sometimes resulting in a dark or
# light edge to transparent textures. Apply this filter to clean that up
# at texture load time.
#texture_clean_transparent = true
#texture_clean_transparent = false
# When using bilinear/trilinear/anisotropic filters, low-resolution textures
# can be blurred, so automatically upscale them with nearest-neighbor
# interpolation to preserve crisp pixels. This sets the minimum texture size
@@ -205,7 +205,7 @@
# memory. Powers of 2 are recommended. Setting this higher than 1 may not
# have a visible effect unless bilinear/trilinear/anisotropic filtering is
# enabled.
#texture_min_size = 16
#texture_min_size = 64
# Set to true to pre-generate all item visuals
#preload_item_visuals = false
# Set to true to enable shaders. Disable them if video_driver = direct3d9/8.

View File

@@ -192,13 +192,18 @@ video::IImage *textureMinSizeUpscale(video::IVideoDriver *driver, video::IImage
if(orig == NULL)
return orig;
s32 scaleto = g_settings->getS32("texture_min_size");
if (scaleto > 0) {
if (scaleto > 1) {
const core::dimension2d<u32> dim = orig->getDimension();
// Don't upscale 1px images. They don't benefit from it anyway
// (wouldn't have been blurred) and MIGHT be sun/moon tonemaps.
if ((dim.Width <= 1) || (dim.Height <= 1))
return orig;
/* Calculate scaling needed to make the shortest texture dimension
* equal to the target minimum. If e.g. this is a vertical frames
* animation, the short dimension will be the real size.
*/
const core::dimension2d<u32> dim = orig->getDimension();
u32 xscale = scaleto / dim.Width;
u32 yscale = scaleto / dim.Height;
u32 scale = (xscale > yscale) ? xscale : yscale;

View File

@@ -149,8 +149,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("anisotropic_filter", "false");
settings->setDefault("bilinear_filter", "false");
settings->setDefault("trilinear_filter", "false");
settings->setDefault("texture_clean_transparent", "true");
settings->setDefault("texture_min_size", "16");
settings->setDefault("texture_clean_transparent", "false");
settings->setDefault("texture_min_size", "64");
settings->setDefault("preload_item_visuals", "false");
settings->setDefault("enable_bumpmapping", "false");
settings->setDefault("enable_parallax_occlusion", "false");

View File

@@ -515,14 +515,10 @@ void MapgenParams::load(const Settings &settings)
std::string seed_str;
const char *seed_name = (&settings == g_settings) ? "fixed_map_seed" : "seed";
if (settings.getNoEx(seed_name, seed_str) && !seed_str.empty()) {
if (settings.getNoEx(seed_name, seed_str) && !seed_str.empty())
seed = read_seed(seed_str.c_str());
} else {
seed = ((u64)(myrand() & 0xFFFF) << 0) |
((u64)(myrand() & 0xFFFF) << 16) |
((u64)(myrand() & 0xFFFF) << 32) |
((u64)(myrand() & 0xFFFF) << 48);
}
else
myrand_bytes(&seed, sizeof(seed));
settings.getNoEx("mg_name", mg_name);
settings.getS16NoEx("water_level", water_level);

View File

@@ -204,6 +204,8 @@ public:
virtual GenElement *getByName(const std::string &name);
INodeDefManager *getNodeDef() { return m_ndef; }
protected:
INodeDefManager *m_ndef;
std::vector<GenElement *> m_elements;

View File

@@ -377,9 +377,9 @@ int MapgenV5::generateBaseTerrain()
stone_surface_max_y = y;
}
}
index2d = index2d - ystride;
index2d -= ystride;
}
index2d = index2d + ystride;
index2d += ystride;
}
return stone_surface_max_y;
@@ -391,10 +391,6 @@ bool MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
if (node_max.Y < water_level)
return false;
MapNode n_air(CONTENT_AIR);
MapNode n_stone(c_stone);
MapNode n_water(c_water_source);
v3s16 em = vm->m_area.getExtent();
u32 index = 0;
bool desert_stone = false;
@@ -496,9 +492,9 @@ void MapgenV5::generateCaves(int max_stone_y)
if (d1*d2 > 0.125)
vm->m_data[i] = MapNode(CONTENT_AIR);
}
index2d = index2d - ystride;
index2d -= ystride;
}
index2d = index2d + ystride;
index2d += ystride;
}
if (node_max.Y > LARGE_CAVE_DEPTH)
@@ -528,27 +524,25 @@ void MapgenV5::dustTopNodes()
if (biome->c_dust == CONTENT_IGNORE)
continue;
s16 y_full_max = full_node_max.Y;
u32 vi_full_max = vm->m_area.index(x, y_full_max, z);
content_t c_full_max = vm->m_data[vi_full_max].getContent();
u32 vi = vm->m_area.index(x, full_node_max.Y, z);
content_t c_full_max = vm->m_data[vi].getContent();
s16 y_start;
if (c_full_max == CONTENT_AIR) {
y_start = y_full_max - 1;
y_start = full_node_max.Y - 1;
} else if (c_full_max == CONTENT_IGNORE) {
s16 y_max = node_max.Y;
u32 vi_max = vm->m_area.index(x, y_max, z);
content_t c_max = vm->m_data[vi_max].getContent();
vi = vm->m_area.index(x, node_max.Y + 1, z);
content_t c_max = vm->m_data[vi].getContent();
if (c_max == CONTENT_AIR)
y_start = y_max - 1;
y_start = node_max.Y;
else
continue;
} else {
continue;
}
u32 vi = vm->m_area.index(x, y_start, z);
vi = vm->m_area.index(x, y_start, z);
for (s16 y = y_start; y >= node_min.Y - 1; y--) {
if (vm->m_data[vi].getContent() != CONTENT_AIR)
break;

View File

@@ -877,9 +877,10 @@ void MapgenV6::placeTreesAndJungleGrass()
for (u32 i = 0; i < grass_count; i++) {
s16 x = grassrandom.range(p2d_min.X, p2d_max.X);
s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y);
s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////optimize this!
if (y < water_level || y < node_min.Y || y > node_max.Y)
int mapindex = central_area_size.X * (z - node_min.Z)
+ (x - node_min.X);
s16 y = heightmap[mapindex];
if (y < water_level)
continue;
u32 vi = vm->m_area.index(x, y, z);
@@ -895,7 +896,9 @@ void MapgenV6::placeTreesAndJungleGrass()
for (u32 i = 0; i < tree_count; i++) {
s16 x = myrand_range(p2d_min.X, p2d_max.X);
s16 z = myrand_range(p2d_min.Y, p2d_max.Y);
s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////////optimize this!
int mapindex = central_area_size.X * (z - node_min.Z)
+ (x - node_min.X);
s16 y = heightmap[mapindex];
// Don't make a tree under water level
// Don't make a tree so high that it doesn't fit
if(y < water_level || y > node_max.Y - 6)

View File

@@ -58,7 +58,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
//// amount of elements to skip for the next index
//// for noise/height/biome maps (not vmanip)
this->ystride = csize.X;
this->zstride = csize.X * csize.Y;
this->zstride = csize.X * (csize.Y + 2);
this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z];
@@ -77,10 +77,10 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
noise_ridge_uwater = new Noise(&sp->np_ridge_uwater, seed, csize.X, csize.Z);
//// 3d terrain noise
noise_mountain = new Noise(&sp->np_mountain, seed, csize.X, csize.Y, csize.Z);
noise_ridge = new Noise(&sp->np_ridge, seed, csize.X, csize.Y, csize.Z);
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y, csize.Z);
noise_mountain = new Noise(&sp->np_mountain, seed, csize.X, csize.Y + 2, csize.Z);
noise_ridge = new Noise(&sp->np_ridge, seed, csize.X, csize.Y + 2, csize.Z);
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z);
//// Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@@ -314,7 +314,9 @@ void MapgenV7::makeChunk(BlockMakeData *data)
updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
if (flags & MG_LIGHT)
calcLighting(node_min, node_max);
calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
full_node_min, full_node_max);
//setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
// node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF);
@@ -326,7 +328,7 @@ void MapgenV7::calculateNoise()
{
//TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
int x = node_min.X;
int y = node_min.Y;
int y = node_min.Y - 1;
int z = node_min.Z;
noise_terrain_persist->perlinMap2D(x, z);
@@ -489,8 +491,8 @@ int MapgenV7::generateBaseTerrain()
if (surface_y > stone_surface_max_y)
stone_surface_max_y = surface_y;
u32 i = vm->m_area.index(x, node_min.Y, z);
for (s16 y = node_min.Y; y <= node_max.Y; y++) {
u32 i = vm->m_area.index(x, node_min.Y - 1, z);
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
if (y <= surface_y)
vm->m_data[i] = n_stone;
@@ -516,7 +518,7 @@ int MapgenV7::generateMountainTerrain(int ymax)
u32 j = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 y = node_min.Y; y <= node_max.Y; y++) {
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
u32 vi = vm->m_area.index(node_min.X, y, z);
for (s16 x = node_min.X; x <= node_max.X; x++) {
int index = (z - node_min.Z) * csize.X + (x - node_min.X);
@@ -549,7 +551,7 @@ void MapgenV7::generateRidgeTerrain()
float width = 0.2; // TODO: figure out acceptable perlin noise values
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 y = node_min.Y; y <= node_max.Y; y++) {
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
u32 vi = vm->m_area.index(node_min.X, y, z);
for (s16 x = node_min.X; x <= node_max.X; x++, index++, vi++) {
int j = (z - node_min.Z) * csize.X + (x - node_min.X);
@@ -583,10 +585,6 @@ bool MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
if (node_max.Y < water_level)
return false;
MapNode n_air(CONTENT_AIR);
MapNode n_stone(c_stone);
MapNode n_water(c_water_source);
v3s16 em = vm->m_area.getExtent();
u32 index = 0;
bool desert_stone = false;
@@ -608,16 +606,6 @@ bool MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
content_t c = vm->m_data[i].getContent();
// It could be the case that the elevation is equal to the chunk
// boundary, but the chunk above has not been generated yet
if (y == node_max.Y && c_above == CONTENT_IGNORE &&
y == heightmap[index] && c == c_stone) {
int j = (z - node_min.Z) * zstride +
(y - node_min.Y) * ystride +
(x - node_min.X);
have_air = !getMountainTerrainFromMap(j, index, y);
}
if (c != CONTENT_IGNORE && c != CONTENT_AIR && (y == node_max.Y || have_air)) {
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
dfiller = biome->depth_filler + noise_filler_depth->result[index];
@@ -691,27 +679,25 @@ void MapgenV7::dustTopNodes()
if (biome->c_dust == CONTENT_IGNORE)
continue;
s16 y_full_max = full_node_max.Y;
u32 vi_full_max = vm->m_area.index(x, y_full_max, z);
content_t c_full_max = vm->m_data[vi_full_max].getContent();
u32 vi = vm->m_area.index(x, full_node_max.Y, z);
content_t c_full_max = vm->m_data[vi].getContent();
s16 y_start;
if (c_full_max == CONTENT_AIR) {
y_start = y_full_max - 1;
y_start = full_node_max.Y - 1;
} else if (c_full_max == CONTENT_IGNORE) {
s16 y_max = node_max.Y;
u32 vi_max = vm->m_area.index(x, y_max, z);
content_t c_max = vm->m_data[vi_max].getContent();
vi = vm->m_area.index(x, node_max.Y + 1, z);
content_t c_max = vm->m_data[vi].getContent();
if (c_max == CONTENT_AIR)
y_start = y_max - 1;
y_start = node_max.Y;
else
continue;
} else {
continue;
}
u32 vi = vm->m_area.index(x, y_start, z);
vi = vm->m_area.index(x, y_start, z);
for (s16 y = y_start; y >= node_min.Y - 1; y--) {
if (vm->m_data[vi].getContent() != CONTENT_AIR)
break;
@@ -831,7 +817,7 @@ void MapgenV7::generateCaves(int max_stone_y)
u32 index2d = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++) {
for (s16 y = node_min.Y; y <= node_max.Y; y++) {
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
u32 i = vm->m_area.index(node_min.X, y, z);
for (s16 x = node_min.X; x <= node_max.X;
x++, i++, index++, index2d++) {

View File

@@ -308,7 +308,7 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed,
}
// randval ranges from -1..1
float randval = (float)pr.next() / (PSEUDORANDOM_MAX / 2) - 1.f;
float randval = (float)pr.next() / (pr.RANDOM_RANGE / 2) - 1.f;
float noiseval = contour(noise->result[index]);
float noiseval2 = contour(noise2->result[index]);
if (noiseval * noiseval2 + randval * random_factor < nthresh)

View File

@@ -207,6 +207,11 @@ bool Schematic::loadSchematicFromFile(const char *filename, INodeDefManager *nde
bool have_cignore = false;
std::ifstream is(filename, std::ios_base::binary);
if (!is.good()) {
errorstream << "loadSchematicFile: unable to open file '"
<< filename << "'" << std::endl;
return false;
}
u32 signature = readU32(is);
if (signature != MTSCHEM_FILE_SIGNATURE) {

View File

@@ -2924,7 +2924,7 @@ void Connection::Send(u16 peer_id, u8 channelnum,
ConnectionCommand c;
c.send(peer_id, channelnum, pkt->oldForgePacket(), reliable);
c.send(peer_id, channelnum, pkt, reliable);
putCommand(c);
}

View File

@@ -437,19 +437,12 @@ struct ConnectionCommand
peer_id = peer_id_;
}
void send(u16 peer_id_, u8 channelnum_,
SharedBuffer<u8> data_, bool reliable_)
NetworkPacket* pkt, bool reliable_)
{
type = CONNCMD_SEND;
peer_id = peer_id_;
channelnum = channelnum_;
data = data_;
reliable = reliable_;
}
void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
{
type = CONNCMD_SEND_TO_ALL;
channelnum = channelnum_;
data = data_;
data = pkt->oldForgePacket();
reliable = reliable_;
}

View File

@@ -510,7 +510,7 @@ NetworkPacket& NetworkPacket::operator<<(video::SColor src)
return *this;
}
SharedBuffer<u8> NetworkPacket::oldForgePacket()
Buffer<u8> NetworkPacket::oldForgePacket()
{
SharedBuffer<u8> sb(m_datasize + 2);
writeU16(&sb[0], m_command);

View File

@@ -104,7 +104,7 @@ public:
NetworkPacket& operator<<(video::SColor src);
// Temp, we remove SharedBuffer when migration finished
SharedBuffer<u8> oldForgePacket();
Buffer<u8> oldForgePacket();
private:
template<typename T> void checkDataSize()
{

View File

@@ -62,6 +62,94 @@ FlagDesc flagdesc_noiseparams[] = {
///////////////////////////////////////////////////////////////////////////////
PcgRandom::PcgRandom(u64 state, u64 seq)
{
seed(state, seq);
}
void PcgRandom::seed(u64 state, u64 seq)
{
m_state = 0U;
m_inc = (seq << 1u) | 1u;
next();
m_state += state;
next();
}
u32 PcgRandom::next()
{
u64 oldstate = m_state;
m_state = oldstate * 6364136223846793005ULL + m_inc;
u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
u32 rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
u32 PcgRandom::range(u32 bound)
{
/*
If the bound is not a multiple of the RNG's range, it may cause bias,
e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
Using rand() % 3, the number 0 would be twice as likely to appear.
With a very large RNG range, the effect becomes less prevalent but
still present. This can be solved by modifying the range of the RNG
to become a multiple of bound by dropping values above the a threshhold.
In our example, threshhold == 4 - 3 = 1 % 3 == 1, so reject 0, thus
making the range 3 with no bias.
This loop looks dangerous, but will always terminate due to the
RNG's property of uniformity.
*/
u32 threshhold = -bound % bound;
u32 r;
while ((r = next()) < threshhold)
;
return r % bound;
}
s32 PcgRandom::range(s32 min, s32 max)
{
assert(max >= min);
u32 bound = max - min + 1;
return range(bound) + min;
}
void PcgRandom::bytes(void *out, size_t len)
{
u8 *outb = (u8 *)out;
int bytes_left = 0;
u32 r;
while (len--) {
if (bytes_left == 0) {
bytes_left = sizeof(u32);
r = next();
}
*outb = r & 0xFF;
outb++;
bytes_left--;
r >>= 8;
}
}
s32 PcgRandom::randNormalDist(s32 min, s32 max, int num_trials)
{
s32 accum = 0;
for (int i = 0; i != num_trials; i++)
accum += range(min, max);
return ((float)accum / num_trials) + 0.5f;
}
///////////////////////////////////////////////////////////////////////////////
float noise2d(int x, int y, int seed)
{

View File

@@ -30,47 +30,67 @@
#include "irr_v3d.h"
#include "util/string.h"
#define PSEUDORANDOM_MAX 32767
extern FlagDesc flagdesc_noiseparams[];
class PseudoRandom
{
// Note: this class is not polymorphic so that its high level of
// optimizability may be preserved in the common use case
class PseudoRandom {
public:
PseudoRandom(): m_next(0)
const static u32 RANDOM_RANGE = 32767;
inline PseudoRandom(int seed=0):
m_next(seed)
{
}
PseudoRandom(int seed): m_next(seed)
{
}
void seed(int seed)
inline void seed(int seed)
{
m_next = seed;
}
// Returns 0...PSEUDORANDOM_MAX
int next()
inline int next()
{
m_next = m_next * 1103515245 + 12345;
return((unsigned)(m_next/65536) % (PSEUDORANDOM_MAX + 1));
return (unsigned)(m_next / 65536) % (RANDOM_RANGE + 1);
}
int range(int min, int max)
inline int range(int min, int max)
{
if (max-min > (PSEUDORANDOM_MAX + 1) / 10)
{
//dstream<<"WARNING: PseudoRandom::range: max > 32767"<<std::endl;
assert("Something wrong with random number" == NULL);
}
if(min > max)
{
assert("Something wrong with random number" == NULL);
//return max;
}
return (next()%(max-min+1))+min;
assert(max >= min);
/*
Here, we ensure the range is not too large relative to RANDOM_MAX,
as otherwise the effects of bias would become noticable. Unlike
PcgRandom, we cannot modify this RNG's range as it would change the
output of this RNG for reverse compatibility.
*/
assert((u32)(max - min) <= (RANDOM_RANGE + 1) / 10);
return (next() % (max - min + 1)) + min;
}
private:
int m_next;
};
class PcgRandom {
public:
const static s32 RANDOM_MIN = -0x7fffffff - 1;
const static s32 RANDOM_MAX = 0x7fffffff;
const static u32 RANDOM_RANGE = 0xffffffff;
PcgRandom(u64 state=0x853c49e6748fea9bULL, u64 seq=0xda3e39cb94b95bdbULL);
void seed(u64 state, u64 seq=0xda3e39cb94b95bdbULL);
u32 next();
u32 range(u32 bound);
s32 range(s32 min, s32 max);
void bytes(void *out, size_t len);
s32 randNormalDist(s32 min, s32 max, int num_trials=6);
private:
u64 m_state;
u64 m_inc;
};
#define NOISE_FLAG_DEFAULTS 0x01
#define NOISE_FLAG_EASED 0x02
#define NOISE_FLAG_ABSVALUE 0x04
@@ -89,7 +109,8 @@ struct NoiseParams {
float lacunarity;
u32 flags;
NoiseParams() {
NoiseParams()
{
offset = 0.0f;
scale = 1.0f;
spread = v3f(250, 250, 250);

View File

@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include <fstream>
#include "jthread/jmutexautolock.h"
#include "util/numeric.h"
#include "hud.h"
#include "constants.h"
@@ -240,6 +241,8 @@ void Player::deSerialize(std::istream &is, std::string playername)
u32 Player::addHud(HudElement *toadd)
{
JMutexAutoLock lock(m_mutex);
u32 id = getFreeHudID();
if (id < hud.size())
@@ -252,6 +255,8 @@ u32 Player::addHud(HudElement *toadd)
HudElement* Player::getHud(u32 id)
{
JMutexAutoLock lock(m_mutex);
if (id < hud.size())
return hud[id];
@@ -260,6 +265,8 @@ HudElement* Player::getHud(u32 id)
HudElement* Player::removeHud(u32 id)
{
JMutexAutoLock lock(m_mutex);
HudElement* retval = NULL;
if (id < hud.size()) {
retval = hud[id];
@@ -270,6 +277,8 @@ HudElement* Player::removeHud(u32 id)
void Player::clearHud()
{
JMutexAutoLock lock(m_mutex);
while(!hud.empty()) {
delete hud.back();
hud.pop_back();

View File

@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_bloated.h"
#include "inventory.h"
#include "constants.h" // BS
#include "jthread/jmutex.h"
#include <list>
#define PLAYERNAME_SIZE 20
@@ -202,7 +203,7 @@ public:
return m_collisionbox;
}
u32 getFreeHudID() const {
u32 getFreeHudID() {
size_t size = hud.size();
for (size_t i = 0; i != size; i++) {
if (!hud[i])
@@ -318,6 +319,11 @@ protected:
bool m_dirty;
std::vector<HudElement *> hud;
private:
// Protect some critical areas
// hud for example can be modified by EmergeThread
// and ServerThread
JMutex m_mutex;
};

View File

@@ -393,6 +393,8 @@ int ModApiCraft::l_get_craft_recipe(lua_State *L)
std::vector<CraftDefinition*> recipes = server->cdef()
->getCraftRecipes(output, server, 1);
lua_createtable(L, 1, 0);
if (recipes.empty()) {
lua_pushnil(L);
lua_setfield(L, -2, "items");

View File

@@ -89,7 +89,7 @@ struct EnumString ModApiMapgen::es_Rotation[] =
///////////////////////////////////////////////////////////////////////////////
bool read_schematic(lua_State *L, int index, Schematic *schem,
bool read_schematic_def(lua_State *L, int index, Schematic *schem,
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
{
//// Get schematic size
@@ -175,20 +175,45 @@ bool read_schematic(lua_State *L, int index, Schematic *schem,
}
bool get_schematic(lua_State *L, int index, Schematic *schem,
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
Schematic *get_schematic(lua_State *L, int index, SchematicManager *schemmgr,
std::map<std::string, std::string> &replace_names)
{
if (index < 0)
index = lua_gettop(L) + 1 + index;
if (lua_istable(L, index)) {
return read_schematic(L, index, schem, ndef, replace_names);
} else if (lua_isstring(L, index)) {
Schematic *schem;
if (lua_isnumber(L, index)) {
return (Schematic *)schemmgr->get(lua_tointeger(L, index));
} else if (lua_istable(L, index)) {
schem = new Schematic;
if (!read_schematic_def(L, index, schem,
schemmgr->getNodeDef(), replace_names)) {
delete schem;
return NULL;
}
} else if (lua_isstring(L, index)) {
const char *filename = lua_tostring(L, index);
return schem->loadSchematicFromFile(filename, ndef, replace_names);
schem = (Schematic *)schemmgr->getByName(filename);
if (schem)
return schem;
schem = new Schematic;
if (!schem->loadSchematicFromFile(filename,
schemmgr->getNodeDef(), replace_names)) {
delete schem;
return NULL;
}
} else {
return false;
return NULL;
}
if (schemmgr->add(schem) == (u32)-1) {
delete schem;
return 0;
}
return schem;
}
@@ -469,32 +494,10 @@ int ModApiMapgen::l_register_biome(lua_State *L)
ndef->pendNodeResolve(nri);
verbosestream << "register_biome: " << b->name << std::endl;
lua_pushinteger(L, id);
return 1;
}
int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
{
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
bmgr->clear();
return 0;
}
int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
{
DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
dmgr->clear();
return 0;
}
int ModApiMapgen::l_clear_registered_ores(lua_State *L)
{
OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
omgr->clear();
return 0;
}
// register_decoration({lots of stuff})
int ModApiMapgen::l_register_decoration(lua_State *L)
{
@@ -504,6 +507,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
"deco_type", es_DecorationType, -1);
@@ -562,7 +566,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
success = regDecoSimple(L, nri, (DecoSimple *)deco);
break;
case DECO_SCHEMATIC:
success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
success = regDecoSchematic(L, schemmgr, (DecoSchematic *)deco);
break;
case DECO_LSYSTEM:
break;
@@ -582,7 +586,6 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
}
verbosestream << "register_decoration: " << deco->name << std::endl;
lua_pushinteger(L, id);
return 1;
}
@@ -627,8 +630,8 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
return true;
}
bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
DecoSchematic *deco)
bool ModApiMapgen::regDecoSchematic(lua_State *L,
SchematicManager *schemmgr, DecoSchematic *deco)
{
int index = 1;
@@ -641,19 +644,12 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
read_schematic_replacements(L, replace_names, lua_gettop(L));
lua_pop(L, 1);
// TODO(hmmmm): get a ref from registered schematics
Schematic *schem = new Schematic;
lua_getfield(L, index, "schematic");
if (!get_schematic(L, -1, schem, ndef, replace_names)) {
lua_pop(L, 1);
delete schem;
return false;
}
Schematic *schem = get_schematic(L, -1, schemmgr, replace_names);
lua_pop(L, 1);
deco->schematic = schem;
return true;
return schem != NULL;
}
// register_ore({lots of stuff})
@@ -741,11 +737,100 @@ int ModApiMapgen::l_register_ore(lua_State *L)
ndef->pendNodeResolve(nri);
verbosestream << "register_ore: " << ore->name << std::endl;
lua_pushinteger(L, id);
return 1;
}
// register_schematic({schematic}, replacements={})
int ModApiMapgen::l_register_schematic(lua_State *L)
{
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
std::map<std::string, std::string> replace_names;
if (lua_istable(L, 2))
read_schematic_replacements(L, replace_names, 2);
Schematic *schem = get_schematic(L, 1, schemmgr, replace_names);
if (!schem)
return 0;
printf("register_schematic!\n");
verbosestream << "register_schematic: " << schem->name << std::endl;
lua_pushinteger(L, schem->id);
return 1;
}
// clear_registered_biomes()
int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
{
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
bmgr->clear();
return 0;
}
// clear_registered_decorations()
int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
{
DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
dmgr->clear();
return 0;
}
// clear_registered_ores()
int ModApiMapgen::l_clear_registered_ores(lua_State *L)
{
OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
omgr->clear();
return 0;
}
// clear_registered_schematics()
int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
{
SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr;
smgr->clear();
return 0;
}
// generate_ores(vm, p1, p2, [ore_id])
int ModApiMapgen::l_generate_ores(lua_State *L)
{
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
mg.seed = emerge->params.seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
v3s16 pmin = read_v3s16(L, 2);
v3s16 pmax = read_v3s16(L, 3);
emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
return 0;
}
// generate_decorations(vm, p1, p2, [deco_id])
int ModApiMapgen::l_generate_decorations(lua_State *L)
{
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
mg.seed = emerge->params.seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
v3s16 pmin = read_v3s16(L, 2);
v3s16 pmax = read_v3s16(L, 3);
emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
return 0;
}
// create_schematic(p1, p2, probability_list, filename)
int ModApiMapgen::l_create_schematic(lua_State *L)
{
@@ -806,53 +891,11 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
return 1;
}
// generate_ores(vm, p1, p2, [ore_id])
int ModApiMapgen::l_generate_ores(lua_State *L)
{
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
mg.seed = emerge->params.seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
v3s16 pmin = read_v3s16(L, 2);
v3s16 pmax = read_v3s16(L, 3);
emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
return 0;
}
// generate_decorations(vm, p1, p2, [deco_id])
int ModApiMapgen::l_generate_decorations(lua_State *L)
{
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
mg.seed = emerge->params.seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
v3s16 pmin = read_v3s16(L, 2);
v3s16 pmax = read_v3s16(L, 3);
emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
return 0;
}
// place_schematic(p, schematic, rotation, replacement)
int ModApiMapgen::l_place_schematic(lua_State *L)
{
Schematic schem;
Map *map = &(getEnv(L)->getMap());
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
//// Read position
v3s16 p = read_v3s16(L, 1);
@@ -873,12 +916,14 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
read_schematic_replacements(L, replace_names, 4);
//// Read schematic
if (!get_schematic(L, 2, &schem, ndef, replace_names)) {
Schematic *schem = get_schematic(L, 2, schemmgr, replace_names);
if (!schem) {
errorstream << "place_schematic: failed to get schematic" << std::endl;
return 0;
}
schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef);
schem->placeStructure(map, p, 0, (Rotation)rot, force_placement,
schemmgr->getNodeDef());
return 1;
}
@@ -895,14 +940,15 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(register_biome);
API_FCT(register_decoration);
API_FCT(register_ore);
API_FCT(register_schematic);
API_FCT(clear_registered_biomes);
API_FCT(clear_registered_decorations);
API_FCT(clear_registered_ores);
API_FCT(clear_registered_schematics);
API_FCT(generate_ores);
API_FCT(generate_decorations);
API_FCT(create_schematic);
API_FCT(place_schematic);
}

View File

@@ -26,6 +26,7 @@ class INodeDefManager;
struct NodeResolveInfo;
class DecoSimple;
class DecoSchematic;
class SchematicManager;
class ModApiMapgen : public ModApiBase {
private:
@@ -56,12 +57,18 @@ private:
// register_ore({lots of stuff})
static int l_register_ore(lua_State *L);
// register_schematic({schematic}, replacements={})
static int l_register_schematic(lua_State *L);
// clear_registered_biomes()
static int l_clear_registered_biomes(lua_State *L);
// clear_registered_decorations()
static int l_clear_registered_decorations(lua_State *L);
// clear_registered_schematics()
static int l_clear_registered_schematics(lua_State *L);
// generate_ores(vm, p1, p2)
static int l_generate_ores(lua_State *L);
@@ -80,7 +87,7 @@ private:
static bool regDecoSimple(lua_State *L,
NodeResolveInfo *nri, DecoSimple *deco);
static bool regDecoSchematic(lua_State *L,
INodeDefManager *ndef, DecoSchematic *deco);
SchematicManager *schemmgr, DecoSchematic *deco);
static struct EnumString es_BiomeTerrainType[];
static struct EnumString es_DecorationType[];

View File

@@ -23,12 +23,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "log.h"
// garbage collector
int LuaPerlinNoise::gc_object(lua_State *L)
///////////////////////////////////////
/*
LuaPerlinNoise
*/
LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
np(*params)
{
}
LuaPerlinNoise::~LuaPerlinNoise()
{
LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
delete o;
return 0;
}
@@ -54,19 +61,6 @@ int LuaPerlinNoise::l_get3d(lua_State *L)
}
LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
np(*params)
{
}
LuaPerlinNoise::~LuaPerlinNoise()
{
}
// LuaPerlinNoise(seed, octaves, persistence, scale)
// Creates an LuaPerlinNoise and leaves it on top of stack
int LuaPerlinNoise::create_object(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -91,14 +85,22 @@ int LuaPerlinNoise::create_object(lua_State *L)
}
LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg)
int LuaPerlinNoise::gc_object(lua_State *L)
{
LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
delete o;
return 0;
}
LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
{
NO_MAP_LOCK_REQUIRED;
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
return *(LuaPerlinNoise**)ud; // unbox pointer
return *(LuaPerlinNoise **)ud;
}
@@ -111,7 +113,7 @@ void LuaPerlinNoise::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -121,12 +123,11 @@ void LuaPerlinNoise::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
lua_pop(L, 1); // drop metatable
lua_pop(L, 1);
luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // drop methodtable
luaL_openlib(L, 0, methods, 0);
lua_pop(L, 1);
// Can be created from Lua (PerlinNoise(seed, octaves, persistence)
lua_register(L, className, create_object);
}
@@ -138,16 +139,26 @@ const luaL_reg LuaPerlinNoise::methods[] = {
{0,0}
};
///////////////////////////////////////
/*
PerlinNoiseMap
*/
LuaPerlinNoiseMap
*/
int LuaPerlinNoiseMap::gc_object(lua_State *L)
LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
{
LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
delete o;
return 0;
m_is3d = size.Z > 1;
np = *params;
try {
noise = new Noise(&np, seed, size.X, size.Y, size.Z);
} catch (InvalidNoiseParamsException &e) {
throw LuaError(e.what());
}
}
LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
{
delete noise;
}
@@ -251,26 +262,6 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
}
LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
{
m_is3d = size.Z > 1;
np = *params;
try {
noise = new Noise(&np, seed, size.X, size.Y, size.Z);
} catch (InvalidNoiseParamsException &e) {
throw LuaError(e.what());
}
}
LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
{
delete noise;
}
// LuaPerlinNoiseMap(np, size)
// Creates an LuaPerlinNoiseMap and leaves it on top of stack
int LuaPerlinNoiseMap::create_object(lua_State *L)
{
NoiseParams np;
@@ -286,6 +277,14 @@ int LuaPerlinNoiseMap::create_object(lua_State *L)
}
int LuaPerlinNoiseMap::gc_object(lua_State *L)
{
LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
delete o;
return 0;
}
LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
@@ -294,7 +293,7 @@ LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
if (!ud)
luaL_typerror(L, narg, className);
return *(LuaPerlinNoiseMap **)ud; // unbox pointer
return *(LuaPerlinNoiseMap **)ud;
}
@@ -307,7 +306,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -317,12 +316,11 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
lua_pop(L, 1); // drop metatable
lua_pop(L, 1);
luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // drop methodtable
luaL_openlib(L, 0, methods, 0);
lua_pop(L, 1);
// Can be created from Lua (PerlinNoiseMap(np, size)
lua_register(L, className, create_object);
}
@@ -336,32 +334,23 @@ const luaL_reg LuaPerlinNoiseMap::methods[] = {
{0,0}
};
///////////////////////////////////////
/*
LuaPseudoRandom
*/
// garbage collector
int LuaPseudoRandom::gc_object(lua_State *L)
{
LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
delete o;
return 0;
}
// next(self, min=0, max=32767) -> get next value
int LuaPseudoRandom::l_next(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPseudoRandom *o = checkobject(L, 1);
int min = 0;
int max = 32767;
lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist
if(!lua_isnil(L, 2))
lua_settop(L, 3);
if (lua_isnumber(L, 2))
min = luaL_checkinteger(L, 2);
if(!lua_isnil(L, 3))
if (lua_isnumber(L, 3))
max = luaL_checkinteger(L, 3);
if(max < min){
if (max < min) {
errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
throw LuaError("PseudoRandom.next(): max < min");
}
@@ -378,30 +367,6 @@ int LuaPseudoRandom::l_next(lua_State *L)
}
LuaPseudoRandom::LuaPseudoRandom(int seed):
m_pseudo(seed)
{
}
LuaPseudoRandom::~LuaPseudoRandom()
{
}
const PseudoRandom& LuaPseudoRandom::getItem() const
{
return m_pseudo;
}
PseudoRandom& LuaPseudoRandom::getItem()
{
return m_pseudo;
}
// LuaPseudoRandom(seed)
// Creates an LuaPseudoRandom and leaves it on top of stack
int LuaPseudoRandom::create_object(lua_State *L)
{
int seed = luaL_checknumber(L, 1);
@@ -413,13 +378,21 @@ int LuaPseudoRandom::create_object(lua_State *L)
}
LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg)
int LuaPseudoRandom::gc_object(lua_State *L)
{
LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
delete o;
return 0;
}
LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
return *(LuaPseudoRandom**)ud; // unbox pointer
return *(LuaPseudoRandom **)ud;
}
@@ -432,7 +405,7 @@ void LuaPseudoRandom::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -442,12 +415,11 @@ void LuaPseudoRandom::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
lua_pop(L, 1); // drop metatable
lua_pop(L, 1);
luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // drop methodtable
luaL_openlib(L, 0, methods, 0);
lua_pop(L, 1);
// Can be created from Lua (LuaPseudoRandom(seed))
lua_register(L, className, create_object);
}
@@ -457,3 +429,101 @@ const luaL_reg LuaPseudoRandom::methods[] = {
luamethod(LuaPseudoRandom, next),
{0,0}
};
///////////////////////////////////////
/*
LuaPcgRandom
*/
int LuaPcgRandom::l_next(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPcgRandom *o = checkobject(L, 1);
u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
lua_pushinteger(L, o->m_rnd.range(min, max));
return 1;
}
int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPcgRandom *o = checkobject(L, 1);
u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
return 1;
}
int LuaPcgRandom::create_object(lua_State *L)
{
lua_Integer seed = luaL_checknumber(L, 1);
LuaPcgRandom *o = lua_isnumber(L, 2) ?
new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
new LuaPcgRandom(seed);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
return 1;
}
int LuaPcgRandom::gc_object(lua_State *L)
{
LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
delete o;
return 0;
}
LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
return *(LuaPcgRandom **)ud;
}
void LuaPcgRandom::Register(lua_State *L)
{
lua_newtable(L);
int methodtable = lua_gettop(L);
luaL_newmetatable(L, className);
int metatable = lua_gettop(L);
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable);
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
lua_pop(L, 1);
luaL_openlib(L, 0, methods, 0);
lua_pop(L, 1);
lua_register(L, className, create_object);
}
const char LuaPcgRandom::className[] = "PcgRandom";
const luaL_reg LuaPcgRandom::methods[] = {
luamethod(LuaPcgRandom, next),
luamethod(LuaPcgRandom, rand_normal_dist),
{0,0}
};

View File

@@ -64,6 +64,9 @@ class LuaPerlinNoiseMap : public ModApiBase {
static const char className[];
static const luaL_reg methods[];
// Exported functions
// garbage collector
static int gc_object(lua_State *L);
static int l_get2dMap(lua_State *L);
@@ -104,18 +107,51 @@ private:
static int l_next(lua_State *L);
public:
LuaPseudoRandom(int seed);
~LuaPseudoRandom();
const PseudoRandom& getItem() const;
PseudoRandom& getItem();
LuaPseudoRandom(int seed) :
m_pseudo(seed) {}
// LuaPseudoRandom(seed)
// Creates an LuaPseudoRandom and leaves it on top of stack
static int create_object(lua_State *L);
static LuaPseudoRandom* checkobject(lua_State *L, int narg);
static LuaPseudoRandom *checkobject(lua_State *L, int narg);
static void Register(lua_State *L);
};
/*
LuaPcgRandom
*/
class LuaPcgRandom : public ModApiBase {
private:
PcgRandom m_rnd;
static const char className[];
static const luaL_reg methods[];
// Exported functions
// garbage collector
static int gc_object(lua_State *L);
// next(self, min=-2147483648, max=2147483647) -> get next value
static int l_next(lua_State *L);
// rand_normal_dist(self, min=-2147483648, max=2147483647, num_trials=6) ->
// get next normally distributed random value
static int l_rand_normal_dist(lua_State *L);
public:
LuaPcgRandom(u64 seed) :
m_rnd(seed) {}
LuaPcgRandom(u64 seed, u64 seq) :
m_rnd(seed, seq) {}
// LuaPcgRandom(seed)
// Creates an LuaPcgRandom and leaves it on top of stack
static int create_object(lua_State *L);
static LuaPcgRandom *checkobject(lua_State *L, int narg);
static void Register(lua_State *L);
};

View File

@@ -29,8 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_sao.h"
#include "server.h"
#include "hud.h"
#include "settings.h"
#include "main.h"
struct EnumString es_HudElementType[] =
@@ -257,10 +255,10 @@ int ObjectRef::l_set_hp(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
luaL_checknumber(L, 2);
ServerActiveObject *co = getobject(ref);
if(co == NULL)
return 0;
if(co == NULL) return 0;
int hp = lua_tonumber(L, 2);
/*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
<<" hp="<<hp<<std::endl;*/
// Do it
co->setHP(hp);
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
@@ -291,38 +289,6 @@ int ObjectRef::l_get_hp(lua_State *L)
return 1;
}
// apply_damage(self, damage)
// damage = amount of damage to apply
// if damage is negative, heal the player
// returns: nil
int ObjectRef::l_apply_damage(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
luaL_checknumber(L, 2);
ServerActiveObject *co = getobject(ref);
if(co == NULL)
return 0;
int damage = lua_tonumber(L, 2);
// No damage, no heal => do nothing
if (damage == 0)
return 0;
// If damage is positive (not healing) and damage is disabled, ignore
if (damage > 0 && g_settings->getBool("enable_damage") == false)
return 0;
// Do damage/heal
co->setHP(co->getHP() - damage);
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), co->getHP() == 0);
}
return 0;
}
// get_inventory(self)
int ObjectRef::l_get_inventory(lua_State *L)
{
@@ -1379,7 +1345,6 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, right_click),
luamethod(ObjectRef, set_hp),
luamethod(ObjectRef, get_hp),
luamethod(ObjectRef, apply_damage),
luamethod(ObjectRef, get_inventory),
luamethod(ObjectRef, get_wield_list),
luamethod(ObjectRef, get_wield_index),

View File

@@ -83,12 +83,6 @@ private:
// 0 if not applicable to this type of object
static int l_get_hp(lua_State *L);
// apply_damage(self, damage)
// damage = amount of damage to apply
// if damage is negative, heal the player
// returns: nil
static int l_apply_damage(lua_State *L);
// get_inventory(self)
static int l_get_inventory(lua_State *L);

View File

@@ -92,6 +92,7 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
LuaPerlinNoise::Register(L);
LuaPerlinNoiseMap::Register(L);
LuaPseudoRandom::Register(L);
LuaPcgRandom::Register(L);
LuaVoxelManip::Register(L);
NodeMetaRef::Register(L);
NodeTimerRef::Register(L);

View File

@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "../constants.h" // BS, MAP_BLOCKSIZE
#include "../noise.h" // PseudoRandom, PcgRandom
#include <string.h>
#include <iostream>
@@ -115,36 +116,32 @@ void FacePositionCache::generateFacePosition(u16 d)
myrand
*/
static unsigned long next = 1;
PcgRandom g_pcgrand;
/* RAND_MAX assumed to be 32767 */
int myrand(void)
u32 myrand()
{
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
return g_pcgrand.next();
}
void mysrand(unsigned seed)
void mysrand(unsigned int seed)
{
next = seed;
g_pcgrand.seed(seed);
}
void myrand_bytes(void *out, size_t len)
{
g_pcgrand.bytes(out, len);
}
int myrand_range(int min, int max)
{
if(max-min > MYRAND_MAX)
{
errorstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
max = min + MYRAND_MAX;
}
if(min > max)
{
errorstream<<"WARNING: myrand_range: min > max"<<std::endl;
return max;
}
return (myrand()%(max-min+1))+min;
return g_pcgrand.range(min, max);
}
// 64-bit unaligned version of MurmurHash
/*
64-bit unaligned version of MurmurHash
*/
u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
@@ -159,12 +156,12 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
memcpy(&k, data, sizeof(u64));
data++;
k *= m;
k ^= k >> r;
k *= m;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
h *= m;
}
const unsigned char *data2 = (const unsigned char *)data;
@@ -178,13 +175,13 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
case 1: h ^= (u64)data2[0];
h *= m;
}
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
}
/*
@@ -197,7 +194,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
f32 camera_fov, f32 range, f32 *distance_ptr)
{
v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
// Block center position
v3f blockpos(
((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
@@ -213,7 +210,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
if(distance_ptr)
*distance_ptr = d;
// If block is far away, it's not in sight
if(d > range)
return false;
@@ -221,7 +218,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
// Maximum radius of a block. The magic number is
// sqrt(3.0) / 2.0 in literal form.
f32 block_max_radius = 0.866025403784 * MAP_BLOCKSIZE * BS;
// If block is (nearly) touching the camera, don't
// bother validating further (that is, render it anyway)
if(d < block_max_radius)
@@ -242,7 +239,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
// Cosine of the angle between the camera direction
// and the block direction (camera_dir is an unit vector)
f32 cosangle = dforward / blockpos_adj.getLength();
// If block is not in the field of view, skip it
if(cosangle < cos(camera_fov / 2))
return false;

View File

@@ -239,10 +239,10 @@ inline float wrapDegrees_180(float f)
/*
Pseudo-random (VC++ rand() sucks)
*/
int myrand(void);
void mysrand(unsigned seed);
#define MYRAND_MAX 32767
#define MYRAND_RANGE 0xffffffff
u32 myrand();
void mysrand(unsigned int seed);
void myrand_bytes(void *out, size_t len);
int myrand_range(int min, int max);
/*