554 lines
20 KiB
C++
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(®istry[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(®istry[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 = ®istry[0];
|
|
item.damage = i;
|
|
}
|
|
else if (i < registry.size()+MAX_BLOCK_ID-1) {
|
|
item.item = ®istry[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 |