Files
CubeGame/src/helpers/inventory.cpp
T
milkwx3 04d1969084
Build / build (push) Has been cancelled
Added day&night cycle. Also fixed world loading
2026-07-07 22:02:10 +03:00

554 lines
20 KiB
C++

#ifndef SERVER
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <iostream>
#include <map>
#include <rlgl.h>
#define PIXUNIT 1.0f / 16.0f
InventoryItem hotbar[ITEMS];
InventoryItem inventory[INVENTORY_SIZE];
static uint8_t selected = 0;
static Texture2D item_atlas;
extern Texture2D terrain;
extern Texture2D playerTex;
const std::string LocaleGet(std::string loc);
std::vector<Item> registry = {
Item{ "block", IType_Block, 0},
Item{ "apple", IType_Edible, 0},
Item{ "stick", IType_Generic, 1},
Item{ "stone_pickaxe", IType_Mining, 2, 1},
Item{ "copper_pickaxe", IType_Mining, 4, 2},
Item{ "silver_pickaxe", IType_Mining, 3, 3},
Item{ "gold_pickaxe", IType_Mining, 5, 4},
Item{ "copper_ingot", IType_Generic, 6},
Item{ "silver_ingot", IType_Generic, 7},
Item{ "gold_ingot", IType_Generic, 8},
};
bool inventoryOpen = false;
InventoryItem* movingItem = nullptr;
static Image itemAtlasImg;
extern std::list<Recipe> recipes;
int GetNumericIDFromString(std::string s);
void DrawItem(InventoryItem item, int x, int y) {
if(item.item != nullptr) {
int atl_size = ITEM_ATLAS_SIZE;
int tex = item.item->texture;
Texture2D atlas = item_atlas;
if(item.item->type == IType_Block) {
atlas = terrain;
atl_size = ATLAS_SIZE_W;
tex = GetBlockDefinition(item.damage).textureTop;
}
DrawTexturePro(atlas,
{
(float)(tex % atl_size) * ITEM_SIZE,
(float)(tex / atl_size) * ITEM_SIZE,
ITEM_SIZE,
ITEM_SIZE
},
{
(float)x+6, (float)y+6, 44, 44
},
{0, 0},
0,
WHITE);
char text[12] = "???\0";
sprintf(text, "x%d", item.amount);
if(item.amount != 0) DrawText(text, x, y, DEFAULT_FONT_SIZE / 2, WHITE);
}
}
void InventoryRemoveItem(int slot) {
if(inventory[slot].amount-1 > 0) {
inventory[slot].amount--;
}
else {
inventory[slot].item = nullptr;
inventory[slot].damage = 0;
inventory[slot].amount = 0;
}
}
void HotbarRemoveItem(int slot) {
if(hotbar[slot].amount-1 > 0) {
hotbar[slot].amount--;
}
else {
hotbar[slot].item = nullptr;
hotbar[slot].damage = 0;
hotbar[slot].amount = 0;
}
}
void HotbarRemoveSelected() {
HotbarRemoveItem(selected);
}
void HotbarAddItem(Item* registry, int damage) {
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if((item.item == registry && item.damage == damage)) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += 1;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if((item.item == registry && item.damage == damage)) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += 1;
return;
}
}
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if(item.item == nullptr) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += 1;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item == nullptr) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += 1;
return;
}
}
}
void HotbarAddItemLots(Item* registry, int damage, int amount) {
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if((item.item == registry && item.damage == damage)) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += amount;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if((item.item == registry && item.damage == damage)) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += amount;
return;
}
}
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if(item.item == nullptr) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += amount;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item == nullptr) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += amount;
return;
}
}
}
Item* GetItemByID(std::string s) {
for (Item& i : registry) {
if (i.id == s) return &i;
}
return nullptr;
}
int GetItemNumID(std::string s) {
int o = 0;
for (Item& i : registry) {
if (i.id == s) return o;
o++;
}
return -1;
}
void InitHotbar() {
/*for (int i = 0; i < ITEMS; i++)
{
HotbarRemoveItem(i);
}*/
//HotbarAddItem(&registry[0], GetNumericIDFromString("workbench"));
item_atlas = LoadTexture(Pathify("items.png"));
itemAtlasImg = LoadImageFromTexture(item_atlas);
}
bool IDTagMatch(std::string tag, std::string id);
static bool GetTaggedItem(std::string tag, InventoryItem* item) {
InventoryItem temp;
int id;
bool isBlock;
bool found;
for(int blk = 0; blk < MAX_BLOCK_ID; blk++) {
if(IDTagMatch(tag, GetBlockDefinition(blk).name)) {
isBlock = true;
id = GetNumericIDFromString(GetBlockDefinition(blk).name);
found = true;
break;
};
}
if(!found) {
for(Item item : registry) {
if(IDTagMatch(tag, item.id)) {
isBlock = false;
id = GetItemNumID(item.id);
found = true;
break;
};
}
}
if(!found) {
return false;
}
if(isBlock) {
temp.item = &(registry[0]);
temp.damage = id;
}
else {
temp.item = &(registry[id]);
}
memcpy(item, &temp, sizeof(InventoryItem));
return true;
}
static bool FindTaggedItem(std::string tag, InventoryItem* item) {
for(int blk = 0; blk < INVENTORY_SIZE; blk++) {
InventoryItem itm = inventory[blk];
if(itm.item != nullptr) {
if(GetTaggedItem(tag, &itm)) {
memcpy(item, &itm, sizeof(InventoryItem));
return true;
}
}
}
return false;
}
void DrawHotbar() {
if(inventoryOpen) UIBegin();
const int width = 52 * ITEMS;
DrawRectangle(GetScreenWidth()/2-width/2, GetScreenHeight()-48-2, width, 50, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < ITEMS; i++)
{
int x = GetScreenWidth()/2-width/2 + i * 52;
int y = GetScreenHeight()-50;
if(inventoryOpen) {
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr && hotbar[i].item == nullptr) {
memcpy(&hotbar[i], movingItem, sizeof(InventoryItem));
movingItem->item = nullptr;
movingItem->amount = 0;
movingItem->damage = 0;
}
else {
movingItem = &hotbar[i];
}
};
}
if(i == selected) {
DrawRectangle(x, y, 52, 52, BLACK);
}
if(&hotbar[i] != movingItem) {
DrawItem(hotbar[i], x, y);
}
}
if(inventoryOpen) {
const int width2 = 52 * INVENTORY_WIDTH;
const int inv_height = 52 * INVENTORY_HEIGHT;
DrawRectangle(GetScreenWidth()/2-width2/2, GetScreenHeight()-56-inv_height, width2, inv_height, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < INVENTORY_SIZE; i++)
{
int x = GetScreenWidth()/2-width2/2 + (i % INVENTORY_WIDTH) * 52;
int y = GetScreenHeight()-56-inv_height + (i / INVENTORY_WIDTH) * 52;
if((i + (i / INVENTORY_WIDTH)) % 2 == 0) {
DrawRectangle(x, y, 52, 52, ColorAlpha(BLACK, 0.1f));
}
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr && inventory[i].item == nullptr) {
memcpy(&inventory[i], movingItem, sizeof(InventoryItem));
movingItem->item = nullptr;
movingItem->amount = 0;
movingItem->damage = 0;
}
else {
movingItem = &inventory[i];
}
};
if(&inventory[i] != movingItem) {
DrawItem(inventory[i], x, y);
}
}
std::list<Recipe> validRecipes;
for (Recipe r : recipes)
{
if(r.requiredStation == "hands") {
std::vector<int> items;
for (RecipeItem ingredient : r.inputs) {
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item != nullptr) {
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items.push_back(i);
}
}
}
}
if(items.size() == r.inputs.size()) {
validRecipes.push_back(r);
}
}
}
int _y = 0;
for (Recipe r : validRecipes)
{
int x = GetScreenWidth()/2-width2/2 - 300;
int y = GetScreenHeight()-56-inv_height - _y * 52;
DrawRectangle(x, y, 260, 52, Fade(BLACK, 0.25f));
int _x = 0;
for (RecipeItem ingredient : r.inputs) {
InventoryItem temp;
if(ingredient.type == IType_Block) {
temp.item = &(registry[0]);
temp.damage = GetNumericIDFromString(ingredient.id);
}
else if (ingredient.type == IType_Generic) {
temp.item = GetItemByID(ingredient.id);
}
else {
GetTaggedItem(ingredient.id, &temp);
}
temp.amount = ingredient.quantity;
DrawItem(temp, x + _x * 52, y);
_x++;
}
_x = 1;
for (RecipeItem ingredient : r.outputs) {
InventoryItem temp;
if(ingredient.type == IType_Block) {
temp.item = &(registry[0]);
temp.damage = GetNumericIDFromString(ingredient.id);
}
else {
temp.item = GetItemByID(ingredient.id);
}
temp.amount = ingredient.quantity;
DrawItem(temp, x + 300 - 40 - _x * 52, y);
_x++;
}
if(ButtonInventory(x, y, 260, 52)) {
std::map<int, int> items;
for (RecipeItem ingredient : r.inputs) {
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item != nullptr) {
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items[i] = ingredient.quantity;
}
}
}
}
if(items.size() == r.inputs.size()) {
for(auto [i, amount] : items) {
for (int _ = 0; _ < amount; _++)
{
InventoryRemoveItem(i);
}
}
for (RecipeItem ingredient : r.outputs) {
if(ingredient.type == IType_Block) {
for (int _ = 0; _ < ingredient.quantity; _++) {
HotbarAddItem(&registry[0], GetNumericIDFromString(ingredient.id));
}
}
else {
for (int _ = 0; _ < ingredient.quantity; _++) {
HotbarAddItem(GetItemByID(ingredient.id), 255);
}
}
}
}
}
_y++;
}
}
if(inventoryOpen) {
const int width2 = 52 * INVENTORY_WIDTH;
const int inv_height = 52 * INVENTORY_HEIGHT;
DrawRectangle(GetScreenWidth()/2-width2/2, 4, width2, inv_height, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item;
if(i < MAX_BLOCK_ID) {
item.item = &registry[0];
item.damage = i;
}
else if (i < registry.size()+MAX_BLOCK_ID-1) {
item.item = &registry[i-MAX_BLOCK_ID+1];
}
int x = GetScreenWidth()/2-width2/2 + (i % INVENTORY_WIDTH) * 52;
int y = 4 + (i / INVENTORY_WIDTH) * 52;
if((i + (i / INVENTORY_WIDTH)) % 2 == 0) {
DrawRectangle(x, y, 52, 52, ColorAlpha(BLACK, 0.1f));
}
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr) {
movingItem = nullptr;
}
else {
HotbarAddItem(item.item, item.damage);
}
};
DrawItem(item, x, y);
}
}
if(movingItem != nullptr && movingItem->item != nullptr) {
DrawItem(*movingItem, GetMouseX(), GetMouseY());
std::string name = "item."+movingItem->item->id;
if(movingItem->item->type == IType_Block) {
name = "item."+GetBlockDefinition(movingItem->damage).name;
}
DrawTextB(LocaleGet(name).c_str(), GetMouseX()-16, GetMouseY()+56, 16, WHITE);
}
if(inventoryOpen) UIHandleControls();
}
InventoryItem HotbarGetSelected() {
return hotbar[selected];
}
void DrawSelectedItem(Color tint) {
InventoryItem item = hotbar[selected];
Vector3 center = {-0.75f, -0.45f, 0.5f};
rlPushMatrix();
rlTranslatef(center.x, center.y-0.25f, center.z);
float swing = powf(player_attack_time,1);
float swing3 = sinf(swing * swing * PI);
float swing2 = sinf(sqrt(swing) * PI);
rlRotatef(-swing3 * 50, 1, 0, 0);
rlRotatef(-swing2 * 80, 0, 1, 0);
swing = powf(player_place_time,2);
swing2 = sinf(swing * PI);
rlRotatef(swing2 * 80, 0, 1, 0);
rlRotatef(-45, 1, 0, 0);
rlRotatef(25, 0, 0, 1);
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, tint, 44,20,4,4);
if(item.item != nullptr) {
if(item.item->type == IType_Block) {
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, GetBlockDefinition(item.damage), tint);
}
else {
UVCorners left = GetUVTex(item.item->texture);
rlSetTexture(item_atlas.id);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, 255);
rlNormal3f(1.0f, 0.0f, 0.0f);
const float size = 0.5f;
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size);
rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(0, -12*PIXUNIT + size, 0.25f - size);
rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(0, -12*PIXUNIT + size, 0.25f + size);
rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f + size);
rlEnd();
}
}
rlPopMatrix();
}
bool InputGetKeyDown(const std::string name);
bool InputGetKeyPressed(const std::string name);
void CloseInventory() {
inventoryOpen = false;
movingItem = nullptr;
DisableCursor();
}
void UpdateHotbar() {
if(GetMouseWheelMoveV().y > 0.1f) {
selected++;
if(selected >= ITEMS) {
selected = 0;
}
}
if(GetMouseWheelMoveV().y < -0.1f) {
selected--;
if(selected >= ITEMS) {
selected = ITEMS-1;
}
}
if(IsKeyPressed(KEY_ONE)) {
selected = 0;
}
if(IsKeyPressed(KEY_TWO)) {
selected = 1;
}
if(IsKeyPressed(KEY_THREE)) {
selected = 2;
}
if(IsKeyPressed(KEY_FOUR)) {
selected = 3;
}
if(IsKeyPressed(KEY_FIVE)) {
selected = 4;
}
if(IsKeyPressed(KEY_SIX)) {
selected = 5;
}
if(IsKeyPressed(KEY_SEVEN)) {
selected = 6;
}
if(IsKeyPressed(KEY_EIGHT)) {
selected = 7;
}
if(IsKeyPressed(KEY_NINE)) {
selected = 8;
}
if(IsKeyPressed(KEY_KP_ADD)) {
hotbar[selected].damage++;
}
if(IsKeyPressed(KEY_KP_SUBTRACT)) {
hotbar[selected].damage--;
}
if(InputGetKeyPressed("inventory")) {
inventoryOpen = !inventoryOpen;
if(inventoryOpen) {
EnableCursor();
}
else {
CloseInventory();
}
}
if(IsKeyPressed(KEY_F9)) {
HotbarAddItem(GetItemByID("gold_pickaxe"), 255);
HotbarAddItemLots(GetItemByID("gold_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("copper_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("silver_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("block"), GetNumericIDFromString("stone"), INT32_MAX);
HotbarAddItemLots(GetItemByID("block"), GetNumericIDFromString("planks"), INT32_MAX);
HotbarAddItemLots(GetItemByID("apple"), 255, INT32_MAX);
}
}
#endif