#ifndef SERVER #include #include #include "common.hpp" #include #include #include #include #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 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 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 validRecipes; for (Recipe r : recipes) { if(r.requiredStation == "hands") { std::vector 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 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