Skip to content

Commit

Permalink
feat: first complete custom dimension
Browse files Browse the repository at this point in the history
  • Loading branch information
quizhizhe committed Dec 7, 2023
1 parent fe9c0ff commit 2b8e71e
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 48 deletions.
3 changes: 3 additions & 0 deletions src/ll/api/dimension/FakeDimensionID.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


#include "FakeDimensionID.h"
6 changes: 6 additions & 0 deletions src/ll/api/dimension/FakeDimensionID.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once


class FakeDimensionID {};


40 changes: 40 additions & 0 deletions src/ll/api/dimension/MoreDimensionConfig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

#include "MoreDimensionConfig.h"

#include "ll/api/Config.h"
#include "ll/api/service/GlobalService.h"
#include "mc/world/level/Level.h"
#include "mc/world/level/LevelSeed64.h"
#include "mc/world/level/storage/LevelData.h"

namespace MoreDimensionConfig {

std::string dimensionConfigPath = R"(worlds\Bedrock level\dimension_config.json)";
Config dimConfig{};

void setDimensionConfigPath() {
auto levelName = ll::Global<Level>->getLevelData().getLevelName();
dimensionConfigPath.replace(dimensionConfigPath.find("Bedrock level"), 13, levelName);
}

bool loadConfigFile() {
setDimensionConfigPath(); // set real world path
if (!ll::config::loadConfig(dimConfig, dimensionConfigPath, false)) {
if (ll::config::saveConfig(dimConfig, dimensionConfigPath)) {
logger.warn("Config file rewrite success!");
} else {
logger.warn("Config file rewrite fail!");
return false;
}
}
return true;
}

bool saveConfigFile() {
if (!ll::config::saveConfig(dimConfig, dimensionConfigPath)) {
logger.error("Config file save fail!");
return false;
}
return true;
}
} // namespace MoreDimensionConfig
30 changes: 30 additions & 0 deletions src/ll/api/dimension/MoreDimensionConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <string>
#include <unordered_map>

#include "ll/api/Logger.h"
#include "ll/api/base/StdInt.h"
#include "mc/world/level/levelgen/GeneratorType.h"

namespace MoreDimensionConfig {
namespace {
ll::Logger logger("MoreDimensionConfig");
}

struct Config {
struct dimensionInfo {
int id = -1;
uint seed = 123;
GeneratorType generatorType = GeneratorType::Void;
};
int version = 1;
std::unordered_map<std::string, dimensionInfo> dimensionList = {};
};
extern std::string dimensionConfigPath;
extern Config dimConfig;

void setDimensionConfigPath();
bool loadConfigFile();
bool saveConfigFile();
}; // namespace MoreDimensionConfig
128 changes: 92 additions & 36 deletions src/ll/api/dimension/MoreDimensionManager.cpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,23 @@

#include "MoreDimensionManager.h"

#include "ll/api/dimension/FakeDimensionID.h"
#include "ll/api/dimension/MoreDimension.h"
#include "ll/api/dimension/MoreDimensionConfig.h"
#include "ll/api/memory/Hook.h"
#include "ll/api/service/GlobalService.h"
#include "mc/math/Vec3.h"
#include "mc/world/level/Level.h"
#include "mc/world/level/dimension/Dimension.h"
#include "mc/world/level/dimension/VanillaDimensionFactory.h"
#include "mc/world/level/dimension/VanillaDimensions.h"
#include "mc/world/level/storage/LevelData.h"

void MoreDimensionManager::init() {}

bool MoreDimensionManager::AddDimension(
std::string_view dimensionName,
uint seed,
AutomaticID<Dimension, int> dimensionId
) {
if (MoreDimensionMap.find(dimensionId.id) != MoreDimensionMap.end()) {
loggerMoreDimMag.error("The Dimension Id Already exists. Id: {}", dimensionId.id);
return false;
}
if (dimensionId == VanillaDimensions::Overworld || dimensionId == VanillaDimensions::Nether
|| dimensionId == VanillaDimensions::TheEnd) {
loggerMoreDimMag.error("Cannot use vanilla dimension id, Id: {}", dimensionId.id);
return false;
}
MoreDimensionMap.emplace(dimensionId.id, DimensionInfo(dimensionName, dimensionId, seed));
ll::memory::modify(VanillaDimensions::$DimensionMap(), [&](auto& dimMap) {
loggerMoreDimMag.debug("Add new dimension");
dimMap.mRight.insert(std::make_pair(dimensionName, dimensionId));
dimMap.mLeft.insert(std::make_pair(dimensionId, dimensionName));
});
ll::memory::modify(VanillaDimensions::Undefined, [&](auto& dimId) {
dimId.id += 1;
loggerMoreDimMag.debug("Set VanillaDimensions::Undefined to {}", dimId.id);
});
return true;
}

LL_AUTO_STATIC_HOOK(
namespace moredimension::hooklist {
LL_TYPED_STATIC_HOOK(
VanillaDimensionsConverHook,
HookPriority::Normal,
VanillaDimensions,
VanillaDimensions::convertPointBetweenDimensions,
bool,
Vec3 const& oldPos,
Expand All @@ -57,9 +34,10 @@ LL_AUTO_STATIC_HOOK(
using BedResult_Dim = Bedrock::Result<DimensionType>;
using BedResult_int = Bedrock::Result<int>&;

LL_AUTO_STATIC_HOOK(
LL_TYPED_STATIC_HOOK(
VanillaDimensionsFromSerializedIntHook,
HookPriority::Normal,
VanillaDimensions,
"?fromSerializedInt@VanillaDimensions@@SA?AV?$Result@V?$AutomaticID@VDimension@@H@@Verror_code@std@@@Bedrock@@$$"
"QEAV?$Result@HVerror_code@std@@@3@@Z",
BedResult_Dim,
Expand All @@ -69,9 +47,10 @@ LL_AUTO_STATIC_HOOK(
return Bedrock::Result<DimensionType>(dim.value());
};

LL_AUTO_STATIC_HOOK(
LL_TYPED_STATIC_HOOK(
VanillaDimensionsFromSerializedIntHookI,
HookPriority::Normal,
VanillaDimensions,
"?fromSerializedInt@VanillaDimensions@@SA?AV?$AutomaticID@VDimension@@H@@H@Z",
DimensionType,
int dimId
Expand All @@ -80,9 +59,10 @@ LL_AUTO_STATIC_HOOK(
return {dimId};
}

LL_AUTO_STATIC_HOOK(
LL_TYPED_STATIC_HOOK(
VanillaDimensionsToSerializedIntHook,
HookPriority::Normal,
VanillaDimensions,
VanillaDimensions::toSerializedInt,
int,
DimensionType const& dim
Expand All @@ -91,9 +71,10 @@ LL_AUTO_STATIC_HOOK(
return dim.id;
}

LL_AUTO_STATIC_HOOK(
LL_TYPED_STATIC_HOOK(
VanillaDimensionsToStringHook,
HookPriority::Normal,
VanillaDimensions,
VanillaDimensions::toString,
std::string const,
DimensionType const& dim
Expand All @@ -104,7 +85,7 @@ LL_AUTO_STATIC_HOOK(

// Registry New Dimension Hook
using fact = OwnerPtrFactory<Dimension, ILevel&, Scheduler&>;
LL_AUTO_STATIC_HOOK(
LL_STATIC_HOOK(
RegistryDimensionSercive,
HookPriority::Normal,
VanillaDimensionFactory::registerDimensionTypes,
Expand All @@ -126,8 +107,83 @@ LL_AUTO_STATIC_HOOK(
}

// registry dimensoin when in ll, must reload Dimension::getWeakRef
LL_AUTO_TYPED_INSTANCE_HOOK(DimensionGetWeakRefHook, HookPriority::Normal, Dimension, &Dimension::getWeakRef, WeakRefT<SharePtrRefTraits<Dimension>>) {
LL_TYPED_INSTANCE_HOOK(DimensionGetWeakRefHook, HookPriority::Normal, Dimension, &Dimension::getWeakRef, WeakRefT<SharePtrRefTraits<Dimension>>) {
if (this->getDimensionId() > 2 && this->getDimensionId() != VanillaDimensions::Undefined.id)
return weak_from_this();
return origin();
};

void hookAll() {
VanillaDimensionsConverHook::hook();
VanillaDimensionsFromSerializedIntHook::hook();
VanillaDimensionsFromSerializedIntHookI::hook();
VanillaDimensionsToSerializedIntHook::hook();
VanillaDimensionsToStringHook::hook();
RegistryDimensionSercive::hook();
DimensionGetWeakRefHook::hook();
}
void unhookAll() {
VanillaDimensionsConverHook::unhook();
VanillaDimensionsFromSerializedIntHook::unhook();
VanillaDimensionsFromSerializedIntHookI::unhook();
VanillaDimensionsToSerializedIntHook::unhook();
VanillaDimensionsToStringHook::unhook();
RegistryDimensionSercive::unhook();
DimensionGetWeakRefHook::unhook();
}
} // namespace moredimension::hooklist

MoreDimensionManager::MoreDimensionManager() {
MoreDimensionConfig::loadConfigFile();
if (!MoreDimensionConfig::dimConfig.dimensionList.empty()) {
for (auto& dim : MoreDimensionConfig::dimConfig.dimensionList) {
this->MoreDimensionMap.emplace(dim.second.id, DimensionInfo(dim.first, dim.second.id, dim.second.seed));
}
moredimension::hooklist::hookAll();
}
};

MoreDimensionManager& MoreDimensionManager::getInstance() {
static MoreDimensionManager instance{};
return instance;
}

bool MoreDimensionManager::AddDimension(DimensionInfo& dimInfo) {
if (MoreDimensionMap.find(dimInfo.id) != MoreDimensionMap.end()) {
loggerMoreDimMag.error("The Dimension Id Already exists. Id: {}", dimInfo.id.id);
return false;
}
if (dimInfo.id == VanillaDimensions::Overworld || dimInfo.id == VanillaDimensions::Nether
|| dimInfo.id == VanillaDimensions::TheEnd) {
loggerMoreDimMag.error("Cannot use vanilla dimension id, Id: {}", dimInfo.id.id);
return false;
}
MoreDimensionMap.emplace(dimInfo.id.id, dimInfo);
MoreDimensionConfig::dimConfig.dimensionList.emplace(
dimInfo.name,
MoreDimensionConfig::Config::dimensionInfo{dimInfo.id.id, dimInfo.seed, dimInfo.generatorType}
);

// registry create dimension function
ll::Global<Level>->getDimensionFactory().registerFactory(
dimInfo.name,
[&](ILevel& ilevel, Scheduler& scheduler) -> OwnerPtrT<SharePtrRefTraits<Dimension>> {
loggerMoreDimMag.debug("Create dimension, name: {}, id: {}", dimInfo.name, dimInfo.id.id);
return std::make_shared<MoreDimension>(ilevel, scheduler, dimInfo);
}
);

// modify default dimension map
ll::memory::modify(VanillaDimensions::$DimensionMap(), [&](auto& dimMap) {
loggerMoreDimMag.debug("Add new dimension to DimensionMap");
dimMap.mRight.insert(std::make_pair(dimInfo.name, dimInfo.id));
dimMap.mLeft.insert(std::make_pair(dimInfo.id, dimInfo.name));
});
// modify default Undefined dimension id
ll::memory::modify(VanillaDimensions::Undefined, [&](auto& dimId) {
dimId.id += 1;
loggerMoreDimMag.debug("Set VanillaDimensions::Undefined to {}", dimId.id);
});

return true;
}
16 changes: 6 additions & 10 deletions src/ll/api/dimension/MoreDimensionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,19 @@ ll::Logger loggerMoreDimMag("MoreDimensionManager");
}

class MoreDimensionManager {
const std::string dimensionConfigPath = R"(worlds\Bedrock level\dimension_config.json)";

void init();
void setDimensionConfigPath();
MoreDimensionManager();
~MoreDimensionManager() = default;

public:
MoreDimensionManager() { init(); };

static MoreDimensionManager getInstance() { return {}; }
static MoreDimensionManager& getInstance();

struct DimensionInfo {
DimensionInfo(std::string_view dimensionName, AutomaticID<Dimension, int> dimensionId, uint sd)
: name(dimensionName),
id(dimensionId),
seed(sd){};

std::string name;
const std::string name;
AutomaticID<Dimension, int> id;
uint seed = 123;
GeneratorType generatorType = GeneratorType::Overworld;
Expand All @@ -34,6 +30,6 @@ class MoreDimensionManager {

AutomaticID<Dimension, int> getNewDimensionId();

LLAPI bool AddDimension(std::string_view dimensionName, uint seed, AutomaticID<Dimension, int> dimensionId);
LLAPI AutomaticID<Dimension, int> AddDimension(std::string_view dimensionName, uint seed);
LLAPI bool AddDimension(DimensionInfo& dimInfo);
LLAPI AutomaticID<Dimension, int> AddDimension(std::string_view dimensionName, uint seed, GeneratorType generatorType);
};
3 changes: 1 addition & 2 deletions src/ll/api/service/GlobalService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,11 @@ LL_AUTO_TYPED_INSTANCE_HOOK(
::ServerInstance& ins
) {
ll::Global<Level>.init(ll::Global<Minecraft>->getLevel());
ll::Global<MoreDimensionManager>.init(new MoreDimensionManager());
ll::Global<MoreDimensionManager>.init(&MoreDimensionManager::getInstance());
origin(ins);
}
LL_AUTO_INSTANCE_HOOK(LevelDestructor, HookPriority::High, "??1Level@@UEAA@XZ", void) {
ll::Global<Level>.init(nullptr);
ll::Global<MoreDimensionManager>->~MoreDimensionManager();
ll::Global<MoreDimensionManager>.init(nullptr);
origin();
}
Expand Down

0 comments on commit 2b8e71e

Please sign in to comment.