diff --git a/modifiedeight-newadditions/assets/images/achievements/ac1.png b/modifiedeight-newadditions/assets/images/achievements/ac1.png new file mode 100644 index 00000000..b3b7b8e1 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac1.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac10.png b/modifiedeight-newadditions/assets/images/achievements/ac10.png new file mode 100644 index 00000000..eeb36ce0 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac10.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac11.png b/modifiedeight-newadditions/assets/images/achievements/ac11.png new file mode 100644 index 00000000..edc3278e Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac11.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac12.png b/modifiedeight-newadditions/assets/images/achievements/ac12.png new file mode 100644 index 00000000..81c2137a Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac12.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac13.png b/modifiedeight-newadditions/assets/images/achievements/ac13.png new file mode 100644 index 00000000..57a454c0 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac13.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac14.png b/modifiedeight-newadditions/assets/images/achievements/ac14.png new file mode 100644 index 00000000..4a3d957f Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac14.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac15.png b/modifiedeight-newadditions/assets/images/achievements/ac15.png new file mode 100644 index 00000000..93114904 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac15.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac2.png b/modifiedeight-newadditions/assets/images/achievements/ac2.png new file mode 100644 index 00000000..da66d672 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac2.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac3.png b/modifiedeight-newadditions/assets/images/achievements/ac3.png new file mode 100644 index 00000000..fa0eff9c Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac3.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac4.png b/modifiedeight-newadditions/assets/images/achievements/ac4.png new file mode 100644 index 00000000..43183d14 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac4.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac5.png b/modifiedeight-newadditions/assets/images/achievements/ac5.png new file mode 100644 index 00000000..bab9d289 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac5.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac6.png b/modifiedeight-newadditions/assets/images/achievements/ac6.png new file mode 100644 index 00000000..58e22e98 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac6.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac7.png b/modifiedeight-newadditions/assets/images/achievements/ac7.png new file mode 100644 index 00000000..01b886ed Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac7.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac8.png b/modifiedeight-newadditions/assets/images/achievements/ac8.png new file mode 100644 index 00000000..d75d2b8c Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac8.png differ diff --git a/modifiedeight-newadditions/assets/images/achievements/ac9.png b/modifiedeight-newadditions/assets/images/achievements/ac9.png new file mode 100644 index 00000000..02d772f7 Binary files /dev/null and b/modifiedeight-newadditions/assets/images/achievements/ac9.png differ diff --git a/modifiedeight-newadditions/headers/Achievements.hpp b/modifiedeight-newadditions/headers/Achievements.hpp new file mode 100644 index 00000000..ea5c5c06 --- /dev/null +++ b/modifiedeight-newadditions/headers/Achievements.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct Entity; +struct Minecraft; + +namespace Achievements { +void load(const std::string& path); +void save(); +void tick(); +void reset(); +bool executeCommand(Minecraft* minecraft, const std::string& line); +void onAttack(Minecraft* minecraft, Entity* victim); +void onDestroyBlock(Minecraft* minecraft, int blockId, int carriedItemId, bool destroyed); +void onUseItem(Minecraft* minecraft, int itemId); +void onUseBlock(Minecraft* minecraft, int blockId); +void render(Minecraft* minecraft); +} diff --git a/modifiedeight-newadditions/impl/Achievements.cpp b/modifiedeight-newadditions/impl/Achievements.cpp new file mode 100644 index 00000000..0be9ff42 --- /dev/null +++ b/modifiedeight-newadditions/impl/Achievements.cpp @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +const int achievementCount = 15; + +struct Popup { + int id; + int ticks; +}; + +int progress[achievementCount]; +std::string progressPath; +Popup popup = {0, 0}; + +void saveToDisk() { + if (progressPath.empty()) return; + std::ofstream out(progressPath.c_str(), std::ios::trunc); + if (!out) return; + for (int value : progress) out << value << '\n'; +} + +void loadFromDisk() { + std::fill(progress, progress + achievementCount, 1); + if (progressPath.empty()) return; + std::ifstream in(progressPath.c_str()); + for (int i = 0; i < achievementCount && in; ++i) { + int value = 1; + in >> value; + progress[i] = value == 2 ? 2 : 1; + } +} + +void announce(Minecraft* minecraft, int id) { + if (!minecraft) return; + popup.id = id; + popup.ticks = 240; + saveToDisk(); +} + +bool isMonsterType(int type) { + return type == 32 || type == 33 || type == 34 || type == 35 || type == 36; +} + +bool matchesUpgrade(int itemId) { + return itemId == 17 || itemId == 1 || itemId == 19 || itemId == 22; +} + +struct Achievement { + int id; + const char* name; +}; + +const Achievement achievements[] = { + {1, "Monster Hunter"}, + {2, "Cow Tipper"}, + {3, "Sniper Duel"}, + {4, "Getting Wood"}, + {5, "DIAMONDS!"}, + {6, "Benchmarking"}, + {7, "Hot Topic"}, + {8, "Time to Mine!"}, + {9, "Acquire Hardware"}, + {10, "Time to Farm!"}, + {11, "Bake Bread"}, + {12, "The Lie"}, + {13, "Getting an Upgrade"}, + {14, "Time to Strike!"}, + {15, "Librarian"}, +}; + +} + +namespace Achievements { +void load(const std::string& path) { + if (!path.empty()) progressPath = path; + loadFromDisk(); +} + +void save() { + saveToDisk(); +} + +void tick() { + if (popup.ticks > 0) --popup.ticks; +} + +void reset() { + std::fill(progress, progress + achievementCount, 1); + popup.id = 0; + popup.ticks = 0; + saveToDisk(); +} + +bool executeCommand(Minecraft* minecraft, const std::string& line) { + if (line.empty() || line[0] != '/') return false; + std::istringstream input(line.substr(1)); + std::string command; + input >> command; + if (command == "save") { + save(); + minecraft->gui.displayClientMessage("Saved Progress!"); + return true; + } + if (command == "load") { + load(progressPath); + minecraft->gui.displayClientMessage("Loaded Progress!"); + return true; + } + if (command == "reset") { + reset(); + minecraft->gui.displayClientMessage("Resetted Progress!"); + return true; + } + return false; +} + +void onAttack(Minecraft* minecraft, Entity* victim) { + if (!minecraft || !minecraft->player || !victim) return; + const int type = victim->getEntityTypeId(); + if (progress[0] == 1 && isMonsterType(type)) { + progress[0] = 2; + announce(minecraft, 1); + } + if (progress[1] == 1 && type == 11) { + progress[1] = 2; + announce(minecraft, 2); + } + ItemInstance* carried = minecraft->player->getCarriedItem(); + if (progress[2] == 1 && type == 34 && carried && carried->getId() == 261) { + progress[2] = 2; + announce(minecraft, 3); + } +} + +void onDestroyBlock(Minecraft* minecraft, int blockId, int carriedItemId, bool destroyed) { + if (!minecraft || !minecraft->player || !destroyed) return; + if (progress[3] == 1 && blockId == 17) { + progress[3] = 2; + announce(minecraft, 4); + } + if (progress[4] == 1 && blockId == 56 && carriedItemId == 257) { + progress[4] = 2; + announce(minecraft, 5); + } +} + +void onUseBlock(Minecraft* minecraft, int blockId) { + if (!minecraft || !minecraft->player) return; + if (blockId == 58 && progress[5] == 1) { + progress[5] = 2; + announce(minecraft, 6); + } + if (blockId == 61 && progress[6] == 1) { + progress[6] = 2; + announce(minecraft, 7); + } +} + +void onUseItem(Minecraft* minecraft, int itemId) { + if (!minecraft || !minecraft->player || itemId < 0) return; + for (int i = 7; i < achievementCount; ++i) { + if (progress[i] != 1) continue; + bool match = false; + if (i == 7) match = itemId == 14; + if (i == 8) match = itemId == 9; + if (i == 9) match = itemId == 36; + if (i == 10) match = itemId == 41; + if (i == 11) match = itemId == 98; + if (i == 12) match = matchesUpgrade(itemId); + if (i == 13) match = itemId == 12; + if (i == 14) match = itemId == 47; + if (match) { + progress[i] = 2; + announce(minecraft, i + 1); + } + } +} + +void render(Minecraft* minecraft) { + if (!minecraft || !minecraft->texturesPtr || popup.ticks <= 0 || popup.id < 1 || popup.id > achievementCount) return; + const float width = 243.0f; + const float height = 48.0f; + const float guiWidth = (float)minecraft->field_1C * Gui::InvGuiScale; + const float x = (guiWidth - width) * 0.5f; + const float alpha = popup.ticks < 40 ? popup.ticks / 40.0f : 1.0f; + std::ostringstream textureStream; + textureStream << "images/achievements/ac" << popup.id << ".png"; + const std::string texture = textureStream.str(); + const uint32_t textureId = minecraft->texturesPtr->loadAndBindTexture(texture); + if (!textureId) return; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColor4f(1.0f, 1.0f, 1.0f, alpha); + Tesselator::instance.begin(7); + Tesselator::instance.vertexUV(x, height, -90, 0, 1); + Tesselator::instance.vertexUV(x + width, height, -90, 1, 1); + Tesselator::instance.vertexUV(x + width, 0, -90, 1, 0); + Tesselator::instance.vertexUV(x, 0, -90, 0, 0); + Tesselator::instance.draw(1); + glDepthMask(1); + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} +} diff --git a/modifiedeight-newadditions/impl/Minecraft.cpp b/modifiedeight-newadditions/impl/Minecraft.cpp index 0b74fe72..2478f346 100644 --- a/modifiedeight-newadditions/impl/Minecraft.cpp +++ b/modifiedeight-newadditions/impl/Minecraft.cpp @@ -62,6 +62,7 @@ #include #include #include +#include char_t* Minecraft::progressMessages[] = {"Locating server", "Building terrain", "Preparing", "Saving chunks", "Waiting for Minecraft Realms"}; @@ -315,6 +316,7 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { InteractPacket v23(entityId, v7, 2); this->rakNetInstance->send(v23); this->gameMode->attack(this->player, this->selectedObject.entity); + Achievements::onAttack(this, this->selectedObject.entity); goto LABEL_27; } if((a2->field_0 & 0x10) == 0 || this->field_D0C) { @@ -341,7 +343,9 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { if(!this->player->isUsingItem()) { gameMode = this->gameMode; this->field_D0C = 8; - if(gameMode->useItem((Player*)this->player, this->level, sel)) { + bool_t used = gameMode->useItem((Player*)this->player, this->level, sel); + if(used) { + Achievements::onUseItem(this, sel->getId()); this->gameRenderer->itemInHandRenderer->itemUsed(); } if(sel->count <= 0) { @@ -359,7 +363,10 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { v13 = Tile::tiles[this->level->getTile(v9, v10, v11)]; if(!a2->isRemove()) { v14 = this->player->inventory->getSelected(); - if(this->gameMode->useItemOn((Player*)this->player, this->level, v14, v9, v10, v11, v12, this->selectedObject.hitVec)) { + bool_t usedOn = this->gameMode->useItemOn((Player*)this->player, this->level, v14, v9, v10, v11, v12, this->selectedObject.hitVec); + if(usedOn) { + Achievements::onUseItem(this, v14 ? v14->getId() : -1); + Achievements::onUseBlock(this, this->level->getTile(v9, v10, v11)); v15 = 0; this->player->swing(); } else { @@ -467,6 +474,7 @@ void Minecraft::init(void) { } ); } + Achievements::load(this->field_D00 + "/achievements.dat"); } bool_t Minecraft::isCreativeMode(void) { return this->isCreative; @@ -915,6 +923,7 @@ bool_t Minecraft::supportNonTouchscreen(void) { return this->supportsNonTouchScreen; } void Minecraft::teardown(void) { + Achievements::save(); if(this->serverSideNetworkHandler) { delete this->serverSideNetworkHandler; } @@ -1026,6 +1035,7 @@ void Minecraft::tick(int32_t a2, int32_t a3) { this->tickInput(); this->gui.tick(); + Achievements::tick(); if(!this->field_CF4) { if(!this->levelGenerated) { diff --git a/modifiedeight-newadditions/impl/entity/player/gamemode/GameMode.cpp b/modifiedeight-newadditions/impl/entity/player/gamemode/GameMode.cpp index 021d84f7..a61217bd 100644 --- a/modifiedeight-newadditions/impl/entity/player/gamemode/GameMode.cpp +++ b/modifiedeight-newadditions/impl/entity/player/gamemode/GameMode.cpp @@ -20,6 +20,7 @@ #include #include +#include GameMode::GameMode(Minecraft* a2) { this->minecraft = a2; @@ -121,6 +122,7 @@ bool_t GameMode::destroyBlock(int32_t x, int32_t y, int32_t z, int32_t side) { if(!v11) { return 0; } + Achievements::onDestroyBlock(this->minecraft, tile->blockID, this->minecraft->player && this->minecraft->player->getCarriedItem() ? this->minecraft->player->getCarriedItem()->getId() : -1, true); this->minecraft->soundEngine->play(tile->soundType->field_8, (float)x + 0.5, (float)y + 0.5, (float)z + 0.5, (float)(tile->soundType->field_0 + 1.0) * 0.5, tile->soundType->field_4 * 0.8); tile->destroy(level, x, y, z, meta); minecraft = this->minecraft; diff --git a/modifiedeight-newadditions/impl/gui/Gui.cpp b/modifiedeight-newadditions/impl/gui/Gui.cpp index 934b3c40..4f6ef99e 100644 --- a/modifiedeight-newadditions/impl/gui/Gui.cpp +++ b/modifiedeight-newadditions/impl/gui/Gui.cpp @@ -22,6 +22,7 @@ #include #include #include +#include float Gui::InvGuiScale = 0.333333; float Gui::GuiScale; @@ -440,6 +441,7 @@ void Gui::render(float a2, bool_t a3, int32_t a4, int32_t a5) { (float)(v21 * 0.5) - (float)(v20 * 0.5), v23, v24); } this->renderChatMessages(v15, v16, 0xAu, this->field_A94, font); + Achievements::render(this->minecraftInst); if (!this->minecraftInst->currentScreen) { this->renderOnSelectItemNameText(v15, font, v16 - 19); diff --git a/modifiedeight-newadditions/impl/gui/screens/ChatScreen.cpp b/modifiedeight-newadditions/impl/gui/screens/ChatScreen.cpp index 21bc1fbc..73f30e01 100644 --- a/modifiedeight-newadditions/impl/gui/screens/ChatScreen.cpp +++ b/modifiedeight-newadditions/impl/gui/screens/ChatScreen.cpp @@ -20,6 +20,7 @@ #include #include #include +#include ChatScreen::ChatScreen() : Screen() { @@ -429,13 +430,8 @@ static bool executeCommand(Minecraft* mc, const std::string& line) { void ChatScreen::sendChatMessage() { if(this->field_54.size()) { - /* - * A Java Edition session takes the line verbatim, slash commands - * included: on a Java server those belong to the server, not to the - * local handler below. sendChat returns 0 when no session is up, so - * MCPE servers and single player keep the original behaviour. - */ - if(JavaBridge::sendChat(this->field_54)) { + if (this->field_54[0] == '/' && Achievements::executeCommand(this->minecraft, this->field_54)) { + } else if(JavaBridge::sendChat(this->field_54)) { } else if (this->minecraft->isOnlineClient()) { MessagePacket v7(this->field_54, this->minecraft->player->username); this->minecraft->rakNetInstance->send(v7); diff --git a/modifiedeight-newadditions/impl/rendering/GameRenderer.cpp b/modifiedeight-newadditions/impl/rendering/GameRenderer.cpp index d097a1c3..899a47ab 100644 --- a/modifiedeight-newadditions/impl/rendering/GameRenderer.cpp +++ b/modifiedeight-newadditions/impl/rendering/GameRenderer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -572,6 +573,7 @@ void GameRenderer::render(float pt) { v27 = 1; this->setupGuiScreen(0); this->minecraft->gui.render(pt, this->minecraft->currentScreen != 0, mx, my); + Achievements::render(this->minecraft); goto LABEL_30; } v27 = 0; diff --git a/modifiedeight/assets/images/achievements/ac1.png b/modifiedeight/assets/images/achievements/ac1.png new file mode 100644 index 00000000..b3b7b8e1 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac1.png differ diff --git a/modifiedeight/assets/images/achievements/ac10.png b/modifiedeight/assets/images/achievements/ac10.png new file mode 100644 index 00000000..eeb36ce0 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac10.png differ diff --git a/modifiedeight/assets/images/achievements/ac11.png b/modifiedeight/assets/images/achievements/ac11.png new file mode 100644 index 00000000..edc3278e Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac11.png differ diff --git a/modifiedeight/assets/images/achievements/ac12.png b/modifiedeight/assets/images/achievements/ac12.png new file mode 100644 index 00000000..81c2137a Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac12.png differ diff --git a/modifiedeight/assets/images/achievements/ac13.png b/modifiedeight/assets/images/achievements/ac13.png new file mode 100644 index 00000000..57a454c0 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac13.png differ diff --git a/modifiedeight/assets/images/achievements/ac14.png b/modifiedeight/assets/images/achievements/ac14.png new file mode 100644 index 00000000..4a3d957f Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac14.png differ diff --git a/modifiedeight/assets/images/achievements/ac15.png b/modifiedeight/assets/images/achievements/ac15.png new file mode 100644 index 00000000..93114904 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac15.png differ diff --git a/modifiedeight/assets/images/achievements/ac2.png b/modifiedeight/assets/images/achievements/ac2.png new file mode 100644 index 00000000..da66d672 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac2.png differ diff --git a/modifiedeight/assets/images/achievements/ac3.png b/modifiedeight/assets/images/achievements/ac3.png new file mode 100644 index 00000000..fa0eff9c Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac3.png differ diff --git a/modifiedeight/assets/images/achievements/ac4.png b/modifiedeight/assets/images/achievements/ac4.png new file mode 100644 index 00000000..43183d14 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac4.png differ diff --git a/modifiedeight/assets/images/achievements/ac5.png b/modifiedeight/assets/images/achievements/ac5.png new file mode 100644 index 00000000..bab9d289 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac5.png differ diff --git a/modifiedeight/assets/images/achievements/ac6.png b/modifiedeight/assets/images/achievements/ac6.png new file mode 100644 index 00000000..58e22e98 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac6.png differ diff --git a/modifiedeight/assets/images/achievements/ac7.png b/modifiedeight/assets/images/achievements/ac7.png new file mode 100644 index 00000000..01b886ed Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac7.png differ diff --git a/modifiedeight/assets/images/achievements/ac8.png b/modifiedeight/assets/images/achievements/ac8.png new file mode 100644 index 00000000..d75d2b8c Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac8.png differ diff --git a/modifiedeight/assets/images/achievements/ac9.png b/modifiedeight/assets/images/achievements/ac9.png new file mode 100644 index 00000000..02d772f7 Binary files /dev/null and b/modifiedeight/assets/images/achievements/ac9.png differ diff --git a/modifiedeight/headers/Achievements.hpp b/modifiedeight/headers/Achievements.hpp new file mode 100644 index 00000000..ea5c5c06 --- /dev/null +++ b/modifiedeight/headers/Achievements.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct Entity; +struct Minecraft; + +namespace Achievements { +void load(const std::string& path); +void save(); +void tick(); +void reset(); +bool executeCommand(Minecraft* minecraft, const std::string& line); +void onAttack(Minecraft* minecraft, Entity* victim); +void onDestroyBlock(Minecraft* minecraft, int blockId, int carriedItemId, bool destroyed); +void onUseItem(Minecraft* minecraft, int itemId); +void onUseBlock(Minecraft* minecraft, int blockId); +void render(Minecraft* minecraft); +} diff --git a/modifiedeight/impl/Achievements.cpp b/modifiedeight/impl/Achievements.cpp new file mode 100644 index 00000000..0be9ff42 --- /dev/null +++ b/modifiedeight/impl/Achievements.cpp @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +const int achievementCount = 15; + +struct Popup { + int id; + int ticks; +}; + +int progress[achievementCount]; +std::string progressPath; +Popup popup = {0, 0}; + +void saveToDisk() { + if (progressPath.empty()) return; + std::ofstream out(progressPath.c_str(), std::ios::trunc); + if (!out) return; + for (int value : progress) out << value << '\n'; +} + +void loadFromDisk() { + std::fill(progress, progress + achievementCount, 1); + if (progressPath.empty()) return; + std::ifstream in(progressPath.c_str()); + for (int i = 0; i < achievementCount && in; ++i) { + int value = 1; + in >> value; + progress[i] = value == 2 ? 2 : 1; + } +} + +void announce(Minecraft* minecraft, int id) { + if (!minecraft) return; + popup.id = id; + popup.ticks = 240; + saveToDisk(); +} + +bool isMonsterType(int type) { + return type == 32 || type == 33 || type == 34 || type == 35 || type == 36; +} + +bool matchesUpgrade(int itemId) { + return itemId == 17 || itemId == 1 || itemId == 19 || itemId == 22; +} + +struct Achievement { + int id; + const char* name; +}; + +const Achievement achievements[] = { + {1, "Monster Hunter"}, + {2, "Cow Tipper"}, + {3, "Sniper Duel"}, + {4, "Getting Wood"}, + {5, "DIAMONDS!"}, + {6, "Benchmarking"}, + {7, "Hot Topic"}, + {8, "Time to Mine!"}, + {9, "Acquire Hardware"}, + {10, "Time to Farm!"}, + {11, "Bake Bread"}, + {12, "The Lie"}, + {13, "Getting an Upgrade"}, + {14, "Time to Strike!"}, + {15, "Librarian"}, +}; + +} + +namespace Achievements { +void load(const std::string& path) { + if (!path.empty()) progressPath = path; + loadFromDisk(); +} + +void save() { + saveToDisk(); +} + +void tick() { + if (popup.ticks > 0) --popup.ticks; +} + +void reset() { + std::fill(progress, progress + achievementCount, 1); + popup.id = 0; + popup.ticks = 0; + saveToDisk(); +} + +bool executeCommand(Minecraft* minecraft, const std::string& line) { + if (line.empty() || line[0] != '/') return false; + std::istringstream input(line.substr(1)); + std::string command; + input >> command; + if (command == "save") { + save(); + minecraft->gui.displayClientMessage("Saved Progress!"); + return true; + } + if (command == "load") { + load(progressPath); + minecraft->gui.displayClientMessage("Loaded Progress!"); + return true; + } + if (command == "reset") { + reset(); + minecraft->gui.displayClientMessage("Resetted Progress!"); + return true; + } + return false; +} + +void onAttack(Minecraft* minecraft, Entity* victim) { + if (!minecraft || !minecraft->player || !victim) return; + const int type = victim->getEntityTypeId(); + if (progress[0] == 1 && isMonsterType(type)) { + progress[0] = 2; + announce(minecraft, 1); + } + if (progress[1] == 1 && type == 11) { + progress[1] = 2; + announce(minecraft, 2); + } + ItemInstance* carried = minecraft->player->getCarriedItem(); + if (progress[2] == 1 && type == 34 && carried && carried->getId() == 261) { + progress[2] = 2; + announce(minecraft, 3); + } +} + +void onDestroyBlock(Minecraft* minecraft, int blockId, int carriedItemId, bool destroyed) { + if (!minecraft || !minecraft->player || !destroyed) return; + if (progress[3] == 1 && blockId == 17) { + progress[3] = 2; + announce(minecraft, 4); + } + if (progress[4] == 1 && blockId == 56 && carriedItemId == 257) { + progress[4] = 2; + announce(minecraft, 5); + } +} + +void onUseBlock(Minecraft* minecraft, int blockId) { + if (!minecraft || !minecraft->player) return; + if (blockId == 58 && progress[5] == 1) { + progress[5] = 2; + announce(minecraft, 6); + } + if (blockId == 61 && progress[6] == 1) { + progress[6] = 2; + announce(minecraft, 7); + } +} + +void onUseItem(Minecraft* minecraft, int itemId) { + if (!minecraft || !minecraft->player || itemId < 0) return; + for (int i = 7; i < achievementCount; ++i) { + if (progress[i] != 1) continue; + bool match = false; + if (i == 7) match = itemId == 14; + if (i == 8) match = itemId == 9; + if (i == 9) match = itemId == 36; + if (i == 10) match = itemId == 41; + if (i == 11) match = itemId == 98; + if (i == 12) match = matchesUpgrade(itemId); + if (i == 13) match = itemId == 12; + if (i == 14) match = itemId == 47; + if (match) { + progress[i] = 2; + announce(minecraft, i + 1); + } + } +} + +void render(Minecraft* minecraft) { + if (!minecraft || !minecraft->texturesPtr || popup.ticks <= 0 || popup.id < 1 || popup.id > achievementCount) return; + const float width = 243.0f; + const float height = 48.0f; + const float guiWidth = (float)minecraft->field_1C * Gui::InvGuiScale; + const float x = (guiWidth - width) * 0.5f; + const float alpha = popup.ticks < 40 ? popup.ticks / 40.0f : 1.0f; + std::ostringstream textureStream; + textureStream << "images/achievements/ac" << popup.id << ".png"; + const std::string texture = textureStream.str(); + const uint32_t textureId = minecraft->texturesPtr->loadAndBindTexture(texture); + if (!textureId) return; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColor4f(1.0f, 1.0f, 1.0f, alpha); + Tesselator::instance.begin(7); + Tesselator::instance.vertexUV(x, height, -90, 0, 1); + Tesselator::instance.vertexUV(x + width, height, -90, 1, 1); + Tesselator::instance.vertexUV(x + width, 0, -90, 1, 0); + Tesselator::instance.vertexUV(x, 0, -90, 0, 0); + Tesselator::instance.draw(1); + glDepthMask(1); + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} +} diff --git a/modifiedeight/impl/Minecraft.cpp b/modifiedeight/impl/Minecraft.cpp index e4d9d443..18fd1929 100644 --- a/modifiedeight/impl/Minecraft.cpp +++ b/modifiedeight/impl/Minecraft.cpp @@ -59,6 +59,7 @@ #include #include #include +#include char_t* Minecraft::progressMessages[] = {"Locating server", "Building terrain", "Preparing", "Saving chunks", "Waiting for Minecraft Realms"}; @@ -312,6 +313,7 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { InteractPacket v23(entityId, v7, 2); this->rakNetInstance->send(v23); this->gameMode->attack(this->player, this->selectedObject.entity); + Achievements::onAttack(this, this->selectedObject.entity); goto LABEL_27; } if((a2->field_0 & 0x10) == 0 || this->field_D0C) { @@ -338,7 +340,9 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { if(!this->player->isUsingItem()) { gameMode = this->gameMode; this->field_D0C = 8; - if(gameMode->useItem((Player*)this->player, this->level, sel)) { + bool_t used = gameMode->useItem((Player*)this->player, this->level, sel); + if(used) { + Achievements::onUseItem(this, sel->getId()); this->gameRenderer->itemInHandRenderer->itemUsed(); } if(sel->count <= 0) { @@ -356,7 +360,10 @@ void Minecraft::handleBuildAction(struct BuildActionIntention* a2) { v13 = Tile::tiles[this->level->getTile(v9, v10, v11)]; if(!a2->isRemove()) { v14 = this->player->inventory->getSelected(); - if(this->gameMode->useItemOn((Player*)this->player, this->level, v14, v9, v10, v11, v12, this->selectedObject.hitVec)) { + bool_t usedOn = this->gameMode->useItemOn((Player*)this->player, this->level, v14, v9, v10, v11, v12, this->selectedObject.hitVec); + if(usedOn) { + Achievements::onUseItem(this, v14 ? v14->getId() : -1); + Achievements::onUseBlock(this, this->level->getTile(v9, v10, v11)); v15 = 0; this->player->swing(); } else { @@ -464,6 +471,8 @@ void Minecraft::init(void) { } ); } + this->field_D00 = this->dataPathMaybe + "/games" + "/com.mojang" + "/minecraftpe"; + Achievements::load(this->field_D00 + "/achievements.dat"); } bool_t Minecraft::isCreativeMode(void) { return this->isCreative; @@ -918,6 +927,7 @@ bool_t Minecraft::supportNonTouchscreen(void) { return this->supportsNonTouchScreen; } void Minecraft::teardown(void) { + Achievements::save(); if(this->serverSideNetworkHandler) { delete this->serverSideNetworkHandler; } @@ -1029,6 +1039,7 @@ void Minecraft::tick(int32_t a2, int32_t a3) { this->tickInput(); this->gui.tick(); + Achievements::tick(); if(!this->field_CF4) { if(!this->levelGenerated) { diff --git a/modifiedeight/impl/entity/player/gamemode/GameMode.cpp b/modifiedeight/impl/entity/player/gamemode/GameMode.cpp index 86f8b77e..9885a477 100644 --- a/modifiedeight/impl/entity/player/gamemode/GameMode.cpp +++ b/modifiedeight/impl/entity/player/gamemode/GameMode.cpp @@ -14,6 +14,7 @@ #include #include #include +#include GameMode::GameMode(Minecraft* a2) { this->minecraft = a2; @@ -54,6 +55,7 @@ bool_t GameMode::destroyBlock(int32_t x, int32_t y, int32_t z, int32_t side) { if(!v11) { return 0; } + Achievements::onDestroyBlock(this->minecraft, tile->blockID, this->minecraft->player && this->minecraft->player->getCarriedItem() ? this->minecraft->player->getCarriedItem()->getId() : -1, true); this->minecraft->soundEngine->play(tile->soundType->field_8, (float)x + 0.5, (float)y + 0.5, (float)z + 0.5, (float)(tile->soundType->field_0 + 1.0) * 0.5, tile->soundType->field_4 * 0.8); tile->destroy(level, x, y, z, meta); minecraft = this->minecraft; diff --git a/modifiedeight/impl/gui/Gui.cpp b/modifiedeight/impl/gui/Gui.cpp index 74d32ff3..9a3f391e 100644 --- a/modifiedeight/impl/gui/Gui.cpp +++ b/modifiedeight/impl/gui/Gui.cpp @@ -22,6 +22,7 @@ #include #include #include +#include float Gui::InvGuiScale = 0.333333; float Gui::GuiScale; @@ -451,6 +452,7 @@ void Gui::render(float a2, bool_t a3, int32_t a4, int32_t a5) { (float)(v21 * 0.5) - (float)(v20 * 0.5), v23, v24); } this->renderChatMessages(v15, v16, 0xAu, this->field_A94, font); + Achievements::render(this->minecraftInst); if (!this->minecraftInst->currentScreen) { this->renderOnSelectItemNameText(v15, font, v16 - 19); diff --git a/modifiedeight/impl/gui/screens/ChatScreen.cpp b/modifiedeight/impl/gui/screens/ChatScreen.cpp index 0bc43a66..99f6fd40 100644 --- a/modifiedeight/impl/gui/screens/ChatScreen.cpp +++ b/modifiedeight/impl/gui/screens/ChatScreen.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -53,10 +54,13 @@ bool_t ChatScreen::guiMessagesUpdated() { } void ChatScreen::sendChatMessage() { if(this->field_54.size()) { - MessagePacket v7(this->field_54, this->minecraft->player->username); - this->minecraft->rakNetInstance->send(v7); - if(!this->minecraft->isOnlineClient()) { - this->minecraft->gui.addMessage(this->minecraft->player->username, this->field_54, 200); + if (this->field_54[0] == '/' && Achievements::executeCommand(this->minecraft, this->field_54)) { + } else { + MessagePacket v7(this->field_54, this->minecraft->player->username); + this->minecraft->rakNetInstance->send(v7); + if(!this->minecraft->isOnlineClient()) { + this->minecraft->gui.addMessage(this->minecraft->player->username, this->field_54, 200); + } } this->field_78.emplace_back(this->field_54); this->field_84 = this->field_78.size(); diff --git a/modifiedeight/impl/rendering/GameRenderer.cpp b/modifiedeight/impl/rendering/GameRenderer.cpp index 7347ed2f..359a8909 100644 --- a/modifiedeight/impl/rendering/GameRenderer.cpp +++ b/modifiedeight/impl/rendering/GameRenderer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -545,6 +546,7 @@ void GameRenderer::render(float pt) { v27 = 1; this->setupGuiScreen(0); this->minecraft->gui.render(pt, this->minecraft->currentScreen != 0, mx, my); + Achievements::render(this->minecraft); goto LABEL_30; } v27 = 0; diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac1.png b/platforms/android/app/src/classic/assets/images/achievements/ac1.png new file mode 100644 index 00000000..b3b7b8e1 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac1.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac10.png b/platforms/android/app/src/classic/assets/images/achievements/ac10.png new file mode 100644 index 00000000..eeb36ce0 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac10.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac11.png b/platforms/android/app/src/classic/assets/images/achievements/ac11.png new file mode 100644 index 00000000..edc3278e Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac11.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac12.png b/platforms/android/app/src/classic/assets/images/achievements/ac12.png new file mode 100644 index 00000000..81c2137a Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac12.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac13.png b/platforms/android/app/src/classic/assets/images/achievements/ac13.png new file mode 100644 index 00000000..57a454c0 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac13.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac14.png b/platforms/android/app/src/classic/assets/images/achievements/ac14.png new file mode 100644 index 00000000..4a3d957f Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac14.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac15.png b/platforms/android/app/src/classic/assets/images/achievements/ac15.png new file mode 100644 index 00000000..93114904 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac15.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac2.png b/platforms/android/app/src/classic/assets/images/achievements/ac2.png new file mode 100644 index 00000000..da66d672 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac2.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac3.png b/platforms/android/app/src/classic/assets/images/achievements/ac3.png new file mode 100644 index 00000000..fa0eff9c Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac3.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac4.png b/platforms/android/app/src/classic/assets/images/achievements/ac4.png new file mode 100644 index 00000000..43183d14 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac4.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac5.png b/platforms/android/app/src/classic/assets/images/achievements/ac5.png new file mode 100644 index 00000000..bab9d289 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac5.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac6.png b/platforms/android/app/src/classic/assets/images/achievements/ac6.png new file mode 100644 index 00000000..58e22e98 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac6.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac7.png b/platforms/android/app/src/classic/assets/images/achievements/ac7.png new file mode 100644 index 00000000..01b886ed Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac7.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac8.png b/platforms/android/app/src/classic/assets/images/achievements/ac8.png new file mode 100644 index 00000000..d75d2b8c Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac8.png differ diff --git a/platforms/android/app/src/classic/assets/images/achievements/ac9.png b/platforms/android/app/src/classic/assets/images/achievements/ac9.png new file mode 100644 index 00000000..02d772f7 Binary files /dev/null and b/platforms/android/app/src/classic/assets/images/achievements/ac9.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac1.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac1.png new file mode 100644 index 00000000..b3b7b8e1 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac1.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac10.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac10.png new file mode 100644 index 00000000..eeb36ce0 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac10.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac11.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac11.png new file mode 100644 index 00000000..edc3278e Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac11.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac12.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac12.png new file mode 100644 index 00000000..81c2137a Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac12.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac13.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac13.png new file mode 100644 index 00000000..57a454c0 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac13.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac14.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac14.png new file mode 100644 index 00000000..4a3d957f Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac14.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac15.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac15.png new file mode 100644 index 00000000..93114904 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac15.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac2.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac2.png new file mode 100644 index 00000000..da66d672 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac2.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac3.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac3.png new file mode 100644 index 00000000..fa0eff9c Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac3.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac4.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac4.png new file mode 100644 index 00000000..43183d14 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac4.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac5.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac5.png new file mode 100644 index 00000000..bab9d289 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac5.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac6.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac6.png new file mode 100644 index 00000000..58e22e98 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac6.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac7.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac7.png new file mode 100644 index 00000000..01b886ed Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac7.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac8.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac8.png new file mode 100644 index 00000000..d75d2b8c Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac8.png differ diff --git a/platforms/android/app/src/newadditions/assets/images/achievements/ac9.png b/platforms/android/app/src/newadditions/assets/images/achievements/ac9.png new file mode 100644 index 00000000..02d772f7 Binary files /dev/null and b/platforms/android/app/src/newadditions/assets/images/achievements/ac9.png differ