#include<bits/stdc++.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#include <fstream>
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#define key(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1 : 0)
using namespace std;
enum GameState { MAIN_MENU, IN_GAME, INVENTORY_MENU, SETTINGS_MENU, NEW_WORLD_MENU, LOAD_WORLD_MENU, NETHER_DIMENSION };
GameState gameState = MAIN_MENU;
string worldName;
bool isCreativeMode = true;
int world[301][601] = {0};
int netherWorld[301][601] = {0};
int grass[601] = {0};
int x = 300, y = 150;
int seed = 0;
int fps = 100, render = 10;
int currentBlock = 0;
int inventory[10] = {0};
int inventoryCount[10] = {0};
int menuSelection = 0;
int inventorySelection = 0;
int worldSelection = 0;
vector<string> savedWorlds;
int creativeSelection = 0;
bool isSelectingItem = false;
int selectedSlot = -1;
bool inNether = false;
char worldNameInput[50] = "";
char seedInput[20] = "";
int inputPos = 0;
DWORD lastStateChangeTime = 0;
const int STATE_CHANGE_DELAY = 1000;
DWORD lastPortalTime = 0;
const int PORTAL_COOLDOWN = 2000;
void _color(int a) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), a);
}
struct item {
int color;
string appe;
string name;
int maxStack = 999999;
} block[100];
void init() {
block[0].appe = " ";
block[0].color = 144;
block[0].name = "Air";
block[1].appe = "██";
block[1].color = 8;
block[1].name = "Stone";
block[2].appe = " ̄";
block[2].color = 47;
block[2].name = "Grass";
block[3].appe = " ";
block[3].color = 111;
block[3].name = "Dirt";
block[4].appe = "||";
block[4].color = 96;
block[4].name = "Wood";
block[5].appe = "◆◆";
block[5].color = 14;
block[5].name = "Coal Ore";
block[6].appe = "◆◆";
block[6].color = 8;
block[6].name = "Iron Ore";
block[7].appe = "==";
block[7].color = 1;
block[7].name = "Bedrock";
block[8].appe = "◆◆";
block[8].color = 15;
block[8].name = "Gold Ore";
block[9].appe = "◆◆";
block[9].color = 11;
block[9].name = "Diamond Ore";
block[10].appe = "◆◆";
block[10].color = 12;
block[10].name = "Redstone Ore";
block[11].appe = "◆◆";
block[11].color = 13;
block[11].name = "Emerald Ore";
block[12].appe = "◆◆";
block[12].color = 10;
block[12].name = "Copper Ore";
block[13].appe = "██";
block[13].color = 7;
block[13].name = "Cobblestone";
block[14].appe = "██";
block[14].color = 6;
block[14].name = "Bricks";
block[15].appe = "□";
block[15].color = 8;
block[15].name = "Gravel";
block[16].appe = "??";
block[16].color = 143;
block[16].name = "Sand";
block[17].appe = "※";
block[17].color = 15;
block[17].name = "Sandstone";
block[18].appe = "▓▓";
block[18].color = 10;
block[18].name = "Leaves";
block[19].appe = "██";
block[19].color = 130;
block[19].name = "Planks";
block[20].appe = "██";
block[20].color = 136;
block[20].name = "Stone Bricks";
block[21].appe = "~~";
block[21].color = 9;
block[21].name = "Water";
block[21].maxStack = 9999;
block[22].appe = "~~";
block[22].color = 12;
block[22].name = "Lava";
block[22].maxStack = 9999;
block[23].appe = "-=";
block[23].color = 15;
block[23].name = "Glass";
block[24].appe = "##";
block[24].color = 14;
block[24].name = "Glowstone";
block[25].appe = "██";
block[25].color = 112;
block[25].name = "Snow";
block[26].appe = "██";
block[26].color = 159;
block[26].name = "Ice";
block[27].appe = "██";
block[27].color = 42;
block[27].name = "Mossy Cobble";
block[28].appe = "██";
block[28].color = 124;
block[28].name = "Netherrack";
block[29].appe = "██";
block[29].color = 128;
block[29].name = "Soul Sand";
block[30].appe = "██";
block[30].color = 192;
block[30].name = "Nether Brick";
block[31].appe = "FL";
block[31].color = 8;
block[31].name = "Flint and Steel";
block[31].maxStack = 1;
block[32].appe = "██";
block[32].color = 5;
block[32].name = "Obsidian";
block[33].appe = "##";
block[33].color = 13;
block[33].name = "Nether Portal";
block[33].maxStack = 0;
block[34].appe = "**";
block[34].color = 12;
block[34].name = "Fire";
block[34].maxStack = 0;
block[35].appe = "◆◆";
block[35].color = 15;
block[35].name = "Nether Quartz";
block[36].appe = "◆◆";
block[36].color = 14;
block[36].name = "Nether Gold";
block[37].appe = " ";
block[37].color = 204;
block[37].name = "Nether Air";
block[38].appe = "MM";
block[38].color = 13;
block[38].name = "Nether Mushroom";
block[39].appe = "MM";
block[39].color = 12;
block[39].name = "Magma Block";
for(int i = 0; i < 10; i++) {
inventory[i] = 0;
inventoryCount[i] = 0;
}
}
void print(int id) {
if(id >= 0 && id < 100 && block[id].color >= 0) {
_color(block[id].color);
printf("%s", block[id].appe.c_str());
} else {
_color(15);
printf(" ");
}
}
bool checkNetherPortalOverworld(int x, int y);
bool checkNetherPortalNether(int x, int y);
void activateNetherPortalOverworld(int x, int y);
void activateNetherPortalNether(int x, int y);
void useFlintAndSteel(int x, int y);
void enterNether();
void returnToOverworld();
void generateNether();
void checkAndEnterPortal();
int ran(int x);
void spawn_tree(int x);
void generateWater();
void maps();
void showHotbar();
void showCreativeInventory();
void showInventoryMenu();
void addToInventory(int blockId);
void placeBlock();
bool worldExists(string filename);
void saveGame();
void loadGame(string filename);
void getSavedWorlds();
void screen();
void setting();
void showMainMenu();
void showNewWorldMenu();
void showLoadWorldMenu();
bool checkNetherPortalNether(int x, int y) {
if(x < 1 || x > 597 || y < 1 || y > 296) return false;
for(int i = 0; i < 5; i++) {
if(netherWorld[y + i][x] != 32) return false;
if(netherWorld[y + i][x + 3] != 32) return false;
}
for(int i = 0; i < 4; i++) {
if(netherWorld[y][x + i] != 32) return false;
if(netherWorld[y + 4][x + i] != 32) return false;
}
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 3; j++) {
if(netherWorld[y + j][x + i] != 0 && netherWorld[y + j][x + i] != 37) return false;
}
}
return true;
}
void activateNetherPortalNether(int x, int y) {
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 3; j++) {
netherWorld[y + j][x + i] = 33;
}
}
}
void useFlintAndSteel(int x, int y) {
if(inventory[currentBlock] != 31) return;
if(!inNether) {
if(world[y][x] == 32) {
for(int offsetX = -3; offsetX <= 0; offsetX++) {
for(int offsetY = -4; offsetY <= 0; offsetY++) {
int portalX = x + offsetX;
int portalY = y + offsetY;
if(portalX >= 1 && portalX <= 597 && portalY >= 1 && portalY <= 296) {
if(checkNetherPortalOverworld(portalX, portalY)) {
activateNetherPortalOverworld(portalX, portalY);
_color(10);
printf("Nether Portal Activated!\n");
Sleep(500);
return;
}
}
}
}
world[y][x] = 34;
_color(12);
printf("Fire!\n");
Sleep(200);
}
} else {
if(netherWorld[y][x] == 32) {
for(int offsetX = -3; offsetX <= 0; offsetX++) {
for(int offsetY = -4; offsetY <= 0; offsetY++) {
int portalX = x + offsetX;
int portalY = y + offsetY;
if(portalX >= 1 && portalX <= 597 && portalY >= 1 && portalY <= 296) {
if(checkNetherPortalNether(portalX, portalY)) {
activateNetherPortalNether(portalX, portalY);
_color(10);
printf("Nether Portal Activated!\n");
Sleep(500);
return;
}
}
}
}
netherWorld[y][x] = 34;
_color(12);
printf("Fire!\n");
Sleep(200);
}
}
}
void checkAndEnterPortal() {
DWORD currentTime = GetTickCount();
if(currentTime - lastPortalTime < PORTAL_COOLDOWN) {
return;
}
if(!inNether) {
if(world[y][x] == 33) {
lastPortalTime = currentTime;
enterNether();
}
} else {
if(netherWorld[y][x] == 33) {
lastPortalTime = currentTime;
returnToOverworld();
}
}
}
void enterNether() {
if(inNether) return;
inNether = true;
gameState = NETHER_DIMENSION;
lastStateChangeTime = GetTickCount();
_color(12);
printf("Entering the Nether...\n");
Sleep(1000);
bool netherEmpty = true;
for(int i = 1; i <= 300; i++) {
for(int j = 1; j <= 600; j++) {
if(netherWorld[i][j] != 0 && netherWorld[i][j] != 37) {
netherEmpty = false;
break;
}
}
if(!netherEmpty) break;
}
if(netherEmpty) {
generateNether();
}
int portalX = min(max(x, 2), 597);
int portalY = min(max(y, 2), 296);
if(portalX > 597) portalX = 597;
if(portalX < 1) portalX = 1;
for(int i = 0; i < 5; i++) {
netherWorld[portalY + i][portalX] = 32;
netherWorld[portalY + i][portalX + 3] = 32;
}
for(int i = 0; i < 4; i++) {
netherWorld[portalY][portalX + i] = 32;
netherWorld[portalY + 4][portalX + i] = 32;
}
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 3; j++) {
netherWorld[portalY + j][portalX + i] = 33;
}
}
x = portalX + 1;
y = portalY + 2;
}
void returnToOverworld() {
if(!inNether) return;
inNether = false;
gameState = IN_GAME;
lastStateChangeTime = GetTickCount();
_color(11);
printf("Returning to Overworld...\n");
Sleep(1000);
int portalX = min(max(x, 2), 597);
int portalY = min(max(y, 2), 296);
if(!checkNetherPortalOverworld(portalX, portalY)) {
for(int i = 0; i < 5; i++) {
world[portalY + i][portalX] = 32;
world[portalY + i][portalX + 3] = 32;
}
for(int i = 0; i < 4; i++) {
world[portalY][portalX + i] = 32;
world[portalY + 4][portalX + i] = 32;
}
}
activateNetherPortalOverworld(portalX, portalY);
x = portalX + 1;
y = portalY + 2;
}
void generateNether() {
memset(netherWorld, 0, sizeof(netherWorld));
for(int j = 1; j <= 600; j++) {
netherWorld[1][j] = 7;
netherWorld[300][j] = 7;
if(j % 10 == 0) {
netherWorld[2][j] = 7;
netherWorld[299][j] = 7;
}
}
int heightMap[601];
int noise = 0;
heightMap[1] = 50 + rand() % 50;
for(int j = 2; j <= 600; j++) {
int change = rand() % 3 - 1;
heightMap[j] = max(10, min(200, heightMap[j-1] + change * (rand() % 3 + 1)));
}
for(int j = 2; j < 600; j++) {
heightMap[j] = (heightMap[j-1] + heightMap[j] + heightMap[j+1]) / 3;
}
for(int j = 1; j <= 600; j++) {
int groundHeight = heightMap[j];
int ceilingHeight = groundHeight - 80 + rand() % 40;
for(int i = 2; i <= 299; i++) {
if(i <= ceilingHeight) {
netherWorld[i][j] = 37;
} else if(i <= groundHeight) {
netherWorld[i][j] = 28;
} else {
netherWorld[i][j] = 37;
}
}
}
int lavaSeaLevel = 200;
for(int j = 1; j <= 600; j++) {
for(int i = lavaSeaLevel - 5; i <= lavaSeaLevel + 5; i++) {
if(i >= 2 && i <= 299 && netherWorld[i][j] == 28) {
netherWorld[i][j] = 22;
}
}
}
for(int cave = 0; cave < 15; cave++) {
int cave_x = rand() % 600 + 1;
int cave_y = 100 + rand() % 100;
int cave_size = rand() % 20 + 10;
for(int i = -cave_size; i <= cave_size; i++) {
for(int jj = -cave_size; jj <= cave_size; jj++) {
if(i*i + jj*jj <= cave_size*cave_size) {
int nx = cave_x + i;
int ny = cave_y + jj;
if(nx >= 1 && nx <= 600 && ny >= 2 && ny <= 299) {
if(netherWorld[ny][nx] == 28) {
netherWorld[ny][nx] = 37;
}
}
}
}
}
}
for(int j = 1; j <= 600; j++) {
for(int i = 2; i <= 299; i++) {
if(netherWorld[i][j] == 37 && netherWorld[i-1][j] == 28) {
if(rand() % 100 < 2) {
int glowstoneHeight = rand() % 5 + 1;
for(int k = 0; k < glowstoneHeight; k++) {
if(i + k <= 299 && netherWorld[i + k][j] == 37) {
netherWorld[i + k][j] = 24;
}
}
}
}
}
}
for(int mushroom = 0; mushroom < 30; mushroom++) {
int mush_x = rand() % 600 + 1;
int mush_y = 0;
for(int i = 2; i <= 299; i++) {
if(netherWorld[i][mush_x] == 28 && netherWorld[i+1][mush_x] == 37) {
mush_y = i + 1;
break;
}
}
if(mush_y > 0 && mush_y <= 299) {
int mush_size = rand() % 5 + 3;
for(int i = -mush_size; i <= mush_size; i++) {
for(int jj = -mush_size; jj <= mush_size; jj++) {
if(i*i + jj*jj <= mush_size*mush_size) {
int nx = mush_x + i;
int ny = mush_y + jj;
if(nx >= 1 && nx <= 600 && ny >= 2 && ny <= 299) {
if(netherWorld[ny][nx] == 37 && rand() % 3 == 0) {
netherWorld[ny][nx] = 38;
}
}
}
}
}
}
}
for(int j = 1; j <= 600; j++) {
for(int i = 2; i <= 299; i++) {
if(netherWorld[i][j] == 28) {
if(rand() % 100 < 3) {
netherWorld[i][j] = 15;
}
if(i > 150 && rand() % 100 < 5) {
netherWorld[i][j] = 29;
}
}
}
}
for(int j = 1; j <= 600; j++) {
for(int i = lavaSeaLevel - 10; i <= lavaSeaLevel + 10; i++) {
if(i >= 2 && i <= 299 && netherWorld[i][j] == 28) {
if(rand() % 100 < 8) {
netherWorld[i][j] = 39;
}
}
}
}
int quartzCount = 200;
for(int q = 0; q < quartzCount; q++) {
int qx = rand() % 600 + 1;
int qy = 50 + rand() % 200;
if(qx >= 1 && qx <= 600 && qy >= 2 && qy <= 299) {
if(netherWorld[qy][qx] == 28) {
netherWorld[qy][qx] = 35;
if(rand() % 3 == 0) {
int veinSize = rand() % 3 + 1;
for(int dx = -veinSize; dx <= veinSize; dx++) {
for(int dy = -veinSize; dy <= veinSize; dy++) {
if(abs(dx) + abs(dy) <= veinSize) {
int nx = qx + dx;
int ny = qy + dy;
if(nx >= 1 && nx <= 600 && ny >= 2 && ny <= 299) {
if(netherWorld[ny][nx] == 28) {
netherWorld[ny][nx] = 35;
}
}
}
}
}
}
}
}
}
int goldCount = 100;
for(int g = 0; g < goldCount; g++) {
int gx = rand() % 600 + 1;
int gy = 0;
int locationType = rand() % 3;
if(locationType == 0) {
for(int i = 100; i <= 250; i++) {
if(netherWorld[i][gx] == 37 && netherWorld[i+1][gx] == 28) {
gy = i;
break;
}
}
} else if(locationType == 1) {
for(int i = 2; i <= 299; i++) {
if(netherWorld[i][gx] == 28 && netherWorld[i+1][gx] == 37) {
gy = i;
break;
}
}
} else {
gy = lavaSeaLevel - (rand() % 10 + 5);
}
if(gy > 0 && gy <= 299 && netherWorld[gy][gx] == 28) {
netherWorld[gy][gx] = 36;
if(rand() % 2 == 0) {
int veinSize = rand() % 2 + 1;
for(int dx = -veinSize; dx <= veinSize; dx++) {
for(int dy = -veinSize; dy <= veinSize; dy++) {
if(abs(dx) + abs(dy) <= veinSize) {
int nx = gx + dx;
int ny = gy + dy;
if(nx >= 1 && nx <= 600 && ny >= 2 && ny <= 299) {
if(netherWorld[ny][nx] == 28) {
netherWorld[ny][nx] = 36;
}
}
}
}
}
}
}
}
for(int structure = 0; structure < 10; structure++) {
int sx = rand() % 600 + 1;
int sy = 0;
for(int i = 2; i <= 299; i++) {
if(netherWorld[i][sx] == 28 && netherWorld[i+1][sx] == 37) {
sy = i;
break;
}
}
if(sy > 0 && sy <= 299) {
int structureHeight = rand() % 10 + 5;
int structureWidth = rand() % 8 + 4;
for(int i = 0; i < structureHeight; i++) {
for(int jj = -structureWidth/2; jj <= structureWidth/2; jj++) {
int nx = sx + jj;
int ny = sy - i;
if(nx >= 1 && nx <= 600 && ny >= 2 && ny <= 299) {
if(i == 0 || i == structureHeight-1 || jj == -structureWidth/2 || jj == structureWidth/2) {
if(rand() % 3 == 0) {
netherWorld[ny][nx] = 30;
}
}
}
}
}
}
}
}
bool checkNetherPortalOverworld(int x, int y) {
if(x < 1 || x > 597 || y < 1 || y > 296) return false;
for(int i = 0; i < 5; i++) {
if(world[y + i][x] != 32) return false;
if(world[y + i][x + 3] != 32) return false;
}
for(int i = 0; i < 4; i++) {
if(world[y][x + i] != 32) return false;
if(world[y + 4][x + i] != 32) return false;
}
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 3; j++) {
if(world[y + j][x + i] != 0) return false;
}
}
return true;
}
void activateNetherPortalOverworld(int x, int y) {
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 3; j++) {
world[y + j][x + i] = 33;
}
}
}
int ran(int x) {
int a = 50;
for (int i = 1; i <= x; i++) {
a = rand();
}
return a;
}
void spawn_tree(int x){
int height=ran(x)%3+4;
int treesize=1+(ran(x)%4);
int i,j;
if(grass[x]-2*treesize-height-1>=0){
for(i=1;i<=height;i++){
world[grass[x]-i][x]=4;
}
for(i=grass[x]-2*treesize-height-1;i<grass[x]-height;i++){
for(j=x-treesize;j<=x+treesize;j++){
world[i][j]=18;
}
}
}
}
void generateWater() {
vector<pair<int, int>> lowPoints;
for(int j = 2; j < 600; j++) {
if(grass[j] > grass[j-1] && grass[j] > grass[j+1]) {
int valleyDepth = min(grass[j] - grass[j-1], grass[j] - grass[j+1]);
if(valleyDepth >= 3) {
lowPoints.push_back({j, grass[j]});
}
}
}
for(auto& point : lowPoints) {
int startX = point.first;
int waterLevel = point.second + 1;
int leftX = startX;
while(leftX > 1 && grass[leftX] <= waterLevel) {
leftX--;
}
int rightX = startX;
while(rightX < 600 && grass[rightX] <= waterLevel) {
rightX++;
}
waterLevel = min(waterLevel, grass[startX] + 5);
for(int xx = leftX; xx <= rightX; xx++) {
for(int yy = waterLevel; yy <= waterLevel + 3; yy++) {
if(yy <= 300 && world[yy][xx] == 0) {
world[yy][xx] = 21;
}
}
}
}
}
void maps() {
int i, j, k;
grass[1] = ran(seed) % 15 + 20;
for (k = 2; k <= 600; k++) {
int r = ran(seed + k - 1) % 3;
if (r == 0) grass[k] = grass[k - 1] + 1;
else if (r == 1) grass[k] = grass[k - 1] - 1;
else grass[k] = grass[k - 1];
if(grass[k] < 10) grass[k] = 10;
if(grass[k] > 50) grass[k] = 50;
}
for (j = 1; j <= 600; j++) {
for (i = 1; i < grass[j]; i++) {
world[i][j] = 0;
}
world[grass[j]][j] = 2;
for (i = grass[j] + 1; i <= grass[j] + 10; i++) {
if(i <= 300) world[i][j] = 3;
}
for (i = grass[j] + 11; i <= 299; i++) {
if(i <= 300) world[i][j] = 1;
}
world[300][j] = 7;
}
generateWater();
for (int cave = 0; cave < 40; cave++) {
int cave_x = ran(seed + cave * 100) % 600 + 1;
int cave_y = ran(seed + cave * 200) % 100 + grass[cave_x] + 15;
int cave_size = ran(seed + cave * 300) % 10 + 5;
for (int i = -cave_size; i <= cave_size; i++) {
for (int jj = -cave_size; jj <= cave_size; jj++) {
if (i*i + jj*jj <= cave_size*cave_size) {
int nx = cave_x + i;
int ny = cave_y + jj;
if (nx >= 1 && nx <= 600 && ny >= 1 && ny <= 300) {
if (world[ny][nx] == 1) world[ny][nx] = 0;
}
}
}
}
}
for(i = 7; i <= 593; i++){
if(ran(grass[i]) % 11 == 8){
spawn_tree(i);
}
}
}
void showHotbar() {
_color(15);
printf("\n");
for(int i = 0; i < 10; i++) {
if(i == currentBlock) {
_color(240);
} else {
_color(15);
}
printf("[");
if(inventory[i] > 0 && inventoryCount[i] > 0) {
print(inventory[i]);
_color(15);
} else {
printf(" ");
_color(15);
}
printf("] ");
}
_color(14);
printf(" Selected: ");
if(inventory[currentBlock] > 0 && inventoryCount[currentBlock] > 0) {
print(inventory[currentBlock]);
_color(14);
printf(" %s", block[inventory[currentBlock]].name.c_str());
} else {
printf("Empty");
}
}
void showCreativeInventory() {
system("cls");
lastStateChangeTime = GetTickCount();
int creativeItems[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, 21,22,23,24,25,26,27,28,29,30,31,32,35,36,38,39};
int itemCount = 36;
while(true) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf("=== CREATIVE INVENTORY ===\n");
_color(15);
printf("WASD: Move Space: Select ESC: Back\n\n");
for(int i = 0; i < itemCount; i++) {
if(i == creativeSelection) {
_color(240);
} else {
_color(15);
}
printf("%02d. ", i+1);
print(creativeItems[i]);
printf(" %s", block[creativeItems[i]].name.c_str());
if(i == creativeSelection) printf(" <--");
printf("\n");
}
if(key('W') && creativeSelection > 0) {
creativeSelection--;
Sleep(150);
}
if(key('S') && creativeSelection < itemCount-1) {
creativeSelection++;
Sleep(150);
}
if(key(VK_SPACE)) {
if(currentBlock >= 0 && currentBlock < 10) {
inventory[currentBlock] = creativeItems[creativeSelection];
inventoryCount[currentBlock] = 9999;
return;
}
}
if(key(VK_ESCAPE)) {
return;
}
Sleep(50);
}
}
void showInventoryMenu() {
system("cls");
lastStateChangeTime = GetTickCount();
while(true) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf("=== INVENTORY ===\n");
_color(15);
printf("WASD: Move Space: Select/Exchange ESC: Exit\n\n");
for(int i = 0; i < 10; i++) {
if(i == inventorySelection) {
_color(240);
} else {
_color(15);
}
printf("Slot %d: ", i);
if(inventory[i] > 0 && inventoryCount[i] > 0) {
print(inventory[i]);
_color(i == inventorySelection ? 240 : 15);
printf(" %s ", block[inventory[i]].name.c_str());
} else {
printf("Empty");
}
if(i == currentBlock) printf(" [HOTBAR]");
if(isSelectingItem && selectedSlot == i) printf(" [SELECTED]");
printf("\n");
}
printf("\n");
if(inventorySelection == 10) {
_color(240);
printf("> Creative Menu <\n");
_color(15);
} else {
printf(" Creative Menu\n");
}
if(key('W') && inventorySelection > 0) {
inventorySelection--;
Sleep(150);
}
if(key('S') && inventorySelection < 10) {
inventorySelection++;
Sleep(150);
}
if(key(VK_SPACE)) {
if(inventorySelection == 10) {
showCreativeInventory();
inventorySelection = 0;
} else {
if(!isSelectingItem) {
isSelectingItem = true;
selectedSlot = inventorySelection;
} else {
if(selectedSlot != inventorySelection) {
swap(inventory[selectedSlot], inventory[inventorySelection]);
swap(inventoryCount[selectedSlot], inventoryCount[inventorySelection]);
}
isSelectingItem = false;
selectedSlot = -1;
}
}
}
if(key(VK_ESCAPE)) {
isSelectingItem = false;
selectedSlot = -1;
return;
}
Sleep(50);
}
}
void addToInventory(int blockId) {
if(blockId == 0 || blockId == 7 || blockId == 33 || blockId == 34 || blockId == 37) return;
for(int i = 0; i < 10; i++) {
if(inventory[i] == blockId && inventoryCount[i] < 9999) {
inventoryCount[i]++;
return;
}
}
for(int i = 0; i < 10; i++) {
if(inventory[i] == 0) {
inventory[i] = blockId;
inventoryCount[i] = 1;
return;
}
}
}
void placeBlock() {
if(inventory[currentBlock] > 0 && inventoryCount[currentBlock] > 0) {
if(!inNether) {
if(world[y][x] == 0 || world[y][x] == 21 || world[y][x] == 22) {
world[y][x] = inventory[currentBlock];
}
} else {
if(netherWorld[y][x] == 0 || netherWorld[y][x] == 21 || netherWorld[y][x] == 22 || netherWorld[y][x] == 37) {
netherWorld[y][x] = inventory[currentBlock];
}
}
}
}
bool worldExists(string filename) {
string path = "saves/" + filename + ".dat";
struct stat buffer;
return (stat(path.c_str(), &buffer) == 0);
}
void saveGame() {
_mkdir("saves");
string path = "saves/" + worldName + ".dat";
if(worldExists(worldName) && worldName != "quicksave") {
_color(12);
printf("World name already exists!\n");
Sleep(1000);
return;
}
ofstream file(path.c_str(), ios::binary);
if(!file.is_open()) {
_color(12);
printf("Failed to create save file!\n");
Sleep(1000);
return;
}
file.write((char*)&seed, sizeof(int));
file.write((char*)&x, sizeof(int));
file.write((char*)&y, sizeof(int));
file.write((char*)&inNether, sizeof(bool));
file.write((char*)&isCreativeMode, sizeof(bool));
for(int i = 0; i <= 300; i++) {
file.write((char*)&world[i][0], 601 * sizeof(int));
}
for(int i = 0; i <= 300; i++) {
file.write((char*)&netherWorld[i][0], 601 * sizeof(int));
}
file.write((char*)inventory, 10 * sizeof(int));
file.write((char*)inventoryCount, 10 * sizeof(int));
file.close();
_color(10);
printf("Game saved to %s\n", path.c_str());
Sleep(1000);
}
void loadGame(string filename) {
string path = "saves/" + filename + ".dat";
if(!worldExists(filename)) {
_color(12);
printf("Save file not found: %s\n", path.c_str());
Sleep(1000);
return;
}
ifstream file(path.c_str(), ios::binary);
if(!file.is_open()) {
_color(12);
printf("Failed to open save file!\n");
Sleep(1000);
return;
}
file.read((char*)&seed, sizeof(int));
file.read((char*)&x, sizeof(int));
file.read((char*)&y, sizeof(int));
file.read((char*)&inNether, sizeof(bool));
file.read((char*)&isCreativeMode, sizeof(bool));
for(int i = 0; i <= 300; i++) {
file.read((char*)&world[i][0], 601 * sizeof(int));
}
for(int i = 0; i <= 300; i++) {
file.read((char*)&netherWorld[i][0], 601 * sizeof(int));
}
file.read((char*)inventory, 10 * sizeof(int));
file.read((char*)inventoryCount, 10 * sizeof(int));
file.close();
worldName = filename;
_color(10);
printf("Game loaded from %s\n", path.c_str());
Sleep(1000);
}
void getSavedWorlds() {
savedWorlds.clear();
struct stat info;
if(stat("saves", &info) != 0) {
_mkdir("saves");
return;
}
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile("saves\\*.dat", &findFileData);
if(hFind != INVALID_HANDLE_VALUE) {
do {
string filename = findFileData.cFileName;
filename = filename.substr(0, filename.length() - 4);
savedWorlds.push_back(filename);
} while(FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
}
}
void screen() {
int i, j;
int (*currentWorld)[601] = inNether ? netherWorld : world;
int startY = max(1, y - render);
int endY = min(300, y + render);
int startX = max(1, x - render);
int endX = min(600, x + render);
for (i = startY; i <= endY; i++) {
for (j = startX; j <= endX; j++) {
if (i == y && j == x) {
_color(11);
printf("[]");
} else {
if(inNether && currentWorld[i][j] == 0) {
print(37);
} else {
print(currentWorld[i][j]);
}
}
printf("\n");
}
}
_color(14);
printf("POS X:%d Y:%d ", x, y);
_color(10);
printf("FPS:%d ", 1000/fps);
_color(11);
printf("Render:%d ", render);
if(inNether) {
_color(12);
printf("NETHER ");
} else {
_color(11);
printf("OVERWORLD ");
}
_color(14);
if(!worldName.empty()) {
printf("World: %s", worldName.c_str());
}
showHotbar();
_color(8);
printf("\nE:Inventory P:Settings F5:Save F6:Load ESC:Menu");
}
void setting() {
int op = 0;
int newfps = fps, newrender = render;
system("cls");
lastStateChangeTime = GetTickCount();
while (true) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(15);
printf("### Settings ###\n\n");
for(int i = 0; i < 5; i++) {
if(i == op) {
_color(240);
} else {
_color(15);
}
switch(i) {
case 0: printf("> Frame Rate: ");
if(newfps == 200) printf("[5fps] 10fps 50fps");
else if(newfps == 100) printf("5fps [10fps] 50fps");
else printf("5fps 10fps [50fps]");
break;
case 1: printf("> Render Distance: ");
if(newrender == 5) printf("[5] 10 15");
else if(newrender == 10) printf("5 [10] 15");
else printf("5 10 [15]");
break;
case 2: printf("> Save Game");
break;
case 3: printf("> Load Game");
break;
case 4: printf("> Back to Game");
break;
}
printf("\n");
}
_color(8);
printf("\nWASD: Navigate Space: Select D: Change value\n");
if(key('W') && op > 0) {
op--;
Sleep(150);
}
if(key('S') && op < 4) {
op++;
Sleep(150);
}
if(key(VK_SPACE) || key('A')) {
switch(op) {
case 0:
if(newfps == 200) newfps = 100;
else if(newfps == 100) newfps = 18;
else newfps = 200;
break;
case 1:
if(newrender == 5) newrender = 10;
else if(newrender == 10) newrender = 15;
else newrender = 5;
break;
case 2:
saveGame();
break;
case 3:
gameState = LOAD_WORLD_MENU;
getSavedWorlds();
return;
case 4:
fps = newfps;
render = newrender;
gameState = IN_GAME;
return;
}
Sleep(150);
}
if(key('D')) {
switch(op) {
case 0:
if(newfps == 200) newfps = 100;
else if(newfps == 100) newfps = 18;
else newfps = 200;
break;
case 1:
if(newrender == 5) newrender = 10;
else if(newrender == 10) newrender = 15;
else newrender = 5;
break;
}
Sleep(150);
}
if(key(VK_ESCAPE)) {
gameState = IN_GAME;
return;
}
Sleep(50);
}
}
void showMainMenu() {
menuSelection = 0;
system("cls");
lastStateChangeTime = GetTickCount();
while(gameState == MAIN_MENU) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf(" Paper Minecraft v3.0 \n");
_color(15);
printf(" Enhanced Edition \n\n");
string menuItems[] = {"New World", "Load World", "About", "Quit"};
for(int i = 0; i < 4; i++) {
if(i == menuSelection) {
_color(224);
printf(" > %s < \n", menuItems[i].c_str());
_color(15);
} else {
_color(15);
printf(" %s \n", menuItems[i].c_str());
}
}
_color(7);
printf("\nWASD: Navigate Space: Select\n");
if(key('W') && menuSelection > 0) {
menuSelection--;
Sleep(200);
}
if(key('S') && menuSelection < 3) {
menuSelection++;
Sleep(200);
}
if(key(VK_SPACE)) {
switch(menuSelection) {
case 0:
memset(worldNameInput, 0, sizeof(worldNameInput));
inputPos = 0;
gameState = NEW_WORLD_MENU;
lastStateChangeTime = GetTickCount();
return;
case 1:
gameState = LOAD_WORLD_MENU;
getSavedWorlds();
lastStateChangeTime = GetTickCount();
return;
case 2:
system("cls");
_color(14);
printf("\n\n About Paper Minecraft v3.0\n\n");
_color(15);
printf(" Enhanced Features:\n");
printf(" - Nether Dimension\n");
printf(" - Improved Water Generation\n");
printf(" - Enhanced Inventory System\n");
printf(" - World Management\n\n");
printf(" Controls:\n");
printf(" WASD - Move/Navigate menus\n");
printf(" Space - Select/Place block\n");
printf(" E - Open inventory\n");
printf(" X - Destroy block\n");
printf(" P - Settings\n");
printf(" F5 - Quick Save\n");
printf(" F6 - Quick Load\n");
printf(" ESC - Pause menu\n\n");
_color(9);
printf(" Press any key to continue...");
while(!_kbhit());
_getch();
break;
case 3:
exit(0);
}
Sleep(200);
}
Sleep(100);
}
}
void showNewWorldMenu() {
memset(worldNameInput, 0, sizeof(worldNameInput));
memset(seedInput, 0, sizeof(seedInput));
int currentInput = 0;
system("cls");
lastStateChangeTime = GetTickCount();
while(gameState == NEW_WORLD_MENU) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf("=== Create New World ===\n\n");
_color(15);
printf("World Name: %s", worldNameInput);
if(currentInput == 0) printf("_");
printf("\n");
_color(15);
printf("Seed (press Enter for random): %s", seedInput);
if(currentInput == 1) printf("_");
printf("\n\n");
_color(8);
printf("Press Enter to confirm input\n");
printf("Press ESC to go back\n");
if(_kbhit()) {
char ch = _getch();
if(ch == '\r' || ch == '\n') {
if(currentInput == 0) {
if(strlen(worldNameInput) == 0) {
_color(12);
printf("\nWorld name cannot be empty!\n");
Sleep(1000);
continue;
}
worldName = worldNameInput;
if(worldExists(worldName)) {
_color(12);
printf("\nWorld name already exists!\n");
Sleep(1000);
continue;
}
currentInput = 1;
} else if(currentInput == 1) {
if(strlen(seedInput) > 0) {
seed = atoi(seedInput);
} else {
seed = (time(NULL) + GetTickCount()) % 1000000;
sprintf(seedInput, "%d", seed);
}
printf("\nGenerating terrain...\n");
seed = abs(seed % 10001);
srand(seed);
memset(world, 0, sizeof(world));
memset(netherWorld, 0, sizeof(netherWorld));
memset(grass, 0, sizeof(grass));
init();
maps();
generateNether();
x = 300;
y = grass[300] > 0 ? grass[300] - 1 : 150;
inventory[0] = 2;
inventoryCount[0] = 999999;
inventory[1] = 3;
inventoryCount[1] = 999999;
inventory[2] = 1;
inventoryCount[2] = 999999;
inventory[3] = 32;
inventoryCount[3] = 999999;
inventory[4] = 31;
inventoryCount[4] = 1;
gameState = IN_GAME;
lastStateChangeTime = GetTickCount();
return;
}
} else if(ch == '\b') {
if(currentInput == 0 && strlen(worldNameInput) > 0) {
worldNameInput[strlen(worldNameInput)-1] = '\0';
} else if(currentInput == 1 && strlen(seedInput) > 0) {
seedInput[strlen(seedInput)-1] = '\0';
}
} else if(ch == 27) {
gameState = MAIN_MENU;
lastStateChangeTime = GetTickCount();
return;
} else if(isprint(ch)) {
if(currentInput == 0 && strlen(worldNameInput) < 49) {
int len = strlen(worldNameInput);
worldNameInput[len] = ch;
worldNameInput[len+1] = '\0';
} else if(currentInput == 1 && strlen(seedInput) < 19) {
if(isdigit(ch) || ch == '-') {
int len = strlen(seedInput);
seedInput[len] = ch;
seedInput[len+1] = '\0';
}
}
}
}
Sleep(50);
}
}
void showLoadWorldMenu() {
worldSelection = 0;
system("cls");
lastStateChangeTime = GetTickCount();
while(gameState == LOAD_WORLD_MENU) {
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf("=== Load World ===\n\n");
if(savedWorlds.empty()) {
_color(15);
printf("No saved worlds found!\n\n");
} else {
for(int i = 0; i < savedWorlds.size(); i++) {
if(i == worldSelection) {
_color(240);
printf("> %s <\n", savedWorlds[i].c_str());
_color(15);
} else {
printf(" %s\n", savedWorlds[i].c_str());
}
}
}
printf("\n");
if(worldSelection == savedWorlds.size()) {
_color(240);
printf("> Back <\n");
_color(15);
} else {
printf(" Back\n");
}
_color(8);
printf("\nWASD: Navigate Space: Select ESC: Back\n");
int totalItems = savedWorlds.size() + 1;
if(key('W') && worldSelection > 0) {
worldSelection--;
Sleep(200);
}
if(key('S') && worldSelection < totalItems - 1) {
worldSelection++;
Sleep(200);
}
if(key(VK_SPACE)) {
if(worldSelection < savedWorlds.size()) {
loadGame(savedWorlds[worldSelection]);
gameState = IN_GAME;
lastStateChangeTime = GetTickCount();
return;
} else {
gameState = MAIN_MENU;
lastStateChangeTime = GetTickCount();
return;
}
}
if(key(VK_ESCAPE)) {
gameState = MAIN_MENU;
lastStateChangeTime = GetTickCount();
return;
}
Sleep(100);
}
}
int main() {
system("title Paper Minecraft v3.0 - Enhanced Edition");
system("mode con cols=130 lines=45");
srand(time(NULL));
init();
while(true) {
switch(gameState) {
case MAIN_MENU:
showMainMenu();
break;
case NEW_WORLD_MENU:
showNewWorldMenu();
break;
case LOAD_WORLD_MENU:
showLoadWorldMenu();
break;
case IN_GAME:
case NETHER_DIMENSION:
screen();
if(GetTickCount() - lastStateChangeTime < STATE_CHANGE_DELAY) {
Sleep(fps);
system("cls");
break;
}
if (key('W')) y--;
if (key('S')) y++;
if (key('A')) x--;
if (key('D')) x++;
if (x > 600) x = 600;
if (x < 1) x = 1;
if (y > 300) y = 300;
if (y < 1) y = 1;
for(int i = 0; i < 10; i++) {
if(key('0' + i)) {
currentBlock = i;
}
}
if (key('X')) {
int destroyedBlock;
if(!inNether) {
destroyedBlock = world[y][x];
if(destroyedBlock != 0 && destroyedBlock != 7 && destroyedBlock != 33 && destroyedBlock != 34) {
world[y][x] = 0;
addToInventory(destroyedBlock);
}
} else {
destroyedBlock = netherWorld[y][x];
if(destroyedBlock != 0 && destroyedBlock != 7 && destroyedBlock != 33 && destroyedBlock != 34 && destroyedBlock != 37) {
netherWorld[y][x] = 37;
addToInventory(destroyedBlock);
}
}
}
if (key(VK_SPACE)) {
if(inventory[currentBlock] == 31) {
useFlintAndSteel(x, y);
} else {
placeBlock();
}
}
checkAndEnterPortal();
if (key('E')) {
showInventoryMenu();
}
if (key('P')) {
setting();
}
if (key(VK_F5)) {
if(!worldName.empty()) {
saveGame();
}
}
if (key(VK_F6)) {
if(worldExists("quicksave")) {
loadGame("quicksave");
}
}
if (key(VK_ESCAPE)) {
int pauseSelection = 0;
DWORD pauseStartTime = GetTickCount();
while(true) {
if(GetTickCount() - pauseStartTime < 500) {
Sleep(100);
continue;
}
system("cls");
_color(14);
printf("=== Game Paused ===\n\n");
string pauseItems[] = {"Resume", "Save Game", "Load Game", "Settings", "Quit to Menu"};
for(int i = 0; i < 5; i++) {
if(i == pauseSelection) {
_color(240);
printf("> %s <\n", pauseItems[i].c_str());
_color(15);
} else {
printf(" %s\n", pauseItems[i].c_str());
}
}
_color(8);
printf("\nWASD: Navigate Space: Select\n");
if(key('W') && pauseSelection > 0) {
pauseSelection--;
Sleep(200);
}
if(key('S') && pauseSelection < 4) {
pauseSelection++;
Sleep(200);
}
if(key(VK_SPACE)) {
switch(pauseSelection) {
case 0:
break;
case 1:
saveGame();
continue;
case 2:
gameState = LOAD_WORLD_MENU;
getSavedWorlds();
lastStateChangeTime = GetTickCount();
break;
case 3:
setting();
break;
case 4:
gameState = MAIN_MENU;
lastStateChangeTime = GetTickCount();
break;
}
break;
}
if(key(VK_ESCAPE)) {
break;
}
Sleep(100);
}
}
Sleep(fps);
system("cls");
break;
}
}
return 0;
}