lua: inventory library
This commit is contained in:
parent
617017d979
commit
e16f7567b1
42
src/items/Inventories.cpp
Normal file
42
src/items/Inventories.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "Inventories.h"
|
||||
#include "../world/Level.h"
|
||||
#include "../world/World.h"
|
||||
|
||||
Inventories::Inventories(Level& level) : level(level) {
|
||||
}
|
||||
|
||||
Inventories::~Inventories() {
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Inventories::create(size_t size) {
|
||||
int64_t id = level.getWorld()->getNextInventoryId();
|
||||
auto inv = std::make_shared<Inventory>(id, size);
|
||||
store(inv);
|
||||
return inv;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Inventories::createVirtual(size_t size) {
|
||||
int64_t id;
|
||||
do {
|
||||
id = -std::max(1L, std::abs(random.rand64()));
|
||||
} while (map.find(id) != map.end());
|
||||
|
||||
auto inv = std::make_shared<Inventory>(id, size);
|
||||
store(inv);
|
||||
return inv;
|
||||
}
|
||||
|
||||
void Inventories::store(std::shared_ptr<Inventory> inv) {
|
||||
map[inv->getId()] = inv;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Inventories::get(int64_t id) {
|
||||
auto found = map.find(id);
|
||||
if (found == map.end())
|
||||
return nullptr;
|
||||
return found->second;
|
||||
}
|
||||
|
||||
const inventories_map& Inventories::getMap() const {
|
||||
return map;
|
||||
}
|
||||
39
src/items/Inventories.h
Normal file
39
src/items/Inventories.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef ITEMS_INVENTORIES_H_
|
||||
#define ITEMS_INVENTORIES_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Inventory.h"
|
||||
#include "../maths/util.h"
|
||||
|
||||
class Level;
|
||||
|
||||
using inventories_map = std::unordered_map<int64_t, std::shared_ptr<Inventory>>;
|
||||
|
||||
/* Inventories runtime storage */
|
||||
class Inventories {
|
||||
Level& level;
|
||||
inventories_map map;
|
||||
PseudoRandom random;
|
||||
public:
|
||||
Inventories(Level& level);
|
||||
~Inventories();
|
||||
|
||||
/* Create new inventory with new id */
|
||||
std::shared_ptr<Inventory> create(size_t size);
|
||||
|
||||
/* Create runtime-only inventory (has negative id) */
|
||||
std::shared_ptr<Inventory> createVirtual(size_t size);
|
||||
|
||||
/* Store inventory */
|
||||
void store(std::shared_ptr<Inventory> inv);
|
||||
|
||||
/* Get inventory by id (works with both real and virtual)*/
|
||||
std::shared_ptr<Inventory> get(int64_t id);
|
||||
|
||||
const inventories_map& getMap() const;
|
||||
};
|
||||
|
||||
#endif // ITEMS_INVENTORIES_H_
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "../content/ContentLUT.h"
|
||||
|
||||
Inventory::Inventory(uint id, size_t size) : id(id), slots(size) {
|
||||
Inventory::Inventory(int64_t id, size_t size) : id(id), slots(size) {
|
||||
}
|
||||
|
||||
ItemStack& Inventory::getSlot(size_t index) {
|
||||
|
||||
@ -14,10 +14,10 @@ class ContentLUT;
|
||||
class ContentIndices;
|
||||
|
||||
class Inventory : Serializable {
|
||||
uint id;
|
||||
int64_t id;
|
||||
std::vector<ItemStack> slots;
|
||||
public:
|
||||
Inventory(uint id, size_t size);
|
||||
Inventory(int64_t id, size_t size);
|
||||
|
||||
ItemStack& getSlot(size_t index);
|
||||
size_t findEmptySlot(size_t begin=0, size_t end=-1) const;
|
||||
@ -40,10 +40,14 @@ public:
|
||||
|
||||
static void convert(dynamic::Map* data, const ContentLUT* lut);
|
||||
|
||||
inline uint getId() const {
|
||||
inline int64_t getId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
inline bool isVirtual() const {
|
||||
return id < 0;
|
||||
}
|
||||
|
||||
static const size_t npos;
|
||||
};
|
||||
|
||||
|
||||
@ -94,6 +94,7 @@ void lua::LuaState::createFuncs() {
|
||||
openlib("pack", packlib, 0);
|
||||
openlib("world", worldlib, 0);
|
||||
openlib("player", playerlib, 0);
|
||||
openlib("inventory", inventorylib, 0);
|
||||
openlib("item", itemlib, 0);
|
||||
openlib("time", timelib, 0);
|
||||
openlib("file", filelib, 0);
|
||||
|
||||
@ -17,7 +17,9 @@
|
||||
#include "../../voxels/Chunks.h"
|
||||
#include "../../voxels/voxel.h"
|
||||
#include "../../items/ItemDef.h"
|
||||
#include "../../items/ItemStack.h"
|
||||
#include "../../items/Inventory.h"
|
||||
#include "../../items/Inventories.h"
|
||||
#include "../../lighting/Lighting.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../window/Window.h"
|
||||
@ -229,7 +231,83 @@ static const luaL_Reg playerlib [] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == items-related functions == */
|
||||
static void validate_itemid(lua_State* L, itemid_t id) {
|
||||
if (id >= scripting::indices->countItemDefs()) {
|
||||
luaL_error(L, "invalid item id");
|
||||
}
|
||||
}
|
||||
|
||||
/* == inventory library == */
|
||||
static int l_inventory_get(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint slotid = lua_tointeger(L, 2);
|
||||
auto inv = scripting::level->inventories->get(invid);
|
||||
if (inv == nullptr) {
|
||||
luaL_error(L, "inventory does not exists in runtime: %d", invid);
|
||||
}
|
||||
if (slotid < 0 || uint64_t(slotid) >= inv->size()) {
|
||||
luaL_error(L, "slot index is out of range [0, inventory.size(invid)]");
|
||||
}
|
||||
ItemStack& item = inv->getSlot(slotid);
|
||||
lua_pushinteger(L, item.getItemId());
|
||||
lua_pushinteger(L, item.getCount());
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_inventory_set(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint slotid = lua_tointeger(L, 2);
|
||||
lua::luaint itemid = lua_tointeger(L, 3);
|
||||
lua::luaint count = lua_tointeger(L, 4);
|
||||
validate_itemid(L, itemid);
|
||||
|
||||
auto inv = scripting::level->inventories->get(invid);
|
||||
if (inv == nullptr) {
|
||||
luaL_error(L, "inventory does not exists in runtime: %d", invid);
|
||||
}
|
||||
if (slotid < 0 || uint64_t(slotid) >= inv->size()) {
|
||||
luaL_error(L, "slot index is out of range [0, inventory.size(invid)]");
|
||||
}
|
||||
ItemStack& item = inv->getSlot(slotid);
|
||||
item.set(ItemStack(itemid, count));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_inventory_size(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
auto inv = scripting::level->inventories->get(invid);
|
||||
if (inv == nullptr) {
|
||||
luaL_error(L, "inventory does not exists in runtime: %d", invid);
|
||||
}
|
||||
lua_pushinteger(L, inv->size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_inventory_add(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint itemid = lua_tointeger(L, 2);
|
||||
lua::luaint count = lua_tointeger(L, 3);
|
||||
validate_itemid(L, itemid);
|
||||
|
||||
auto inv = scripting::level->inventories->get(invid);
|
||||
if (inv == nullptr) {
|
||||
luaL_error(L, "inventory does not exists in runtime: %d", invid);
|
||||
}
|
||||
ItemStack item(itemid, count);
|
||||
inv->move(item, scripting::indices);
|
||||
lua_pushinteger(L, item.getCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg inventorylib [] = {
|
||||
{"get", l_inventory_get},
|
||||
{"set", l_inventory_set},
|
||||
{"size", l_inventory_size},
|
||||
{"add", l_inventory_add},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == item library == */
|
||||
static int l_item_name(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
|
||||
@ -9,7 +9,7 @@ class LuaState;
|
||||
|
||||
class Engine;
|
||||
class Content;
|
||||
class ContentPack;
|
||||
struct ContentPack;
|
||||
class ContentIndices;
|
||||
class Level;
|
||||
class Block;
|
||||
@ -29,6 +29,7 @@ namespace scripting {
|
||||
extern Level* level;
|
||||
extern BlocksController* blocks;
|
||||
|
||||
/* Lua environment wrapper for automatic deletion */
|
||||
class Environment {
|
||||
int env;
|
||||
public:
|
||||
@ -64,13 +65,28 @@ namespace scripting {
|
||||
void on_block_placed(Player* player, const Block* block, int x, int y, int z);
|
||||
void on_block_broken(Player* player, const Block* block, int x, int y, int z);
|
||||
bool on_block_interact(Player* player, const Block* block, int x, int y, int z);
|
||||
|
||||
/* Called on RMB click on block with the item selected
|
||||
@return true if prevents default action */
|
||||
bool on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z);
|
||||
/* Called on LMB click on block with the item selected
|
||||
@return true if prevents default action */
|
||||
bool on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z);
|
||||
|
||||
/* Called on UI view show */
|
||||
void on_ui_open(UiDocument* layout, Inventory* inventory);
|
||||
/* Called on UI view close*/
|
||||
void on_ui_close(UiDocument* layout, Inventory* inventory);
|
||||
|
||||
/* Load script associated with a Block */
|
||||
void load_block_script(int env, std::string prefix, fs::path file, block_funcs_set& funcsset);
|
||||
/* Load script associated with an Item */
|
||||
void load_item_script(int env, std::string prefix, fs::path file, item_funcs_set& funcsset);
|
||||
/* Load package-specific world script */
|
||||
void load_world_script(int env, std::string prefix, fs::path file);
|
||||
/* Load script associated with an UiDocument */
|
||||
void load_layout_script(int env, std::string prefix, fs::path file, uidocscript& script);
|
||||
/* Finalize lua state. Using scripting after will lead to Lua panic */
|
||||
|
||||
void close();
|
||||
}
|
||||
|
||||
49
src/maths/util.h
Normal file
49
src/maths/util.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef MATHS_UTIL_H_
|
||||
#define MATHS_UTIL_H_
|
||||
|
||||
#include <ctime>
|
||||
#include <stdint.h>
|
||||
|
||||
class PseudoRandom {
|
||||
unsigned short seed;
|
||||
public:
|
||||
PseudoRandom(){
|
||||
seed = (unsigned short)time(0);
|
||||
}
|
||||
|
||||
int rand(){
|
||||
seed = (seed + 0x7ed5 + (seed << 6));
|
||||
seed = (seed ^ 0xc23c ^ (seed >> 9));
|
||||
seed = (seed + 0x1656 + (seed << 3));
|
||||
seed = ((seed + 0xa264) ^ (seed << 4));
|
||||
seed = (seed + 0xfd70 - (seed << 3));
|
||||
seed = (seed ^ 0xba49 ^ (seed >> 8));
|
||||
|
||||
return (int)seed;
|
||||
}
|
||||
|
||||
int32_t rand32() {
|
||||
return (rand() << 16) | rand();
|
||||
}
|
||||
|
||||
uint32_t randU32() {
|
||||
return (rand() << 16) | rand();
|
||||
}
|
||||
|
||||
int64_t rand64() {
|
||||
uint64_t x = randU32();
|
||||
uint64_t y = randU32();
|
||||
return (x << 32ULL) | y;
|
||||
}
|
||||
|
||||
void setSeed(int number){
|
||||
seed = ((unsigned short)(number*23729) ^ (unsigned short)(number+16786));
|
||||
rand();
|
||||
}
|
||||
void setSeed(int number1, int number2){
|
||||
seed = (((unsigned short)(number1*23729) | (unsigned short)(number2%16786)) ^ (unsigned short)(number2*number1));
|
||||
rand();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MATHS_UTIL_H_
|
||||
@ -18,10 +18,10 @@ const float FLIGHT_SPEED_MUL = 4.0f;
|
||||
const float CHEAT_SPEED_MUL = 5.0f;
|
||||
const float JUMP_FORCE = 8.0f;
|
||||
|
||||
Player::Player(glm::vec3 position, float speed) :
|
||||
Player::Player(glm::vec3 position, float speed, std::shared_ptr<Inventory> inv) :
|
||||
speed(speed),
|
||||
chosenSlot(0),
|
||||
inventory(new Inventory(0, 40)),
|
||||
inventory(inv),
|
||||
camera(new Camera(position, glm::radians(90.0f))),
|
||||
spCamera(new Camera(position, glm::radians(90.0f))),
|
||||
tpCamera(new Camera(position, glm::radians(90.0f))),
|
||||
@ -195,7 +195,6 @@ std::unique_ptr<dynamic::Map> Player::serialize() const {
|
||||
}
|
||||
|
||||
void Player::deserialize(dynamic::Map *src) {
|
||||
|
||||
auto posarr = src->list("position");
|
||||
glm::vec3& position = hitbox->position;
|
||||
position.x = posarr->num(0);
|
||||
|
||||
@ -48,7 +48,7 @@ public:
|
||||
|
||||
glm::vec2 cam = {};
|
||||
|
||||
Player(glm::vec3 position, float speed);
|
||||
Player(glm::vec3 position, float speed, std::shared_ptr<Inventory> inv);
|
||||
~Player();
|
||||
|
||||
void teleport(glm::vec3 position);
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../content/Content.h"
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../maths/util.h"
|
||||
#include "../core_defs.h"
|
||||
|
||||
// TODO: do something with long conditions + move magic numbers to constants
|
||||
@ -62,36 +63,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PseudoRandom {
|
||||
unsigned short seed;
|
||||
public:
|
||||
PseudoRandom(){
|
||||
seed = (unsigned short)time(0);
|
||||
}
|
||||
|
||||
int rand(){
|
||||
seed = (seed + 0x7ed5 + (seed << 6));
|
||||
seed = (seed ^ 0xc23c ^ (seed >> 9));
|
||||
seed = (seed + 0x1656 + (seed << 3));
|
||||
seed = ((seed + 0xa264) ^ (seed << 4));
|
||||
seed = (seed + 0xfd70 - (seed << 3));
|
||||
seed = (seed ^ 0xba49 ^ (seed >> 8));
|
||||
|
||||
return (int)seed;
|
||||
}
|
||||
|
||||
void setSeed(int number){
|
||||
seed = ((unsigned short)(number*23729) ^ (unsigned short)(number+16786));
|
||||
rand();
|
||||
}
|
||||
void setSeed(int number1,int number2){
|
||||
seed = (((unsigned short)(number1*23729) | (unsigned short)(number2%16786)) ^ (unsigned short)(number2*number1));
|
||||
rand();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
float calc_height(fnl_state *noise, int cur_x, int cur_z){
|
||||
float height = 0;
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "../physics/PhysicsSolver.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../items/Inventory.h"
|
||||
#include "../items/Inventories.h"
|
||||
|
||||
Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings)
|
||||
: world(world),
|
||||
@ -30,6 +31,8 @@ Level::Level(World* world, const Content* content, Player* player, EngineSetting
|
||||
events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
|
||||
this->chunksStorage->remove(chunk->x, chunk->z);
|
||||
});
|
||||
|
||||
inventories = std::make_unique<Inventories>(*this);
|
||||
}
|
||||
|
||||
Level::~Level(){
|
||||
|
||||
@ -11,6 +11,7 @@ class World;
|
||||
class Player;
|
||||
class Chunks;
|
||||
class Inventory;
|
||||
class Inventories;
|
||||
class LevelEvents;
|
||||
class Lighting;
|
||||
class PhysicsSolver;
|
||||
@ -23,6 +24,7 @@ public:
|
||||
Player* player;
|
||||
Chunks* chunks;
|
||||
ChunksStorage* chunksStorage;
|
||||
std::unique_ptr<Inventories> inventories;
|
||||
|
||||
PhysicsSolver* physics;
|
||||
Lighting* lighting;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "../voxels/ChunksStorage.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../window/Camera.h"
|
||||
#include "../items/Inventories.h"
|
||||
|
||||
world_load_error::world_load_error(std::string message)
|
||||
: std::runtime_error(message) {
|
||||
@ -65,6 +66,7 @@ void World::write(Level* level) {
|
||||
|
||||
const float DEF_PLAYER_Y = 100.0f;
|
||||
const float DEF_PLAYER_SPEED = 4.0f;
|
||||
const int DEF_PLAYER_INVENTORY_SIZE = 40;
|
||||
|
||||
Level* World::create(std::string name,
|
||||
fs::path directory,
|
||||
@ -73,8 +75,12 @@ Level* World::create(std::string name,
|
||||
const Content* content,
|
||||
const std::vector<ContentPack>& packs) {
|
||||
auto world = new World(name, directory, seed, settings, content, packs);
|
||||
auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
||||
return new Level(world, content, player, settings);
|
||||
auto inv = std::make_shared<Inventory>(world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE);
|
||||
auto player = new Player(
|
||||
glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv
|
||||
);
|
||||
auto level = new Level(world, content, player, settings);
|
||||
level->inventories->store(player->getInventory());
|
||||
}
|
||||
|
||||
Level* World::load(fs::path directory,
|
||||
@ -90,10 +96,13 @@ Level* World::load(fs::path directory,
|
||||
throw world_load_error("could not to find world.json");
|
||||
}
|
||||
|
||||
auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
||||
auto inv = std::make_shared<Inventory>(0, DEF_PLAYER_INVENTORY_SIZE);
|
||||
auto player = new Player(
|
||||
glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv
|
||||
);
|
||||
auto level = new Level(world.get(), content, player, settings);
|
||||
wfile->readPlayer(player);
|
||||
|
||||
level->inventories->store(player->getInventory());
|
||||
world.release();
|
||||
return level;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user