refactor: reconstructing the mod

This commit is contained in:
zimuya4153
2025-06-26 19:18:09 +08:00
Unverified
parent 8b13033bea
commit ded7e6284f
7 changed files with 1396 additions and 15 deletions
+311 -8
View File
@@ -1,21 +1,50 @@
#include <gmlib/gm/ui/CustomForm.h>
#include <gmlib/mc/locale/I18nAPI.h>
#include <gmlib/mod/item/CustomItemRegistry.h>
#include <gmlib/mod/item/base/ICustomItem.h>
#include <ll/api/base/Containers.h>
#include <ll/api/thread/ServerThreadExecutor.h>
#include <ll/api/utils/StringUtils.h>
#include <magic_enum.hpp>
#include <mc/deps/core/math/Vec3.h>
#include <mc/deps/core/string/HashedString.h>
#include <mc/legacy/facing/Name.h>
#include <mc/legacy/facing/Rotation.h>
#include <mc/util/BidirectionalUnorderedMap.h>
#include <mc/world/actor/player/Player.h>
#include <mc/world/level/BlockSource.h>
#include <mc/world/level/block/Block.h>
#include <mc/world/gamemode/InteractionResult.h>
#include <mc/world/item/VanillaItemNames.h>
#include <mc/world/level/BlockPos.h>
#include <mc/world/level/BlockSource.h>
#include <mc/world/level/TrialSpawner.h>
#include <mc/world/level/block/Block.h>
#include <mc/world/level/block/CandleCount.h>
#include <mc/world/level/block/ComposterBlock.h>
#include <mc/world/level/block/CoralDirection.h>
#include <mc/world/level/block/RailDirection.h>
#include <mc/world/level/block/SculkSensorPhase.h>
#include <mc/world/level/block/WeirdoDirection.h>
#include <mc/world/level/block/states/vanilla_states/VanillaStates.h>
#include <mc/world/level/levelgen/structure/SensibleDirections.h>
#include <string>
namespace DebugStick {
class DebugStickItem : public gmlib::mod::ICustomItem {
public:
DebugStickItem() : ICustomItem(VanillaItemNames::DebugStick()){}
enum class BlockUpdateFlag : uchar {
None = 0,
Neighbors = 1 << 0,
Network = 1 << 1,
NoGraphic = 1 << 2,
Priority = 1 << 3,
ForceNoticeListener = 1 << 4,
All = Neighbors | Network, // default value
AllPriority = All | Priority,
};
public:
DebugStickItem() : ICustomItem(VanillaItemNames::DebugStick()) {}
uint8_t getItemMaxStackSize() const override { return 1; }
@@ -35,11 +64,285 @@ public:
it->second->cancel();
}
mTimer[&player] = ll::thread::ServerThreadExecutor::getDefault().executeAfter(
[&player, pos]() -> void { //
auto& region = player.getDimensionBlockSource();
auto& oldBlock = region.getBlock(pos);
auto* newBlock = oldBlock.getLegacyBlock().getNextBlockPermutation(oldBlock);
if (newBlock) region.setBlock(pos, *newBlock, 3, nullptr, &player);
[&player, pos]() -> void {
static ll::DenseMap<Player*, std::pair<BlockPos, Block const*>> mEditBlocks;
static auto mStatesHandler = []() {
ll::DenseMap<BlockState const*, std::function<void(gmlib::ui::CustomForm&, Block const&)>> states;
auto handlerFunc = [&]<typename T>(T const& state) {
using Type = std::remove_cvref_t<typename T::Type>;
if constexpr (std::is_same_v<Type, bool>) {
states[&state] = [&state](gmlib::ui::CustomForm& form, Block const& block) -> void {
auto oldValue = *block.getState<Type>(state);
form.appendToggle(
fmt::format("state.{0}.name", state.mName->getString()),
oldValue,
[oldValue, &state](Player& player, bool newValue) -> void {
if (oldValue == newValue) return;
if (auto block = mEditBlocks[&player].second->setState(state, newValue);
block) {
mEditBlocks[&player].second = block.as_ptr();
}
}
);
};
} else if constexpr (std::is_integral_v<Type>) {
states[&state] = [&state](gmlib::ui::CustomForm& form, Block const& block) -> void {
auto oldValue = std::to_string(*block.getState<Type>(state));
form.appendInput(
fmt::format("state.{0}.name", state.mName->getString()),
{},
oldValue,
[oldValue, &state](Player& player, std::string const& newValue) -> void {
if (oldValue == newValue) return;
if (auto result = ll::string_utils::svtonum<Type>(newValue, nullptr, 10);
result) {
if (auto block = mEditBlocks[&player].second->setState(state, *result);
block) {
mEditBlocks[&player].second = block.as_ptr();
}
}
}
);
};
} else if constexpr (std::is_enum_v<Type>) {
states[&state] = [&state](gmlib::ui::CustomForm& form, Block const& block) -> void {
// clang-format off
static auto enumMap = magic_enum::enum_values<Type>() | std::ranges::to<std::vector>();
static auto names =
enumMap
| std::views::transform([](auto sv) {
return fmt::format(
"%enum.{0}.{1}",
ll::reflection::type_stem_name_v<Type>,
magic_enum::enum_name(sv)
);
})
| std::ranges::to<std::vector>();
auto oldValue = std::find(
enumMap.begin(),
enumMap.end(),
static_cast<Type>(*block.getState<int>(state))
) - enumMap.begin();
// clang-format on
form.appendDropdown(
fmt::format("state.{0}.name", state.mName->getString()),
names,
oldValue,
[oldValue, &state](Player& player, int64 value) -> void {
if (oldValue == value) return;
// clang-format off
if (
auto block = mEditBlocks[&player].second->setState(
state,
static_cast<int>(enumMap.at(value))
); block
) {
mEditBlocks[&player].second = block.as_ptr();
}
// clang-format on
}
);
};
} else {
static_assert(ll::traits::always_false<T>, "Unsupported state type");
}
};
{
handlerFunc(VanillaStates::Active());
handlerFunc(VanillaStates::Age());
handlerFunc(VanillaStates::AgeBit());
handlerFunc(VanillaStates::AttachedBit());
handlerFunc(VanillaStates::Attachment());
handlerFunc(VanillaStates::BambooLeafSize());
handlerFunc(VanillaStates::BambooThickness());
handlerFunc(VanillaStates::BeehiveHoneyLevel());
handlerFunc(VanillaStates::BigDripleafHead());
handlerFunc(VanillaStates::BigDripleafTilt());
handlerFunc(VanillaStates::BiteCounter());
handlerFunc(VanillaStates::Bloom());
handlerFunc(VanillaStates::BookshelfOccupiedSlots());
handlerFunc(VanillaStates::BrewingStandSlotABit());
handlerFunc(VanillaStates::BrewingStandSlotBBit());
handlerFunc(VanillaStates::BrewingStandSlotCBit());
handlerFunc(VanillaStates::BrushedProgress());
handlerFunc(VanillaStates::ButtonPressedBit());
handlerFunc(VanillaStates::CanSummon());
handlerFunc(reinterpret_cast<BlockStateVariant<CandleCount> const&>(VanillaStates::Candles()));
handlerFunc(VanillaStates::CauldronLiquid());
handlerFunc(VanillaStates::ClusterCount());
handlerFunc(VanillaStates::ComposterFillLevel());
handlerFunc(VanillaStates::ConditionalBit());
handlerFunc(
reinterpret_cast<BlockStateVariant<CoralDirection> const&>(VanillaStates::CoralDirection())
);
handlerFunc(VanillaStates::CoralFanDirection());
handlerFunc(VanillaStates::CoveredBit());
handlerFunc(VanillaStates::CrackedState());
handlerFunc(VanillaStates::Crafting());
handlerFunc(VanillaStates::CreakingHeartState());
handlerFunc(VanillaStates::DEPRECATED());
handlerFunc(VanillaStates::DEPRECATED_AllowUnderwaterBit());
handlerFunc(VanillaStates::DEPRECATED_BlockLightLevel());
handlerFunc(VanillaStates::DEPRECATED_ChemistryTableType());
handlerFunc(VanillaStates::DEPRECATED_ChiselType());
handlerFunc(VanillaStates::DEPRECATED_Color());
handlerFunc(VanillaStates::DEPRECATED_ColorBit());
handlerFunc(VanillaStates::DEPRECATED_CoralColor());
handlerFunc(VanillaStates::DEPRECATED_CoralHangTypeBit());
handlerFunc(VanillaStates::DEPRECATED_Damage());
handlerFunc(VanillaStates::DEPRECATED_DirtType());
handlerFunc(VanillaStates::DEPRECATED_DoublePlantType());
handlerFunc(VanillaStates::DEPRECATED_FlowerType());
handlerFunc(VanillaStates::DEPRECATED_MonsterEggStoneType());
handlerFunc(VanillaStates::DEPRECATED_NewLeavesType());
handlerFunc(VanillaStates::DEPRECATED_NewLogType());
handlerFunc(VanillaStates::DEPRECATED_NoDropBit());
handlerFunc(VanillaStates::DEPRECATED_OldLeavesType());
handlerFunc(VanillaStates::DEPRECATED_OldLogType());
handlerFunc(VanillaStates::DEPRECATED_PrismarineBlockType());
handlerFunc(VanillaStates::DEPRECATED_SandType());
handlerFunc(VanillaStates::DEPRECATED_SandstoneType());
handlerFunc(VanillaStates::DEPRECATED_SaplingType());
handlerFunc(VanillaStates::DEPRECATED_SpongeType());
handlerFunc(VanillaStates::DEPRECATED_StoneBrickType());
handlerFunc(VanillaStates::DEPRECATED_StoneSlabType());
handlerFunc(VanillaStates::DEPRECATED_StoneSlabType2());
handlerFunc(VanillaStates::DEPRECATED_StoneSlabType3());
handlerFunc(VanillaStates::DEPRECATED_StoneSlabType4());
handlerFunc(VanillaStates::DEPRECATED_StoneType());
handlerFunc(VanillaStates::DEPRECATED_StrippedBit());
handlerFunc(VanillaStates::DEPRECATED_StructureVoidType());
handlerFunc(VanillaStates::DEPRECATED_TallGrassType());
handlerFunc(VanillaStates::DEPRECATED_WallBlockType());
handlerFunc(VanillaStates::DEPRECATED_WoodType());
handlerFunc(VanillaStates::DeadBit());
handlerFunc(
reinterpret_cast<BlockStateVariant<SensibleDirections> const&>(VanillaStates::Direction())
);
handlerFunc(VanillaStates::DisarmedBit());
handlerFunc(VanillaStates::DoorHingeBit());
handlerFunc(VanillaStates::DragDown());
handlerFunc(VanillaStates::DripstoneThickness());
handlerFunc(VanillaStates::EndPortalEyeBit());
handlerFunc(VanillaStates::ExplodeBit());
handlerFunc(VanillaStates::Extinguished());
handlerFunc(
reinterpret_cast<BlockStateVariant<Facing::Name> const&>(VanillaStates::FacingDirection())
);
handlerFunc(VanillaStates::FillLevel());
handlerFunc(VanillaStates::GrowingPlantAge());
handlerFunc(VanillaStates::Growth());
handlerFunc(VanillaStates::HangingBit());
handlerFunc(VanillaStates::HeadPieceBit());
handlerFunc(VanillaStates::Height());
handlerFunc(VanillaStates::HugeMushroomBits());
handlerFunc(VanillaStates::InWallBit());
handlerFunc(VanillaStates::InfiniburnBit());
handlerFunc(VanillaStates::ItemFrameMapBit());
handlerFunc(VanillaStates::ItemFramePhotoBit());
handlerFunc(VanillaStates::KelpAge());
handlerFunc(VanillaStates::LeverDirection());
handlerFunc(VanillaStates::LiquidDepth());
handlerFunc(VanillaStates::Lit());
handlerFunc(VanillaStates::MoisturizedAmount());
handlerFunc(VanillaStates::MultiFaceDirectionBits());
handlerFunc(VanillaStates::Natural());
handlerFunc(VanillaStates::OccupiedBit());
handlerFunc(VanillaStates::Ominous());
handlerFunc(VanillaStates::OpenBit());
handlerFunc(VanillaStates::Orientation());
handlerFunc(VanillaStates::OutputLitBit());
handlerFunc(VanillaStates::OutputSubtractBit());
handlerFunc(VanillaStates::PaleMossCarpetSideEast());
handlerFunc(VanillaStates::PaleMossCarpetSideNorth());
handlerFunc(VanillaStates::PaleMossCarpetSideSouth());
handlerFunc(VanillaStates::PaleMossCarpetSideWest());
handlerFunc(VanillaStates::PersistentBit());
handlerFunc(VanillaStates::PillarAxis());
handlerFunc(VanillaStates::PortalAxis());
handlerFunc(VanillaStates::PoweredBit());
handlerFunc(VanillaStates::PropaguleStage());
handlerFunc(VanillaStates::RailDataBit());
handlerFunc(
reinterpret_cast<BlockStateVariant<RailDirection> const&>(VanillaStates::RailDirection())
);
handlerFunc(VanillaStates::RedstoneSignal());
handlerFunc(VanillaStates::RepeaterDelay());
handlerFunc(VanillaStates::RespawnAnchorCharge());
handlerFunc(
reinterpret_cast<BlockStateVariant<Facing::Rotation> const&>(VanillaStates::Rotation())
);
handlerFunc(reinterpret_cast<BlockStateVariant<SculkSensorPhase> const&>(
VanillaStates::SculkSensorPhase()
));
handlerFunc(VanillaStates::SeagrassType());
handlerFunc(VanillaStates::Stability());
handlerFunc(VanillaStates::StabilityCheckBit());
handlerFunc(VanillaStates::StandingRotation());
handlerFunc(VanillaStates::StructureBlockType());
handlerFunc(VanillaStates::SuspendedBit());
handlerFunc(VanillaStates::Tip());
handlerFunc(VanillaStates::ToggleBit());
handlerFunc(VanillaStates::TopSlotBit());
handlerFunc(VanillaStates::TorchFacingDirection());
handlerFunc(reinterpret_cast<BlockStateVariant<TrialSpawner::SpawningLogicState> const&>(
VanillaStates::TrialSpawnerState()
));
handlerFunc(VanillaStates::TriggeredBit());
handlerFunc(VanillaStates::TurtleEggCount());
handlerFunc(VanillaStates::TwistingVinesAge());
handlerFunc(VanillaStates::UpdateBit());
handlerFunc(VanillaStates::UpperBlockBit());
handlerFunc(VanillaStates::UpsideDownBit());
handlerFunc(VanillaStates::VaultState());
handlerFunc(VanillaStates::VineDirectionBits());
handlerFunc(VanillaStates::WallConnectionTypeEast());
handlerFunc(VanillaStates::WallConnectionTypeNorth());
handlerFunc(VanillaStates::WallConnectionTypeSouth());
handlerFunc(VanillaStates::WallConnectionTypeWest());
handlerFunc(VanillaStates::WallPostBit());
handlerFunc(VanillaStates::WeepingVinesAge());
handlerFunc(reinterpret_cast<BlockStateVariant<WeirdoDirection> const&>(
VanillaStates::WeirdoDirection()
));
}
return states;
}();
auto* block = (mEditBlocks[&player] = {pos, &player.getDimensionBlockSource().getBlock(pos)}).second;
auto title = fmt::format("%{0}.name", block->mLegacyBlock->mDescriptionId.get());
if (gmlib::I18nAPI::get(title) == title.substr(1)) {
title = fmt::format(
"%{0}.name",
block->mLegacyBlock->asItemInstance(*block, nullptr).mItem->getDescriptionId()
);
}
gmlib::ui::CustomForm form(title);
bool showStates = false;
for (auto& [state, func] : mStatesHandler) {
if (!block->hasState(*state)) continue;
func(form, *block);
showStates = true;
}
if (!showStates) return;
form.sendTo(player, [](Player& player, auto&, std::optional<ModalFormCancelReason> reason) -> void {
if (reason) return;
if (auto it = mEditBlocks.find(&player); it != mEditBlocks.end()) {
player.getDimensionBlockSource().setBlock(
it->second.first,
*it->second.second,
static_cast<int>(BlockUpdateFlag::Network),
nullptr,
nullptr
);
mEditBlocks.erase(it);
}
});
},
std::chrono::milliseconds(50)
);