Nooncraft/src/world.h

144 lines
3.5 KiB
C++

// nooncraft.world: World data and structures
#pragma once
#include <num/num.h>
#include "block.h"
#include <stddef.h>
#include <gint/defs/attributes.h>
#include <gint/defs/util.h>
using namespace libnum;
struct WorldCoord
{
int16_t x, y;
constexpr WorldCoord(): x {0}, y {0} {}
constexpr WorldCoord(int _x, int _y): x {(int16_t)_x}, y {(int16_t)_y} {}
inline constexpr WorldCoord &operator+=(WorldCoord const &other) {
this->x += other.x;
this->y += other.y;
return *this;
}
inline constexpr WorldCoord operator-=(WorldCoord const &other) {
this->x -= other.x;
this->y -= other.y;
return *this;
}
inline constexpr bool operator==(WorldCoord const &other) {
return this->x == other.x && this->y == other.y;
}
static WorldCoord Up, Down, Left, Right;
};
inline constexpr WorldCoord operator+(WorldCoord l, WorldCoord const &r) {
return (l += r);
}
inline constexpr WorldCoord operator-(WorldCoord l, WorldCoord const &r) {
return (l -= r);
}
struct WorldRect
{
/* All included */
int16_t xmin, xmax;
int16_t ymin, ymax;
constexpr WorldRect(): xmin {0}, xmax {0}, ymin {0}, ymax {0} {}
constexpr WorldRect(int _xmin, int _xmax, int _ymin, int _ymax):
xmin {(int16_t)_xmin}, xmax {(int16_t)_xmax},
ymin {(int16_t)_ymin}, ymax {(int16_t)_ymax} {}
int width() const {
return xmax - xmin + 1;
}
int height() const {
return ymax - ymin + 1;
}
WorldCoord clampPoint(WorldCoord p) const {
p.x = max(p.x, xmin);
p.x = min(p.x, xmax);
p.y = max(p.y, ymin);
p.y = min(p.y, ymax);
return p;
}
bool contains(WorldCoord p) const {
return xmin <= p.x && p.x <= xmax && ymin <= p.y && p.y <= ymax;
}
};
/* Don't ask me why this is here */
struct vec2 {
num x, y;
};
enum class Biome: uint8_t {
Plains,
Forest,
Ocean,
Cave,
};
struct World
{
/* Map data limits (ie. how far blocks exist) */
WorldRect limits;
/* World border position */
WorldRect worldBorder;
/* Block cells in row-major order */
Block *cells;
int cellCount() const {
return limits.width() * limits.height();
}
size_t cellDataSize() const {
return cellCount() * sizeof(*cells);
}
GINLINE Block const &cellAt(int16_t x, int16_t y) const {
int ix = (x - limits.xmin) + (y - limits.ymin) * limits.width();
return cells[ix];
}
GINLINE Block &cellAt(int16_t x, int16_t y) {
int ix = (x - limits.xmin) + (y - limits.ymin) * limits.width();
return cells[ix];
}
GINLINE void trySetCellAt(int16_t x, int16_t y, Block b) {
if(x < limits.xmin || x > limits.xmax
|| y < limits.ymin || y > limits.ymax)
return;
cellAt(x, y) = b;
}
bool isPointOnWorldBorder(int16_t x, int16_t y) const {
return x == worldBorder.xmin || x == worldBorder.xmax
|| y == worldBorder.ymin || y == worldBorder.ymax;
}
bool validSpawn(int x, int y) const;
WorldCoord findSpawnPoint();
BlockInfo *blockInfoAt(WorldCoord p) const;
bool canBreakBlock(WorldCoord p) const;
bool canPlaceAt(WorldCoord p) const;
};
namespace Nooncraft {
/* Make an empty uninitialized world map. */
World *mkWorld(int width, int height);
/* Run the world generator, initializing the entire world. */
void genWorld(World *w);
/* Free a world object. */
void freeWorld(World *w);
} /* namespace Nooncraft */