144 lines
3.5 KiB
C++
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 */
|