From 4465f547a78aea9ba60f2212738ef35d51d6128f Mon Sep 17 00:00:00 2001 From: OEOTYAN Date: Sun, 7 Apr 2024 04:24:43 +0800 Subject: [PATCH] faet: add most region --- old/core/brush/Brush.cpp | 43 +- old/core/brush/Brush.h | 45 +- old/core/brush/Brushs.h | 19 +- old/core/brush/ClipboardBrush.cpp | 130 +- old/core/brush/ClipboardBrush.h | 23 +- old/core/brush/ColorBrush.cpp | 285 +- old/core/brush/ColorBrush.h | 39 +- old/core/brush/CubeBrush.cpp | 30 +- old/core/brush/CubeBrush.h | 19 +- old/core/brush/CylinderBrush.cpp | 33 +- old/core/brush/CylinderBrush.h | 21 +- old/core/brush/DeformBrush.cpp | 5 +- old/core/brush/DeformBrush.h | 9 +- old/core/brush/FlatBrush.cpp | 118 +- old/core/brush/FlatBrush.h | 19 +- old/core/brush/GravityBrush.cpp | 5 +- old/core/brush/GravityBrush.h | 9 +- old/core/brush/ImageHeightmapBrush.cpp | 270 +- old/core/brush/ImageHeightmapBrush.h | 23 +- old/core/brush/MixBrush.cpp | 246 +- old/core/brush/MixBrush.h | 23 +- old/core/brush/SmoothBrush.cpp | 133 +- old/core/brush/SmoothBrush.h | 21 +- old/core/brush/SphereBrush.cpp | 31 +- old/core/brush/SphereBrush.h | 19 +- old/core/brush/tool.cpp | 451 +- old/core/brush/tool.h | 110 +- old/core/builder/SimpleBuilder.cpp | 529 +-- old/core/builder/SimpleBuilder.h | 63 +- old/core/command/BrushCommand.cpp | 698 +-- old/core/command/ClipboardCommand.cpp | 715 +-- old/core/command/GenerationCommand.cpp | 425 +- old/core/command/HandToolCommand.cpp | 307 +- old/core/command/HistoryCommand.cpp | 301 +- old/core/command/RegionCommand.cpp | 1106 ++--- old/core/command/RegionInfoCommand.cpp | 623 +-- old/core/command/RegionOperationCommand.cpp | 4407 ++++++++++--------- old/core/command/allCommand.cpp | 526 ++- old/core/command/allCommand.hpp | 47 +- old/core/data/PlayerData.cpp | 397 +- old/core/data/PlayerData.h | 101 +- old/core/eval/Bresenham.cpp | 211 - old/core/eval/Bresenham.hpp | 48 - old/core/eval/Eval.cpp | 1283 +++--- old/core/eval/Eval.h | 245 +- old/core/eval/blur.cpp | 141 +- old/core/eval/blur.hpp | 12 +- old/core/filesys/download.cpp | 42 +- old/core/filesys/download.h | 11 +- old/core/filesys/file.cpp | 90 +- old/core/filesys/file.h | 25 +- old/core/image/Image.cpp | 196 +- old/core/image/Image.h | 87 +- old/core/particle/Graphics.cpp | 264 +- old/core/particle/Graphics.h | 53 +- old/core/region/ConvexRegion.cpp | 281 -- old/core/region/ConvexRegion.h | 89 - old/core/region/CuboidRegion.cpp | 172 - old/core/region/CuboidRegion.h | 32 - old/core/region/CylinderRegion.cpp | 357 +- old/core/region/CylinderRegion.h | 62 +- old/core/region/ExpandRegion.cpp | 165 - old/core/region/ExpandRegion.h | 29 - old/core/region/LoftRegion.cpp | 451 +- old/core/region/LoftRegion.h | 88 +- old/core/region/PolyRegion.cpp | 407 +- old/core/region/PolyRegion.h | 69 +- old/core/region/Region.cpp | 213 - old/core/region/Region.h | 93 - old/core/region/Regions.h | 13 +- old/core/region/SphereRegion.cpp | 135 - old/core/region/SphereRegion.h | 44 - old/core/store/BlockListPattern.cpp | 594 +-- old/core/store/BlockListPattern.h | 114 +- old/core/store/BlockNBTSet.cpp | 225 +- old/core/store/BlockNBTSet.hpp | 83 +- old/core/store/Clipboard.cpp | 427 +- old/core/store/Clipboard.hpp | 89 +- old/core/store/ClipboardPattern.cpp | 113 +- old/core/store/ClipboardPattern.h | 31 +- old/core/store/GradientPattern.cpp | 181 +- old/core/store/GradientPattern.h | 39 +- old/core/store/History.cpp | 5 +- old/core/store/History.h | 50 +- old/core/store/Pattern.cpp | 34 +- old/core/store/Pattern.h | 64 +- old/core/store/Patterns.h | 9 +- old/core/subscribe/player.cpp | 510 ++- old/core/subscribe/player.hpp | 39 +- old/core/subscribe/server.cpp | 120 +- old/core/subscribe/server.hpp | 9 +- old/core/subscribe/subscribeall.hpp | 3 - old/core/utils/ColorTool.cpp | 137 +- old/core/utils/ColorTool.h | 23 +- old/core/utils/StringTool.h | 124 +- scripts/format_all.py | 41 + src/region/ConvexRegion.cpp | 234 + src/region/ConvexRegion.h | 52 + src/region/CuboidRegion.cpp | 156 + src/region/CuboidRegion.h | 39 + src/region/ExpandRegion.cpp | 27 + src/region/ExpandRegion.h | 19 + src/region/Region.cpp | 102 + src/region/Region.h | 78 + src/region/SphereRegion.cpp | 139 + src/region/SphereRegion.h | 50 + src/utils/Bresenham.cpp | 175 + src/utils/Bresenham.h | 55 + src/utils/Catenary.h | 14 + src/utils/GeoContainer.h | 49 + src/utils/Hash.h | 11 + src/utils/Math.cpp | 47 + src/utils/Math.h | 47 + src/utils/Serialize.h | 17 + src/utils/Triangle.h | 57 + src/utils/WithDim.h | 1 + src/worldedit/Config.h | 25 +- src/worldedit/Global.h | 17 +- src/worldedit/WorldEdit.cpp | 29 +- src/worldedit/WorldEdit.h | 7 +- xmake.lua | 2 +- 121 files changed, 11720 insertions(+), 10625 deletions(-) delete mode 100644 old/core/eval/Bresenham.cpp delete mode 100644 old/core/eval/Bresenham.hpp delete mode 100644 old/core/region/ConvexRegion.cpp delete mode 100644 old/core/region/ConvexRegion.h delete mode 100644 old/core/region/CuboidRegion.cpp delete mode 100644 old/core/region/CuboidRegion.h delete mode 100644 old/core/region/ExpandRegion.cpp delete mode 100644 old/core/region/ExpandRegion.h delete mode 100644 old/core/region/Region.cpp delete mode 100644 old/core/region/Region.h delete mode 100644 old/core/region/SphereRegion.cpp delete mode 100644 old/core/region/SphereRegion.h create mode 100644 scripts/format_all.py create mode 100644 src/region/ConvexRegion.cpp create mode 100644 src/region/ConvexRegion.h create mode 100644 src/region/CuboidRegion.cpp create mode 100644 src/region/CuboidRegion.h create mode 100644 src/region/ExpandRegion.cpp create mode 100644 src/region/ExpandRegion.h create mode 100644 src/region/Region.cpp create mode 100644 src/region/Region.h create mode 100644 src/region/SphereRegion.cpp create mode 100644 src/region/SphereRegion.h create mode 100644 src/utils/Bresenham.cpp create mode 100644 src/utils/Bresenham.h create mode 100644 src/utils/Catenary.h create mode 100644 src/utils/GeoContainer.h create mode 100644 src/utils/Hash.h create mode 100644 src/utils/Math.cpp create mode 100644 src/utils/Math.h create mode 100644 src/utils/Serialize.h create mode 100644 src/utils/Triangle.h diff --git a/old/core/brush/Brush.cpp b/old/core/brush/Brush.cpp index d3161ca..241a2cb 100644 --- a/old/core/brush/Brush.cpp +++ b/old/core/brush/Brush.cpp @@ -1,31 +1,28 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "Brush.h" +#include "store/Patterns.h" #include #include -#include "store/Patterns.h" -namespace worldedit { - long long Brush::set(Player* player, ::BlockInstance blockInstance) { - return -2; - } - long long Brush::lset(Player* player, ::BlockInstance blockInstance) { - return -2; - } - bool Brush::maskFunc(EvalFunctions& func, - const phmap::flat_hash_map& var, - std::function const& todo) { - if (mask != "") { - if (cpp_eval::eval(mask, var, func) > 0.5) { - todo(); - return true; - } - } else { +namespace we { +long long Brush::set(Player* player, ::BlockInstance blockInstance) { return -2; } +long long Brush::lset(Player* player, ::BlockInstance blockInstance) { return -2; } +bool Brush::maskFunc( + EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo +) { + if (mask != "") { + if (cpp_eval::eval(mask, var, func) > 0.5) { todo(); return true; } - return false; + } else { + todo(); + return true; } + return false; +} - Brush::Brush(unsigned short s, std::unique_ptr p) : size(s), pattern(std::move(p)) {} -} // namespace worldedit \ No newline at end of file +Brush::Brush(unsigned short s, std::unique_ptr p) +: size(s), + pattern(std::move(p)) {} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/Brush.h b/old/core/brush/Brush.h index 679a1ce..deb157c 100644 --- a/old/core/brush/Brush.h +++ b/old/core/brush/Brush.h @@ -1,27 +1,26 @@ -// -// Created by OEOTYAN on 2022/06/09. -// #pragma once -#include -#include #include "eval/Eval.h" #include "store/Patterns.h" +#include +#include -namespace worldedit { - class Brush { - public: - unsigned short size = 0; - std::unique_ptr pattern = nullptr; - std::string mask = ""; - bool needFace = false; - bool lneedFace = false; - Brush() {} - Brush(unsigned short, std::unique_ptr p); - void setMask(std::string_view str = "") { mask = str; }; - virtual long long set(class Player*, class ::BlockInstance); - virtual long long lset(class Player*, class ::BlockInstance); - bool maskFunc(class EvalFunctions& func, - const phmap::flat_hash_map& var, - std::function const& todo); - }; -} // namespace worldedit +namespace we { +class Brush { +public: + unsigned short size = 0; + std::unique_ptr pattern = nullptr; + std::string mask = ""; + bool needFace = false; + bool lneedFace = false; + Brush() {} + Brush(unsigned short, std::unique_ptr p); + void setMask(std::string_view str = "") { mask = str; }; + virtual long long set(class Player*, class ::BlockInstance); + virtual long long lset(class Player*, class ::BlockInstance); + bool maskFunc( + class EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo + ); +}; +} // namespace we diff --git a/old/core/brush/Brushs.h b/old/core/brush/Brushs.h index 13c0652..0fb9c6c 100644 --- a/old/core/brush/Brushs.h +++ b/old/core/brush/Brushs.h @@ -1,18 +1,15 @@ -// -// Created by OEOTYAN on 2022/06/09. -// #pragma once -#include "tool.h" #include "Brush.h" -#include "MixBrush.h" -#include "FlatBrush.h" -#include "CubeBrush.h" +#include "ClipboardBrush.h" #include "ColorBrush.h" +#include "CubeBrush.h" +#include "CylinderBrush.h" #include "DeformBrush.h" -#include "SmoothBrush.h" -#include "SphereBrush.h" +#include "FlatBrush.h" #include "GravityBrush.h" -#include "CylinderBrush.h" -#include "ClipboardBrush.h" #include "ImageHeightmapBrush.h" +#include "MixBrush.h" +#include "SmoothBrush.h" +#include "SphereBrush.h" +#include "tool.h" diff --git a/old/core/brush/ClipboardBrush.cpp b/old/core/brush/ClipboardBrush.cpp index 20dcf1a..4292607 100644 --- a/old/core/brush/ClipboardBrush.cpp +++ b/old/core/brush/ClipboardBrush.cpp @@ -1,76 +1,78 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "ClipboardBrush.h" -#include "store/Patterns.h" +#include "WorldEdit.h" #include "store/BlockNBTSet.hpp" +#include "store/Patterns.h" #include -#include "WorldEdit.h" -namespace worldedit { - ClipboardBrush::ClipboardBrush(unsigned short s, Clipboard& c, bool o, bool a) - : Brush(s, nullptr), center(o), ignoreAir(a), clipboard(c) {} - long long ClipboardBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - BlockPos pbPos; - if (center) { - BoundingBox box(BlockPos::ZERO, clipboard.board); - pbPos = blockInstance.getPosition() - box.getCenter() + clipboard.playerRelPos; - } else { - pbPos = blockInstance.getPosition(); - } - auto dimID = player->getDimensionId(); +namespace we { +ClipboardBrush::ClipboardBrush(unsigned short s, Clipboard& c, bool o, bool a) +: Brush(s, nullptr), + center(o), + ignoreAir(a), + clipboard(c) {} +long long ClipboardBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + BlockPos pbPos; + if (center) { + BoundingBox box(BlockPos::ZERO, clipboard.board); + pbPos = blockInstance.getPosition() - box.getCenter() + clipboard.playerRelPos; + } else { + pbPos = blockInstance.getPosition(); + } + auto dimID = player->getDimensionId(); - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - auto blockSource = &player->getDimensionBlockSource(); - BoundingBox box = clipboard.getBoundingBox() + pbPos; + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + auto blockSource = &player->getDimensionBlockSource(); + BoundingBox box = clipboard.getBoundingBox() + pbPos; - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dimID; - history.playerPos = box.min; - box.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - box.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dimID; + history.playerPos = box.min; + box.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - box.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - EvalFunctions f; - f.setbs(blockSource); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - long long i = 0; - if (ignoreAir) { - clipboard.forEachBlockInClipboard([&](const BlockPos& pos) { - if (clipboard.getSet(pos).getBlock() == BedrockBlocks::mAir && - clipboard.getSet(pos).getExBlock() == BedrockBlocks::mAir) { - return; - } - auto worldPos = clipboard.getPos(pos) + pbPos; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + long long i = 0; + if (ignoreAir) { + clipboard.forEachBlockInClipboard([&](BlockPos const& pos) { + if (clipboard.getSet(pos).getBlock() == BedrockBlocks::mAir + && clipboard.getSet(pos).getExBlock() == BedrockBlocks::mAir) { + return; + } + auto worldPos = clipboard.getPos(pos) + pbPos; - setFunction(variables, f, box, playerPos, worldPos, box.toAABB().getCenter()); - maskFunc(f, variables, [&]() mutable { - i += playerData.clipboard.setBlocks(pos, worldPos, blockSource, playerData, f, variables); - }); + setFunction(variables, f, box, playerPos, worldPos, box.toAABB().getCenter()); + maskFunc(f, variables, [&]() mutable { + i += playerData.clipboard + .setBlocks(pos, worldPos, blockSource, playerData, f, variables); }); - } else { - clipboard.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = clipboard.getPos(pos) + pbPos; - setFunction(variables, f, box, playerPos, worldPos, box.toAABB().getCenter()); - maskFunc(f, variables, [&]() mutable { - i += playerData.clipboard.setBlocks(pos, worldPos, blockSource, playerData, f, variables); - }); + }); + } else { + clipboard.forEachBlockInClipboard([&](BlockPos const& pos) { + auto worldPos = clipboard.getPos(pos) + pbPos; + setFunction(variables, f, box, playerPos, worldPos, box.toAABB().getCenter()); + maskFunc(f, variables, [&]() mutable { + i += playerData.clipboard + .setBlocks(pos, worldPos, blockSource, playerData, f, variables); }); - } - return i; + }); } -} // namespace worldedit \ No newline at end of file + return i; +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/ClipboardBrush.h b/old/core/brush/ClipboardBrush.h index 8a81b42..4da79ad 100644 --- a/old/core/brush/ClipboardBrush.h +++ b/old/core/brush/ClipboardBrush.h @@ -1,17 +1,14 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" #include "store/Clipboard.hpp" -namespace worldedit { - class ClipboardBrush final : public Brush { - public: - Clipboard clipboard; - bool center = true; - bool ignoreAir = false; - ClipboardBrush(unsigned short, Clipboard&, bool, bool); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class ClipboardBrush : public Brush { +public: + Clipboard clipboard; + bool center = true; + bool ignoreAir = false; + ClipboardBrush(unsigned short, Clipboard&, bool, bool); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/ColorBrush.cpp b/old/core/brush/ColorBrush.cpp index f526a11..c0306fc 100644 --- a/old/core/brush/ColorBrush.cpp +++ b/old/core/brush/ColorBrush.cpp @@ -1,154 +1,171 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #pragma once #include "ColorBrush.h" #include "WorldEdit.h" -#include "utils/ColorTool.h" -#include "mc/StaticVanillaBlocks.hpp" -#include "mc/BlockSource.hpp" #include "mc/BlockInstance.hpp" +#include "mc/BlockSource.hpp" +#include "mc/StaticVanillaBlocks.hpp" #include "store/Patterns.h" +#include "utils/ColorTool.h" -namespace worldedit { - ColorBrush::ColorBrush(unsigned short size, - float density, - float opacity, - mce::Color color, - std::unique_ptr bp, - bool mixbox) - : Brush(size, std::move(bp)), density(density), opacity(opacity), color(color), useMixboxLerp(mixbox) {} - - long long ColorBrush::set(Player* player, BlockInstance blockInstance) { - long long iter = 0; - if (blockInstance == BlockInstance::Null) { +namespace we { +ColorBrush::ColorBrush( + unsigned short size, + float density, + float opacity, + mce::Color color, + std::unique_ptr bp, + bool mixbox +) +: Brush(size, std::move(bp)), + density(density), + opacity(opacity), + color(color), + useMixboxLerp(mixbox) {} + +long long ColorBrush::set(Player* player, BlockInstance blockInstance) { + long long iter = 0; + if (blockInstance == BlockInstance::Null) { + return -2; + } + std::queue q; + auto pos0 = blockInstance.getPosition(); + q.push(pos0); + + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto blockSource = blockInstance.getBlockSource(); + + EvalFunctions f; + f.setbs(blockSource); + phmap::flat_hash_map variables; + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + variables["px"] = playerPos.x; + variables["py"] = playerPos.y; + variables["pz"] = playerPos.z; + variables["pp"] = playerRot.x; + variables["pt"] = playerRot.y; + phmap::flat_hash_set s; + s.insert(pos0); + + BoundingBox boundingBox = BoundingBox(pos0, pos0); + + mce::Color finalColor = color; + + auto& cmap = getBlockColorMap(); + + if (pattern != nullptr) { + f.setPos(pos0); + variables["rx"] = pos0.x; + variables["ry"] = pos0.y; + variables["rz"] = pos0.z; + variables["x"] = 0; + variables["y"] = 0; + variables["z"] = 0; + variables["cx"] = 0; + variables["cy"] = 0; + variables["cz"] = 0; + variables["ox"] = pos0.x - playerPos.x; + variables["oy"] = pos0.y - playerPos.y; + variables["oz"] = pos0.z - playerPos.z; + Block const* blockp = pattern->getBlock(variables, f); + if (!cmap.contains(blockp)) { return -2; } - std::queue q; - auto pos0 = blockInstance.getPosition(); - q.push(pos0); - - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto blockSource = blockInstance.getBlockSource(); - - EvalFunctions f; - f.setbs(blockSource); - phmap::flat_hash_map variables; - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - variables["px"] = playerPos.x; - variables["py"] = playerPos.y; - variables["pz"] = playerPos.z; - variables["pp"] = playerRot.x; - variables["pt"] = playerRot.y; - phmap::flat_hash_set s; - s.insert(pos0); - - BoundingBox boundingBox = BoundingBox(pos0, pos0); - - mce::Color finalColor = color; - - auto& cmap = getBlockColorMap(); - - if (pattern != nullptr) { - f.setPos(pos0); - variables["rx"] = pos0.x; - variables["ry"] = pos0.y; - variables["rz"] = pos0.z; - variables["x"] = 0; - variables["y"] = 0; - variables["z"] = 0; - variables["cx"] = 0; - variables["cy"] = 0; - variables["cz"] = 0; - variables["ox"] = pos0.x - playerPos.x; - variables["oy"] = pos0.y - playerPos.y; - variables["oz"] = pos0.z - playerPos.z; - Block const* blockp = pattern->getBlock(variables, f); - if (!cmap.contains(blockp)) { - return -2; - } - finalColor = cmap[blockp]; - } + finalColor = cmap[blockp]; + } - while (!q.empty()) { - auto pos1 = q.front(); - q.pop(); - boundingBox.merge(pos1); - BoundingBox(pos1 - 1, pos1 + 1).forEachBlockInBox([&](const BlockPos& tmpPos) { - if (&blockSource->getBlock(tmpPos) != BedrockBlocks::mAir && tmpPos != pos1 && - pos0.distanceTo(tmpPos) <= 0.5 + size && !s.contains(tmpPos)) { - int counts = 0; - for (auto& calPos : tmpPos.getNeighbors()) { - counts += !blockSource->getBlock(calPos).isSolid(); - } - if (counts > 0) { - q.push(tmpPos); - s.insert(tmpPos); - } + while (!q.empty()) { + auto pos1 = q.front(); + q.pop(); + boundingBox.merge(pos1); + BoundingBox(pos1 - 1, pos1 + 1).forEachBlockInBox([&](BlockPos const& tmpPos) { + if (&blockSource->getBlock(tmpPos) != BedrockBlocks::mAir && tmpPos != pos1 + && pos0.distanceTo(tmpPos) <= 0.5 + size && !s.contains(tmpPos)) { + int counts = 0; + for (auto& calPos : tmpPos.getNeighbors()) { + counts += !blockSource->getBlock(calPos).isSolid(); + } + if (counts > 0) { + q.push(tmpPos); + s.insert(tmpPos); } - }); - } - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = blockInstance.getDimensionId(); - history.playerPos = boundingBox.min; - for (auto& pos1 : s) { - auto localPos = pos1 - boundingBox.min; - auto bi = blockSource->getBlockInstance(pos1); - history.storeBlock(bi, localPos); } - } + }); + } + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = blockInstance.getDimensionId(); + history.playerPos = boundingBox.min; for (auto& pos1 : s) { - f.setPos(pos1); - variables["x"] = static_cast(pos1.x - pos0.x) / size; - variables["y"] = static_cast(pos1.y - pos0.y) / size; - variables["z"] = static_cast(pos1.z - pos0.z) / size; - variables["rx"] = pos1.x; - variables["ry"] = pos1.y; - variables["rz"] = pos1.z; - variables["cx"] = pos1.x - pos0.x; - variables["cy"] = pos1.y - pos0.y; - variables["cz"] = pos1.z - pos0.z; - variables["ox"] = pos1.x - playerPos.x; - variables["oy"] = pos1.y - playerPos.y; - variables["oz"] = pos1.z - playerPos.z; - // logger().debug("maskFunc"); - maskFunc(f, variables, [&]() mutable { - auto* block =&blockSource->getBlock(pos1); - mce::Color hereColor(0, 0, 0, 1); - if (cmap.contains(block)) { - hereColor = cmap[block]; - } + auto localPos = pos1 - boundingBox.min; + auto bi = blockSource->getBlockInstance(pos1); + history.storeBlock(bi, localPos); + } + } + + for (auto& pos1 : s) { + f.setPos(pos1); + variables["x"] = static_cast(pos1.x - pos0.x) / size; + variables["y"] = static_cast(pos1.y - pos0.y) / size; + variables["z"] = static_cast(pos1.z - pos0.z) / size; + variables["rx"] = pos1.x; + variables["ry"] = pos1.y; + variables["rz"] = pos1.z; + variables["cx"] = pos1.x - pos0.x; + variables["cy"] = pos1.y - pos0.y; + variables["cz"] = pos1.z - pos0.z; + variables["ox"] = pos1.x - playerPos.x; + variables["oy"] = pos1.y - playerPos.y; + variables["oz"] = pos1.z - playerPos.z; + // logger().debug("maskFunc"); + maskFunc(f, variables, [&]() mutable { + auto* block = &blockSource->getBlock(pos1); + mce::Color hereColor(0, 0, 0, 1); + if (cmap.contains(block)) { + hereColor = cmap[block]; + } - hereColor = useMixboxLerp ? mixboxLerp(hereColor, finalColor, - smoothBrushAlpha(static_cast(pos1.distanceTo(pos0)), - density, opacity, size)) - : linearLerp(hereColor, finalColor, - smoothBrushAlpha(static_cast(pos1.distanceTo(pos0)), - density, opacity, size)); - - double minDist = DBL_MAX; - Block const* minBlock = nullptr; - for (auto& i : getColorBlockMap()) { - if (i.first.a == 1) { - auto dst = i.first.distanceTo(hereColor); - if (dst < minDist) { - minDist = dst; - minBlock = i.second; - } + hereColor = useMixboxLerp ? mixboxLerp( + hereColor, + finalColor, + smoothBrushAlpha( + static_cast(pos1.distanceTo(pos0)), + density, + opacity, + size + ) + ) + : linearLerp( + hereColor, + finalColor, + smoothBrushAlpha( + static_cast(pos1.distanceTo(pos0)), + density, + opacity, + size + ) + ); + + double minDist = DBL_MAX; + Block const* minBlock = nullptr; + for (auto& i : getColorBlockMap()) { + if (i.first.a == 1) { + auto dst = i.first.distanceTo(hereColor); + if (dst < minDist) { + minDist = dst; + minBlock = i.second; } } + } - iter += playerData.setBlockSimple(blockSource, f, variables, pos1, minBlock); - }); - } - return iter; + iter += playerData.setBlockSimple(blockSource, f, variables, pos1, minBlock); + }); } -} // namespace worldedit \ No newline at end of file + return iter; +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/ColorBrush.h b/old/core/brush/ColorBrush.h index b6aaea2..4712518 100644 --- a/old/core/brush/ColorBrush.h +++ b/old/core/brush/ColorBrush.h @@ -1,25 +1,24 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #pragma once -#include "Globals.h" #include "Brush.h" +#include "Globals.h" -namespace worldedit { - class ColorBrush final : public Brush { - public: - float density = 1; - float opacity = 1; - bool useMixboxLerp = true; - mce::Color color = {1, 1, 1, 1}; - ColorBrush(unsigned short size, - float density, - float opacity, - mce::Color color, - std::unique_ptr bp, - bool mixbox); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class ColorBrush : public Brush { +public: + float density = 1; + float opacity = 1; + bool useMixboxLerp = true; + mce::Color color = {1, 1, 1, 1}; + ColorBrush( + unsigned short size, + float density, + float opacity, + mce::Color color, + std::unique_ptr bp, + bool mixbox + ); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/CubeBrush.cpp b/old/core/brush/CubeBrush.cpp index d329a02..20a6348 100644 --- a/old/core/brush/CubeBrush.cpp +++ b/old/core/brush/CubeBrush.cpp @@ -1,18 +1,24 @@ -// -// Created by OEOTYAN on 2022/06/11. -// #include "CubeBrush.h" #include "builder/SimpleBuilder.h" #include "store/Patterns.h" -namespace worldedit { - CubeBrush::CubeBrush(unsigned short s, std::unique_ptr bp, bool a) : Brush(s, std::move(bp)), hollow(a) {} - long long CubeBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - return SimpleBuilder::buildCube(blockInstance.getPosition(), blockInstance.getDimensionId(), player->getXuid(), - pattern.get(), size, hollow, mask); +namespace we { +CubeBrush::CubeBrush(unsigned short s, std::unique_ptr bp, bool a) +: Brush(s, std::move(bp)), + hollow(a) {} +long long CubeBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; } -} // namespace worldedit \ No newline at end of file + return SimpleBuilder::buildCube( + blockInstance.getPosition(), + blockInstance.getDimensionId(), + player->getXuid(), + pattern.get(), + size, + hollow, + mask + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/CubeBrush.h b/old/core/brush/CubeBrush.h index 2eeaef1..beaca56 100644 --- a/old/core/brush/CubeBrush.h +++ b/old/core/brush/CubeBrush.h @@ -1,14 +1,11 @@ -// -// Created by OEOTYAN on 2022/06/11. -// #pragma once #include "Brush.h" -namespace worldedit { - class CubeBrush final : public Brush { - public: - bool hollow = false; - CubeBrush(unsigned short, std::unique_ptr, bool); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class CubeBrush : public Brush { +public: + bool hollow = false; + CubeBrush(unsigned short, std::unique_ptr, bool); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/CylinderBrush.cpp b/old/core/brush/CylinderBrush.cpp index e88ddec..16add9c 100644 --- a/old/core/brush/CylinderBrush.cpp +++ b/old/core/brush/CylinderBrush.cpp @@ -1,18 +1,25 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "CylinderBrush.h" #include "builder/SimpleBuilder.h" #include "store/Patterns.h" -namespace worldedit { - CylinderBrush::CylinderBrush(unsigned short s, std::unique_ptr bp, int h, bool a) - : Brush(s, std::move(bp)), height(h), hollow(a) {} - long long CylinderBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - return SimpleBuilder::buildCylinder(blockInstance.getPosition(), blockInstance.getDimensionId(), - player->getXuid(), pattern.get(), size, height, hollow, mask); +namespace we { +CylinderBrush::CylinderBrush(unsigned short s, std::unique_ptr bp, int h, bool a) +: Brush(s, std::move(bp)), + height(h), + hollow(a) {} +long long CylinderBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; } -} // namespace worldedit \ No newline at end of file + return SimpleBuilder::buildCylinder( + blockInstance.getPosition(), + blockInstance.getDimensionId(), + player->getXuid(), + pattern.get(), + size, + height, + hollow, + mask + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/CylinderBrush.h b/old/core/brush/CylinderBrush.h index 6bbf677..12b577f 100644 --- a/old/core/brush/CylinderBrush.h +++ b/old/core/brush/CylinderBrush.h @@ -1,15 +1,12 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" -namespace worldedit { - class CylinderBrush final : public Brush { - public: - bool hollow = false; - int height = 0; - CylinderBrush(unsigned short, std::unique_ptr, int, bool); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class CylinderBrush : public Brush { +public: + bool hollow = false; + int height = 0; + CylinderBrush(unsigned short, std::unique_ptr, int, bool); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/DeformBrush.cpp b/old/core/brush/DeformBrush.cpp index d3d060e..cea383d 100644 --- a/old/core/brush/DeformBrush.cpp +++ b/old/core/brush/DeformBrush.cpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "DeformBrush.h" -namespace worldedit {} // namespace worldedit \ No newline at end of file +namespace we {} // namespace we \ No newline at end of file diff --git a/old/core/brush/DeformBrush.h b/old/core/brush/DeformBrush.h index 322f7db..e59ea6f 100644 --- a/old/core/brush/DeformBrush.h +++ b/old/core/brush/DeformBrush.h @@ -1,9 +1,6 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" -namespace worldedit { - class DeformBrush final : public Brush {}; -} // namespace worldedit +namespace we { +class DeformBrush : public Brush {}; +} // namespace we diff --git a/old/core/brush/FlatBrush.cpp b/old/core/brush/FlatBrush.cpp index b5a1aa9..561aec9 100644 --- a/old/core/brush/FlatBrush.cpp +++ b/old/core/brush/FlatBrush.cpp @@ -1,70 +1,78 @@ -// -// Created by OEOTYAN on 2023/02/03. -// -#include "Globals.h" #include "FlatBrush.h" -#include "mc/Level.hpp" +#include "Globals.h" #include "WorldEdit.h" #include "mc/Dimension.hpp" -#include "utils/ColorTool.h" +#include "mc/Level.hpp" #include "region/CuboidRegion.h" +#include "utils/ColorTool.h" -namespace worldedit { - FlatBrush::FlatBrush(unsigned short size, float density) : Brush(size, nullptr), density(density) {} +namespace we { +FlatBrush::FlatBrush(unsigned short size, float density) +: Brush(size, nullptr), + density(density) {} - long long FlatBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto pos = blockInstance.getPosition(); +long long FlatBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; + } + auto pos = blockInstance.getPosition(); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto dimID = player->getDimensionId(); - auto blockSource = &player->getDimensionBlockSource(); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto dimID = player->getDimensionId(); + auto blockSource = &player->getDimensionBlockSource(); - BoundingBox box(pos - size, pos + size); - box.min.y = pos.y; - box.max.y = pos.y; + BoundingBox box(pos - size, pos + size); + box.min.y = pos.y; + box.max.y = pos.y; - int sizex = box.max.x - box.min.x + 1; - int sizez = box.max.z - box.min.z + 1; - std::vector heightMap(sizex * sizez, -1e200); - auto range = - reinterpret_cast(Global->getDimension(dimID).mHandle.lock().get())->getHeightRange(); - for (int x = box.min.x; x <= box.max.x; ++x) - for (int z = box.min.z; z <= box.max.z; ++z) { - auto topy = getHighestTerrainBlock(blockSource, x, z, range.min, range.max, mask); - if (topy >= range.min && topy <= range.max) { - int cx = x - box.min.x; - int cz = z - box.min.z; - heightMap[cx * sizez + cz] = - std::lerp(topy + 0.5, pos.y + 0.5, - static_cast(smoothBrushAlpha( - static_cast(sqrt(pow2(x - pos.x) + pow2(z - pos.z))), density, 1, size))); - box.merge(BlockPos(x, topy, z)); - } + int sizex = box.max.x - box.min.x + 1; + int sizez = box.max.z - box.min.z + 1; + std::vector heightMap(sizex * sizez, -1e200); + auto range = reinterpret_cast( + Global->getDimension(dimID).mHandle.lock().get() + ) + ->getHeightRange(); + for (int x = box.min.x; x <= box.max.x; ++x) + for (int z = box.min.z; z <= box.max.z; ++z) { + auto topy = + getHighestTerrainBlock(blockSource, x, z, range.min, range.max, mask); + if (topy >= range.min && topy <= range.max) { + int cx = x - box.min.x; + int cz = z - box.min.z; + heightMap[cx * sizez + cz] = std::lerp( + topy + 0.5, + pos.y + 0.5, + static_cast(smoothBrushAlpha( + static_cast(sqrt(pow2(x - pos.x) + pow2(z - pos.z))), + density, + 1, + size + )) + ); + box.merge(BlockPos(x, topy, z)); } - box.min.y = std::max(static_cast(range.min), box.min.y - 1); - box.max.y = std::min(static_cast(range.max), box.max.y + 1); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dimID; - history.playerPos = box.min; - box.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - box.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); } + box.min.y = std::max(static_cast(range.min), box.min.y - 1); + box.max.y = std::min(static_cast(range.max), box.max.y + 1); - // logger().debug("applyHeightMap"); - CuboidRegion(box, dimID).applyHeightMap(heightMap, xuid, mask); - - return -2; + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dimID; + history.playerPos = box.min; + box.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - box.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); } -} // namespace worldedit \ No newline at end of file + // logger().debug("applyHeightMap"); + CuboidRegion(box, dimID).applyHeightMap(heightMap, xuid, mask); + + return -2; +} + +} // namespace we \ No newline at end of file diff --git a/old/core/brush/FlatBrush.h b/old/core/brush/FlatBrush.h index 795e53c..50bbb75 100644 --- a/old/core/brush/FlatBrush.h +++ b/old/core/brush/FlatBrush.h @@ -1,16 +1,13 @@ -// -// Created by OEOTYAN on 2023/02/03. -// #pragma once #include "Brush.h" -namespace worldedit { - class FlatBrush final : public Brush { - public: - float density; - FlatBrush(unsigned short size, float density); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit \ No newline at end of file +namespace we { +class FlatBrush : public Brush { +public: + float density; + FlatBrush(unsigned short size, float density); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we \ No newline at end of file diff --git a/old/core/brush/GravityBrush.cpp b/old/core/brush/GravityBrush.cpp index 95f3845..77b3e87 100644 --- a/old/core/brush/GravityBrush.cpp +++ b/old/core/brush/GravityBrush.cpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "GravityBrush.h" -namespace worldedit {} // namespace worldedit \ No newline at end of file +namespace we {} // namespace we \ No newline at end of file diff --git a/old/core/brush/GravityBrush.h b/old/core/brush/GravityBrush.h index 8d67e39..8b011ba 100644 --- a/old/core/brush/GravityBrush.h +++ b/old/core/brush/GravityBrush.h @@ -1,9 +1,6 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" -namespace worldedit { - class GravityBrush final : public Brush {}; -} // namespace worldedit +namespace we { +class GravityBrush : public Brush {}; +} // namespace we diff --git a/old/core/brush/ImageHeightmapBrush.cpp b/old/core/brush/ImageHeightmapBrush.cpp index 1868266..6b1a933 100644 --- a/old/core/brush/ImageHeightmapBrush.cpp +++ b/old/core/brush/ImageHeightmapBrush.cpp @@ -1,138 +1,158 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "ImageHeightmapBrush.h" -#include "store/Patterns.h" -#include "mc/Dimension.hpp" #include "WorldEdit.h" +#include "mc/Dimension.hpp" +#include "store/Patterns.h" -namespace worldedit { - ImageHeightmapBrush::ImageHeightmapBrush(unsigned short s, int a, Texture2D const& tex, bool r) - : Brush(s, nullptr), height(a), texture(tex), rotation(r) {} - - long long ImageHeightmapBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto pos = blockInstance.getPosition(); - - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto dimID = player->getDimensionId(); - auto blockSource = &player->getDimensionBlockSource(); - auto range = - reinterpret_cast(Global->getDimension(dimID).mHandle.lock().get())->getHeightRange(); - int minY = 2147483647; - int maxY = -2147483648; - int volume = (size * 2 + 1) * (size * 2 + 1); - std::vector map(volume, -1e200); - - for (int dx = -size; dx <= size; dx++) - for (int dz = -size; dz <= size; dz++) { - auto posk = pos + BlockPos(dx, 0, dz); - posk.y = getHighestTerrainBlock(blockSource, posk.x, posk.z, range.min, range.max - 1, mask); - if (range.min > posk.y) { - continue; - } - maxY = std::max(maxY, posk.y); - minY = std::min(minY, posk.y); - map[(dx + size) * (size * 2 + 1) + dz + size] = posk.y + 0.5; +namespace we { +ImageHeightmapBrush::ImageHeightmapBrush( + unsigned short s, + int a, + Texture2D const& tex, + bool r +) +: Brush(s, nullptr), + height(a), + texture(tex), + rotation(r) {} + +long long ImageHeightmapBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; + } + auto pos = blockInstance.getPosition(); + + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto dimID = player->getDimensionId(); + auto blockSource = &player->getDimensionBlockSource(); + auto range = reinterpret_cast( + Global->getDimension(dimID).mHandle.lock().get() + ) + ->getHeightRange(); + int minY = 2147483647; + int maxY = -2147483648; + int volume = (size * 2 + 1) * (size * 2 + 1); + std::vector map(volume, -1e200); + + for (int dx = -size; dx <= size; dx++) + for (int dz = -size; dz <= size; dz++) { + auto posk = pos + BlockPos(dx, 0, dz); + posk.y = getHighestTerrainBlock( + blockSource, + posk.x, + posk.z, + range.min, + range.max - 1, + mask + ); + if (range.min > posk.y) { + continue; } - if (height > 0) { - maxY += height; - } else { - minY += height; - } - maxY = std::min(maxY, range.max - 1); - minY = std::max(minY, (int)range.min); - - BoundingBox box({pos.x - size, minY, pos.z - size}, {pos.x + size, maxY, pos.z + size}); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dimID; - history.playerPos = box.min; - box.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - box.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); + maxY = std::max(maxY, posk.y); + minY = std::min(minY, posk.y); + map[(dx + size) * (size * 2 + 1) + dz + size] = posk.y + 0.5; } + if (height > 0) { + maxY += height; + } else { + minY += height; + } + maxY = std::min(maxY, range.max - 1); + minY = std::max(minY, (int)range.min); + + BoundingBox box( + {pos.x - size, minY, pos.z - size}, + {pos.x + size, maxY, pos.z + size} + ); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dimID; + history.playerPos = box.min; + box.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - box.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - Sampler sampler(SamplerType::Bilinear, EdgeType::FLIP); - - long long iter = 0; - - std::function rotate; - - if (rotation) { - auto angle = player->getRotation().y; - if (angle >= -45 && angle < 45) { - rotate = [&](double& u, double& v) {}; - } else if (angle >= 45 && angle < 135) { - rotate = [&](double& u, double& v) { - std::swap(u, v); - v = 1 - v; - }; - } else if (angle >= 135 || angle < -135) { - rotate = [&](double& u, double& v) { - u = 1 - u; - v = 1 - v; - }; - } else { - rotate = [&](double& u, double& v) { - std::swap(u, v); - u = 1 - u; - }; - } - } else { + Sampler sampler(SamplerType::Bilinear, EdgeType::FLIP); + + long long iter = 0; + + std::function rotate; + + if (rotation) { + auto angle = player->getRotation().y; + if (angle >= -45 && angle < 45) { rotate = [&](double& u, double& v) {}; + } else if (angle >= 45 && angle < 135) { + rotate = [&](double& u, double& v) { + std::swap(u, v); + v = 1 - v; + }; + } else if (angle >= 135 || angle < -135) { + rotate = [&](double& u, double& v) { + u = 1 - u; + v = 1 - v; + }; + } else { + rotate = [&](double& u, double& v) { + std::swap(u, v); + u = 1 - u; + }; } + } else { + rotate = [&](double& u, double& v) {}; + } - EvalFunctions f; - f.setbs(blockSource); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - auto playerPos = player->getPosition(); - - Vec3 center = pos.toVec3(); - - for (int dx = -size; dx <= size; dx++) - for (int dz = -size; dz <= size; dz++) { - auto posk = pos + BlockPos(dx, 0, dz); - double mapp = map[(dx + size) * (size * 2 + 1) + dz + size]; - int originY = (int)floor(mapp); - double u = (dx + size) * 0.5 / size; - double v = (dz + size) * 0.5 / size; - rotate(u, v); - double mapPoint = colorToHeight(texture.sample(sampler, u, v)); - posk.y = (int)floor(mapp + mapPoint * height); - posk.y = std::max(posk.y, (int)range.min); - posk.y = std::min(posk.y, (int)range.max - 1); - if (posk.y > originY) { - auto* block = &blockSource->getBlock({posk.x, originY, posk.z}); - for (int i = originY + 1; i <= posk.y; ++i) { - BlockPos iPos(posk.x, i, posk.z); - setFunction(variables, f, box, playerPos, iPos, center); - maskFunc(f, variables, [&]() mutable { - iter += - playerData.setBlockSimple(blockSource, f, variables, iPos,block); - }); - } - } else if (posk.y < originY) { - for (int i = posk.y; i <= originY; ++i) { - BlockPos iPos(posk.x, i, posk.z); - setFunction(variables, f, box, playerPos, iPos, center); - maskFunc(f, variables, - [&]() mutable { iter += playerData.setBlockSimple(blockSource, f, variables, iPos); }); - } + EvalFunctions f; + f.setbs(blockSource); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + auto playerPos = player->getPosition(); + + Vec3 center = pos.toVec3(); + + for (int dx = -size; dx <= size; dx++) + for (int dz = -size; dz <= size; dz++) { + auto posk = pos + BlockPos(dx, 0, dz); + double mapp = map[(dx + size) * (size * 2 + 1) + dz + size]; + int originY = (int)floor(mapp); + double u = (dx + size) * 0.5 / size; + double v = (dz + size) * 0.5 / size; + rotate(u, v); + double mapPoint = colorToHeight(texture.sample(sampler, u, v)); + posk.y = (int)floor(mapp + mapPoint * height); + posk.y = std::max(posk.y, (int)range.min); + posk.y = std::min(posk.y, (int)range.max - 1); + if (posk.y > originY) { + auto* block = &blockSource->getBlock({posk.x, originY, posk.z}); + for (int i = originY + 1; i <= posk.y; ++i) { + BlockPos iPos(posk.x, i, posk.z); + setFunction(variables, f, box, playerPos, iPos, center); + maskFunc(f, variables, [&]() mutable { + iter += + playerData + .setBlockSimple(blockSource, f, variables, iPos, block); + }); + } + } else if (posk.y < originY) { + for (int i = posk.y; i <= originY; ++i) { + BlockPos iPos(posk.x, i, posk.z); + setFunction(variables, f, box, playerPos, iPos, center); + maskFunc(f, variables, [&]() mutable { + iter += + playerData.setBlockSimple(blockSource, f, variables, iPos); + }); } } + } - return iter; - } -} // namespace worldedit \ No newline at end of file + return iter; +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/ImageHeightmapBrush.h b/old/core/brush/ImageHeightmapBrush.h index a011d4c..5d97048 100644 --- a/old/core/brush/ImageHeightmapBrush.h +++ b/old/core/brush/ImageHeightmapBrush.h @@ -1,17 +1,14 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" #include "image/Image.h" -namespace worldedit { - class ImageHeightmapBrush final : public Brush { - public: - int height = 0; - bool rotation; - Texture2D texture; - ImageHeightmapBrush(unsigned short, int, Texture2D const&, bool); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class ImageHeightmapBrush : public Brush { +public: + int height = 0; + bool rotation; + Texture2D texture; + ImageHeightmapBrush(unsigned short, int, Texture2D const&, bool); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/MixBrush.cpp b/old/core/brush/MixBrush.cpp index abbdd93..7f9a3a5 100644 --- a/old/core/brush/MixBrush.cpp +++ b/old/core/brush/MixBrush.cpp @@ -1,141 +1,155 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #pragma once -#include "Globals.h" #include "MixBrush.h" +#include "Globals.h" #include "WorldEdit.h" -#include "utils/ColorTool.h" -#include "mc/BlockSource.hpp" #include "mc/BlockInstance.hpp" +#include "mc/BlockSource.hpp" +#include "utils/ColorTool.h" -namespace worldedit { - MixBrush::MixBrush(unsigned short size, float density, float opacity, bool mixbox) - : Brush(size, nullptr), density(density), opacity(opacity), useMixboxLerp(mixbox) {} +namespace we { +MixBrush::MixBrush(unsigned short size, float density, float opacity, bool mixbox) +: Brush(size, nullptr), + density(density), + opacity(opacity), + useMixboxLerp(mixbox) {} - long long MixBrush::set(Player* player, BlockInstance blockInstance) { - long long iter = 0; - if (blockInstance == BlockInstance::Null) { - return -2; - } - std::queue q; - auto pos0 = blockInstance.getPosition(); - q.push(pos0); +long long MixBrush::set(Player* player, BlockInstance blockInstance) { + long long iter = 0; + if (blockInstance == BlockInstance::Null) { + return -2; + } + std::queue q; + auto pos0 = blockInstance.getPosition(); + q.push(pos0); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto blockSource = blockInstance.getBlockSource(); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto blockSource = blockInstance.getBlockSource(); - EvalFunctions f; - f.setbs(blockSource); - phmap::flat_hash_map variables; - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - variables["px"] = playerPos.x; - variables["py"] = playerPos.y; - variables["pz"] = playerPos.z; - variables["pp"] = playerRot.x; - variables["pt"] = playerRot.y; - phmap::flat_hash_set s; - s.insert(pos0); + EvalFunctions f; + f.setbs(blockSource); + phmap::flat_hash_map variables; + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + variables["px"] = playerPos.x; + variables["py"] = playerPos.y; + variables["pz"] = playerPos.z; + variables["pp"] = playerRot.x; + variables["pt"] = playerRot.y; + phmap::flat_hash_set s; + s.insert(pos0); - BoundingBox boundingBox = BoundingBox(pos0, pos0); + BoundingBox boundingBox = BoundingBox(pos0, pos0); - while (!q.empty()) { - auto pos1 = q.front(); - q.pop(); - boundingBox.merge(pos1); - BoundingBox(pos1 - 1, pos1 + 1).forEachBlockInBox([&](const BlockPos& tmpPos) { - if (&blockSource->getBlock(tmpPos) != BedrockBlocks::mAir && tmpPos != pos1 && - pos0.distanceTo(tmpPos) <= 0.5 + size && !s.contains(tmpPos)) { - int counts = 0; - for (auto& calPos : tmpPos.getNeighbors()) { - counts += !blockSource->getBlock(calPos).isSolid(); - } - if (counts > 0) { - q.push(tmpPos); - s.insert(tmpPos); - } + while (!q.empty()) { + auto pos1 = q.front(); + q.pop(); + boundingBox.merge(pos1); + BoundingBox(pos1 - 1, pos1 + 1).forEachBlockInBox([&](BlockPos const& tmpPos) { + if (&blockSource->getBlock(tmpPos) != BedrockBlocks::mAir && tmpPos != pos1 + && pos0.distanceTo(tmpPos) <= 0.5 + size && !s.contains(tmpPos)) { + int counts = 0; + for (auto& calPos : tmpPos.getNeighbors()) { + counts += !blockSource->getBlock(calPos).isSolid(); } - }); - } - - phmap::flat_hash_map bColor; - int totalColor = 0; - auto& cmap = getBlockColorMap(); - for (auto& pos1 : s) { - auto* block = &blockSource->getBlock(pos1); - if (cmap.contains(block)) { - auto& color = cmap[block]; - ++totalColor; - if (bColor.contains(color)) { - bColor[color] += 1; - } else { - bColor[color] = 1; + if (counts > 0) { + q.push(tmpPos); + s.insert(tmpPos); } } - } + }); + } - if (totalColor <= 0) { - return -2; + phmap::flat_hash_map bColor; + int totalColor = 0; + auto& cmap = getBlockColorMap(); + for (auto& pos1 : s) { + auto* block = &blockSource->getBlock(pos1); + if (cmap.contains(block)) { + auto& color = cmap[block]; + ++totalColor; + if (bColor.contains(color)) { + bColor[color] += 1; + } else { + bColor[color] = 1; + } } + } - mce::Color finalColor = useMixboxLerp ? mixboxAverage(bColor) : linearAverage(bColor); + if (totalColor <= 0) { + return -2; + } - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = blockInstance.getDimensionId(); - history.playerPos = boundingBox.min; - for (auto& pos1 : s) { - auto localPos = pos1 - boundingBox.min; - auto bi = blockSource->getBlockInstance(pos1); - history.storeBlock(bi, localPos); - } - } + mce::Color finalColor = useMixboxLerp ? mixboxAverage(bColor) : linearAverage(bColor); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = blockInstance.getDimensionId(); + history.playerPos = boundingBox.min; for (auto& pos1 : s) { - f.setPos(pos1); - variables["x"] = static_cast(pos1.x - pos0.x) / size; - variables["y"] = static_cast(pos1.y - pos0.y) / size; - variables["z"] = static_cast(pos1.z - pos0.z) / size; - variables["rx"] = pos1.x; - variables["ry"] = pos1.y; - variables["rz"] = pos1.z; - variables["cx"] = pos1.x - pos0.x; - variables["cy"] = pos1.y - pos0.y; - variables["cz"] = pos1.z - pos0.z; - variables["ox"] = pos1.x - playerPos.x; - variables["oy"] = pos1.y - playerPos.y; - variables["oz"] = pos1.z - playerPos.z; - maskFunc(f, variables, [&]() mutable { - auto* block =&blockSource->getBlock(pos1); - if (cmap.contains(block)) { - mce::Color hereColor = - useMixboxLerp - ? mixboxLerp( - cmap[block], finalColor, - smoothBrushAlpha(static_cast(pos1.distanceTo(pos0)), density, opacity, size)) - : linearLerp( - cmap[block], finalColor, - smoothBrushAlpha(static_cast(pos1.distanceTo(pos0)), density, opacity, size)); - double minDist = DBL_MAX; - Block const* minBlock = nullptr; - for (auto& i : getColorBlockMap()) { - if (i.first.a == 1) { - auto dst = i.first.distanceTo(hereColor); - if (dst < minDist) { - minDist = dst; - minBlock = i.second; - } + auto localPos = pos1 - boundingBox.min; + auto bi = blockSource->getBlockInstance(pos1); + history.storeBlock(bi, localPos); + } + } + + for (auto& pos1 : s) { + f.setPos(pos1); + variables["x"] = static_cast(pos1.x - pos0.x) / size; + variables["y"] = static_cast(pos1.y - pos0.y) / size; + variables["z"] = static_cast(pos1.z - pos0.z) / size; + variables["rx"] = pos1.x; + variables["ry"] = pos1.y; + variables["rz"] = pos1.z; + variables["cx"] = pos1.x - pos0.x; + variables["cy"] = pos1.y - pos0.y; + variables["cz"] = pos1.z - pos0.z; + variables["ox"] = pos1.x - playerPos.x; + variables["oy"] = pos1.y - playerPos.y; + variables["oz"] = pos1.z - playerPos.z; + maskFunc(f, variables, [&]() mutable { + auto* block = &blockSource->getBlock(pos1); + if (cmap.contains(block)) { + mce::Color hereColor = + useMixboxLerp ? mixboxLerp( + cmap[block], + finalColor, + smoothBrushAlpha( + static_cast(pos1.distanceTo(pos0)), + density, + opacity, + size + ) + ) + : linearLerp( + cmap[block], + finalColor, + smoothBrushAlpha( + static_cast(pos1.distanceTo(pos0)), + density, + opacity, + size + ) + ); + double minDist = DBL_MAX; + Block const* minBlock = nullptr; + for (auto& i : getColorBlockMap()) { + if (i.first.a == 1) { + auto dst = i.first.distanceTo(hereColor); + if (dst < minDist) { + minDist = dst; + minBlock = i.second; } } - iter += playerData.setBlockSimple(blockSource, f, variables, pos1, minBlock); } - }); - } - return iter; + iter += + playerData.setBlockSimple(blockSource, f, variables, pos1, minBlock); + } + }); } -} // namespace worldedit \ No newline at end of file + return iter; +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/MixBrush.h b/old/core/brush/MixBrush.h index 2518858..4c2089f 100644 --- a/old/core/brush/MixBrush.h +++ b/old/core/brush/MixBrush.h @@ -1,17 +1,14 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #pragma once #include "Brush.h" -namespace worldedit { - class MixBrush final : public Brush { - public: - float density = 1; - float opacity = 1; - bool useMixboxLerp = true; - MixBrush(unsigned short size, float density, float opacity, bool mixbox); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class MixBrush : public Brush { +public: + float density = 1; + float opacity = 1; + bool useMixboxLerp = true; + MixBrush(unsigned short size, float density, float opacity, bool mixbox); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/SmoothBrush.cpp b/old/core/brush/SmoothBrush.cpp index c3aa046..5971cb1 100644 --- a/old/core/brush/SmoothBrush.cpp +++ b/old/core/brush/SmoothBrush.cpp @@ -1,78 +1,87 @@ -// -// Created by OEOTYAN on 2022/06/10. -// -#include "Globals.h" #include "SmoothBrush.h" -#include "utils/ColorTool.h" -#include "store/Patterns.h" +#include "Globals.h" #include "WorldEdit.h" +#include "eval/blur.hpp" #include "mc/Dimension.hpp" #include "region/CuboidRegion.h" -#include "eval/blur.hpp" +#include "store/Patterns.h" +#include "utils/ColorTool.h" -namespace worldedit { - SmoothBrush::SmoothBrush(unsigned short s, int a, float d) : Brush(s, nullptr), ksize(a), density(d) {} - long long SmoothBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto pos = blockInstance.getPosition(); +namespace we { +SmoothBrush::SmoothBrush(unsigned short s, int a, float d) +: Brush(s, nullptr), + ksize(a), + density(d) {} +long long SmoothBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; + } + auto pos = blockInstance.getPosition(); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto dimID = player->getDimensionId(); - auto blockSource = &player->getDimensionBlockSource(); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto dimID = player->getDimensionId(); + auto blockSource = &player->getDimensionBlockSource(); - BoundingBox box(pos - size, pos + size); - box.min.y = pos.y; - box.max.y = pos.y; + BoundingBox box(pos - size, pos + size); + box.min.y = pos.y; + box.max.y = pos.y; - int sizex = box.max.x - box.min.x + 1; - int sizez = box.max.z - box.min.z + 1; - std::vector heightMap(sizex * sizez, -1e200); - auto range = - reinterpret_cast(Global->getDimension(dimID).mHandle.lock().get())->getHeightRange(); - for (int x = box.min.x; x <= box.max.x; ++x) - for (int z = box.min.z; z <= box.max.z; ++z) { - auto topy = getHighestTerrainBlock(blockSource, x, z, range.min, range.max, mask); - if (topy >= range.min && topy <= range.max) { - int cx = x - box.min.x; - int cz = z - box.min.z; - heightMap[cx * sizez + cz] = topy + 0.5; - box.merge(BlockPos(x, topy, z)); - } + int sizex = box.max.x - box.min.x + 1; + int sizez = box.max.z - box.min.z + 1; + std::vector heightMap(sizex * sizez, -1e200); + auto range = reinterpret_cast( + Global->getDimension(dimID).mHandle.lock().get() + ) + ->getHeightRange(); + for (int x = box.min.x; x <= box.max.x; ++x) + for (int z = box.min.z; z <= box.max.z; ++z) { + auto topy = + getHighestTerrainBlock(blockSource, x, z, range.min, range.max, mask); + if (topy >= range.min && topy <= range.max) { + int cx = x - box.min.x; + int cz = z - box.min.z; + heightMap[cx * sizez + cz] = topy + 0.5; + box.merge(BlockPos(x, topy, z)); } - box.min.y = std::max(static_cast(range.min), box.min.y - 1); - box.max.y = std::min(static_cast(range.max), box.max.y + 1); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dimID; - history.playerPos = box.min; - box.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - box.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); } + box.min.y = std::max(static_cast(range.min), box.min.y - 1); + box.max.y = std::min(static_cast(range.max), box.max.y + 1); - auto smoothedHeightMap = blur2D(heightMap, ksize, sizex, sizez); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dimID; + history.playerPos = box.min; + box.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - box.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - for (int x = box.min.x; x <= box.max.x; ++x) - for (int z = box.min.z; z <= box.max.z; ++z) { - int cx = x - box.min.x; - int cz = z - box.min.z; - smoothedHeightMap[cx * sizez + cz] = - std::lerp(heightMap[cx * sizez + cz], smoothedHeightMap[cx * sizez + cz], - static_cast(smoothBrushAlpha( - static_cast(sqrt(pow2(x - pos.x) + pow2(z - pos.z))), density, 1, size))); - } + auto smoothedHeightMap = blur2D(heightMap, ksize, sizex, sizez); - CuboidRegion(box, dimID).applyHeightMap(smoothedHeightMap, xuid, mask); + for (int x = box.min.x; x <= box.max.x; ++x) + for (int z = box.min.z; z <= box.max.z; ++z) { + int cx = x - box.min.x; + int cz = z - box.min.z; + smoothedHeightMap[cx * sizez + cz] = std::lerp( + heightMap[cx * sizez + cz], + smoothedHeightMap[cx * sizez + cz], + static_cast(smoothBrushAlpha( + static_cast(sqrt(pow2(x - pos.x) + pow2(z - pos.z))), + density, + 1, + size + )) + ); + } - return -2; - } + CuboidRegion(box, dimID).applyHeightMap(smoothedHeightMap, xuid, mask); + + return -2; +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/brush/SmoothBrush.h b/old/core/brush/SmoothBrush.h index 008d137..f6dfc51 100644 --- a/old/core/brush/SmoothBrush.h +++ b/old/core/brush/SmoothBrush.h @@ -1,15 +1,12 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" -namespace worldedit { - class SmoothBrush final : public Brush { - public: - float density = 1; - int ksize = 0; - SmoothBrush(unsigned short, int, float); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class SmoothBrush : public Brush { +public: + float density = 1; + int ksize = 0; + SmoothBrush(unsigned short, int, float); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/SphereBrush.cpp b/old/core/brush/SphereBrush.cpp index 4618e0a..eaa6b62 100644 --- a/old/core/brush/SphereBrush.cpp +++ b/old/core/brush/SphereBrush.cpp @@ -1,18 +1,23 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "SphereBrush.h" #include "builder/SimpleBuilder.h" #include "store/Patterns.h" -namespace worldedit { - SphereBrush::SphereBrush(unsigned short s, std::unique_ptr bp, bool a) - : Brush(s, std::move(bp)), hollow(a) {} - long long SphereBrush::set(Player* player, BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - return SimpleBuilder::buildSphere(blockInstance.getPosition(), blockInstance.getDimensionId(), - player->getXuid(), pattern.get(), size, hollow, mask); +namespace we { +SphereBrush::SphereBrush(unsigned short s, std::unique_ptr bp, bool a) +: Brush(s, std::move(bp)), + hollow(a) {} +long long SphereBrush::set(Player* player, BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; } -} // namespace worldedit \ No newline at end of file + return SimpleBuilder::buildSphere( + blockInstance.getPosition(), + blockInstance.getDimensionId(), + player->getXuid(), + pattern.get(), + size, + hollow, + mask + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/brush/SphereBrush.h b/old/core/brush/SphereBrush.h index 767b167..2f60957 100644 --- a/old/core/brush/SphereBrush.h +++ b/old/core/brush/SphereBrush.h @@ -1,14 +1,11 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #pragma once #include "Brush.h" -namespace worldedit { - class SphereBrush final : public Brush { - public: - bool hollow = false; - SphereBrush(unsigned short, std::unique_ptr, bool); - long long set(Player* player, BlockInstance blockInstance) override; - }; -} // namespace worldedit +namespace we { +class SphereBrush : public Brush { +public: + bool hollow = false; + SphereBrush(unsigned short, std::unique_ptr, bool); + long long set(Player* player, BlockInstance blockInstance) override; +}; +} // namespace we diff --git a/old/core/brush/tool.cpp b/old/core/brush/tool.cpp index a625ed0..fa45ef6 100644 --- a/old/core/brush/tool.cpp +++ b/old/core/brush/tool.cpp @@ -1,182 +1,190 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "tool.h" -#include "utils/StringTool.h" #include "WorldEdit.h" #include "mc/BlockInstance.hpp" #include "store/Patterns.h" -namespace worldedit { +#include "utils/StringTool.h" +namespace we { - //////// - long long FarWand::lset(Player* player, class BlockInstance blockInstance) { - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - playerData.changeMainPos(blockInstance); - return -2; - } - long long FarWand::set(Player* player, class BlockInstance blockInstance) { - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - playerData.changeVicePos(blockInstance); - return -2; - } +//////// +long long FarWand::lset(Player* player, class BlockInstance blockInstance) { + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + playerData.changeMainPos(blockInstance); + return -2; +} +long long FarWand::set(Player* player, class BlockInstance blockInstance) { + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + playerData.changeVicePos(blockInstance); + return -2; +} + +//////// +long long AirWand::lset(Player* player, class BlockInstance blockInstance) { + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto bs = Level::getBlockSource(player); + playerData.changeMainPos(bs->getBlockInstance(player->getBlockPos())); + return -2; +} +long long AirWand::set(Player* player, class BlockInstance blockInstance) { + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto bs = Level::getBlockSource(player); + playerData.changeVicePos(bs->getBlockInstance(player->getBlockPos())); + return -2; +} - //////// - long long AirWand::lset(Player* player, class BlockInstance blockInstance) { - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto bs = Level::getBlockSource(player); - playerData.changeMainPos(bs->getBlockInstance(player->getBlockPos())); +//////// +long long InfoTool::set(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } - long long AirWand::set(Player* player, class BlockInstance blockInstance) { - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto bs = Level::getBlockSource(player); - playerData.changeVicePos(bs->getBlockInstance(player->getBlockPos())); - return -2; + auto block = blockInstance.getBlock(); + auto exblock = &const_cast( + blockInstance.getBlockSource()->getExtraBlock(blockInstance.getPosition()) + ); + std::cout << "block: (" << getBlockId(block->getTypeName()) << ":" + << block->getTileData() << ") " << block->getRuntimeId() << "\n" + << block->getNbt()->toPrettySNBT() << std::endl; + player->sendText( + "block: (" + fto_string(getBlockId(block->getTypeName())) + ":" + + fto_string(block->getTileData()) + ") " + fto_string(block->getRuntimeId()) + + "\n" + block->getNbt()->toPrettySNBT(true) + ); + if (exblock != BedrockBlocks::mAir) { + std::cout << "exBlock: (" << getBlockId(exblock->getTypeName()) << ":" + << exblock->getTileData() << ") " << exblock->getRuntimeId() << "\n" + << exblock->getNbt()->toPrettySNBT() << std::endl; + player->sendText( + "exBlock: (" + fto_string(getBlockId(exblock->getTypeName())) + ":" + + fto_string(exblock->getTileData()) + ") " + + fto_string(exblock->getRuntimeId()) + "\n" + + exblock->getNbt()->toPrettySNBT(true) + ); } - - //////// - long long InfoTool::set(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto block = blockInstance.getBlock(); - auto exblock = &const_cast(blockInstance.getBlockSource()->getExtraBlock(blockInstance.getPosition())); - std::cout << "block: (" << getBlockId(block->getTypeName()) << ":" << block->getTileData() << ") " - << block->getRuntimeId() << "\n" - << block->getNbt()->toPrettySNBT() << std::endl; - player->sendText("block: (" + fto_string(getBlockId(block->getTypeName())) + ":" + - fto_string(block->getTileData()) + ") " + fto_string(block->getRuntimeId()) + "\n" + - block->getNbt()->toPrettySNBT(true)); - if (exblock != BedrockBlocks::mAir) { - std::cout << "exBlock: (" << getBlockId(exblock->getTypeName()) << ":" << exblock->getTileData() << ") " - << exblock->getRuntimeId() << "\n" - << exblock->getNbt()->toPrettySNBT() << std::endl; - player->sendText("exBlock: (" + fto_string(getBlockId(exblock->getTypeName())) + ":" + - fto_string(exblock->getTileData()) + ") " + fto_string(exblock->getRuntimeId()) + "\n" + - exblock->getNbt()->toPrettySNBT(true)); + if (blockInstance.hasBlockEntity()) { + auto be = blockInstance.getBlockEntity(); + if (be != nullptr) { + std::cout << "blockEntity:\n" << be->getNbt()->toPrettySNBT() << std::endl; + player->sendText("blockEntity:\n" + be->getNbt()->toPrettySNBT(true)); + } else { + std::cout << "blockEntity: null" << std::endl; + player->sendText("blockEntity: null"); } - if (blockInstance.hasBlockEntity()) { - auto be = blockInstance.getBlockEntity(); - if (be != nullptr) { - std::cout << "blockEntity:\n" << be->getNbt()->toPrettySNBT() << std::endl; - player->sendText("blockEntity:\n" + be->getNbt()->toPrettySNBT(true)); - } else { - std::cout << "blockEntity: null" << std::endl; - player->sendText("blockEntity: null"); - } - } - return -2; } + return -2; +} - //////// - long long CyclerTool::lset(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } +//////// +long long CyclerTool::lset(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } - long long CyclerTool::set(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } + return -2; +} +long long CyclerTool::set(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } + return -2; +} - //////// - long long RepTool::lset(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - blockSet = std::move(BlockNBTSet(blockInstance)); +//////// +long long RepTool::lset(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } - long long RepTool::set(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - auto blockSource = blockInstance.getBlockSource(); - auto bpos = blockInstance.getPosition(); + blockSet = std::move(BlockNBTSet(blockInstance)); + return -2; +} +long long RepTool::set(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { + return -2; + } + auto blockSource = blockInstance.getBlockSource(); + auto bpos = blockInstance.getPosition(); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); - EvalFunctions f; - f.setbs(blockSource); - phmap::flat_hash_map variables; + EvalFunctions f; + f.setbs(blockSource); + phmap::flat_hash_map variables; - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(BlockPos(0, 0, 0))); - history.playerRelPos.x = blockInstance.getDimensionId(); - history.playerPos = bpos; - history.storeBlock(blockInstance, BlockPos(0, 0, 0)); - } - f.setPos(bpos); - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - variables["rx"] = bpos.x; - variables["ry"] = bpos.y; - variables["rz"] = bpos.z; - variables["px"] = playerPos.x; - variables["py"] = playerPos.y; - variables["pz"] = playerPos.z; - variables["pp"] = playerRot.x; - variables["pt"] = playerRot.y; - variables["ox"] = bpos.x - playerPos.x; - variables["oy"] = bpos.y - playerPos.y; - variables["oz"] = bpos.z - playerPos.z; - maskFunc(f, variables, [&]() mutable { blockSet.setBlock(bpos, blockSource, playerData, f, variables); }); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(BlockPos(0, 0, 0))); + history.playerRelPos.x = blockInstance.getDimensionId(); + history.playerPos = bpos; + history.storeBlock(blockInstance, BlockPos(0, 0, 0)); + } + f.setPos(bpos); + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + variables["rx"] = bpos.x; + variables["ry"] = bpos.y; + variables["rz"] = bpos.z; + variables["px"] = playerPos.x; + variables["py"] = playerPos.y; + variables["pz"] = playerPos.z; + variables["pp"] = playerRot.x; + variables["pt"] = playerRot.y; + variables["ox"] = bpos.x - playerPos.x; + variables["oy"] = bpos.y - playerPos.y; + variables["oz"] = bpos.z - playerPos.z; + maskFunc(f, variables, [&]() mutable { + blockSet.setBlock(bpos, blockSource, playerData, f, variables); + }); + + return -2; +} +long long FloodFillTool::set(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } + std::queue q; + auto pos0 = blockInstance.getPosition(); + q.push(pos0); - long long FloodFillTool::set(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } - std::queue q; - auto pos0 = blockInstance.getPosition(); - q.push(pos0); - - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto blockSource = blockInstance.getBlockSource(); - Block const* block = blockInstance.getBlock(); - Block const* exBlock = &blockSource->getExtraBlock(pos0); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto blockSource = blockInstance.getBlockSource(); + Block const* block = blockInstance.getBlock(); + Block const* exBlock = &blockSource->getExtraBlock(pos0); - EvalFunctions f; - f.setbs(blockSource); - phmap::flat_hash_map variables; - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - variables["px"] = playerPos.x; - variables["py"] = playerPos.y; - variables["pz"] = playerPos.z; - variables["pp"] = playerRot.x; - variables["pt"] = playerRot.y; - phmap::flat_hash_set s; - s.insert(pos0); + EvalFunctions f; + f.setbs(blockSource); + phmap::flat_hash_map variables; + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + variables["px"] = playerPos.x; + variables["py"] = playerPos.y; + variables["pz"] = playerPos.z; + variables["pp"] = playerRot.x; + variables["pt"] = playerRot.y; + phmap::flat_hash_set s; + s.insert(pos0); - BoundingBox boundingBox = BoundingBox(pos0, pos0); + BoundingBox boundingBox = BoundingBox(pos0, pos0); - while (!q.empty()) { - auto pos1 = q.front(); - q.pop(); - boundingBox.merge(pos1); - if (needEdge) { - BoundingBox(pos1 - 1, pos1 + 1).forEachBlockInBox([&](const BlockPos& tmpPos) { - if (tmpPos != pos1 && pos0.distanceTo(tmpPos) <= 0.5 + size && - (&blockSource->getBlock(tmpPos) == block && &blockSource->getExtraBlock(tmpPos) == exBlock) && - s.find(tmpPos) == s.end()) { + while (!q.empty()) { + auto pos1 = q.front(); + q.pop(); + boundingBox.merge(pos1); + if (needEdge) { + BoundingBox(pos1 - 1, pos1 + 1) + .forEachBlockInBox([&](BlockPos const& tmpPos) { + if (tmpPos != pos1 && pos0.distanceTo(tmpPos) <= 0.5 + size + && (&blockSource->getBlock(tmpPos) == block + && &blockSource->getExtraBlock(tmpPos) == exBlock) + && s.find(tmpPos) == s.end()) { f.setPos(tmpPos); - variables["x"] = static_cast(tmpPos.x - pos0.x) / size; - variables["y"] = static_cast(tmpPos.y - pos0.y) / size; - variables["z"] = static_cast(tmpPos.z - pos0.z) / size; + variables["x"] = static_cast(tmpPos.x - pos0.x) / size; + variables["y"] = static_cast(tmpPos.y - pos0.y) / size; + variables["z"] = static_cast(tmpPos.z - pos0.z) / size; variables["rx"] = tmpPos.x; variables["ry"] = tmpPos.y; variables["rz"] = tmpPos.z; @@ -192,91 +200,92 @@ namespace worldedit { }); } }); - } else { - for (auto& tmpPos : pos1.getNeighbors()) { - if (pos0.distanceTo(tmpPos) <= 0.5 + size && - (&blockSource->getBlock(tmpPos) == block && &blockSource->getExtraBlock(tmpPos) == exBlock) && - s.find(tmpPos) == s.end()) { - f.setPos(tmpPos); - variables["x"] = static_cast(tmpPos.x - pos0.x) / size; - variables["y"] = static_cast(tmpPos.y - pos0.y) / size; - variables["z"] = static_cast(tmpPos.z - pos0.z) / size; - variables["rx"] = tmpPos.x; - variables["ry"] = tmpPos.y; - variables["rz"] = tmpPos.z; - variables["cx"] = tmpPos.x - pos0.x; - variables["cy"] = tmpPos.y - pos0.y; - variables["cz"] = tmpPos.z - pos0.z; - variables["ox"] = tmpPos.x - playerPos.x; - variables["oy"] = tmpPos.y - playerPos.y; - variables["oz"] = tmpPos.z - playerPos.z; - maskFunc(f, variables, [&]() mutable { - q.push(tmpPos); - s.insert(tmpPos); - }); - } + } else { + for (auto& tmpPos : pos1.getNeighbors()) { + if (pos0.distanceTo(tmpPos) <= 0.5 + size + && (&blockSource->getBlock(tmpPos) == block + && &blockSource->getExtraBlock(tmpPos) == exBlock) + && s.find(tmpPos) == s.end()) { + f.setPos(tmpPos); + variables["x"] = static_cast(tmpPos.x - pos0.x) / size; + variables["y"] = static_cast(tmpPos.y - pos0.y) / size; + variables["z"] = static_cast(tmpPos.z - pos0.z) / size; + variables["rx"] = tmpPos.x; + variables["ry"] = tmpPos.y; + variables["rz"] = tmpPos.z; + variables["cx"] = tmpPos.x - pos0.x; + variables["cy"] = tmpPos.y - pos0.y; + variables["cz"] = tmpPos.z - pos0.z; + variables["ox"] = tmpPos.x - playerPos.x; + variables["oy"] = tmpPos.y - playerPos.y; + variables["oz"] = tmpPos.z - playerPos.z; + maskFunc(f, variables, [&]() mutable { + q.push(tmpPos); + s.insert(tmpPos); + }); } } } + } - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = blockInstance.getDimensionId(); - history.playerPos = boundingBox.min; - for (auto& pos1 : s) { - auto localPos = pos1 - boundingBox.min; - auto bi = blockSource->getBlockInstance(pos1); - history.storeBlock(bi, localPos); - } - } - + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = blockInstance.getDimensionId(); + history.playerPos = boundingBox.min; for (auto& pos1 : s) { - f.setPos(pos1); - variables["x"] = static_cast(pos1.x - pos0.x) / size; - variables["y"] = static_cast(pos1.y - pos0.y) / size; - variables["z"] = static_cast(pos1.z - pos0.z) / size; - variables["rx"] = pos1.x; - variables["ry"] = pos1.y; - variables["rz"] = pos1.z; - variables["cx"] = pos1.x - pos0.x; - variables["cy"] = pos1.y - pos0.y; - variables["cz"] = pos1.z - pos0.z; - variables["ox"] = pos1.x - playerPos.x; - variables["oy"] = pos1.y - playerPos.y; - variables["oz"] = pos1.z - playerPos.z; - pattern->setBlock(variables, f, blockSource, pos1); + auto localPos = pos1 - boundingBox.min; + auto bi = blockSource->getBlockInstance(pos1); + history.storeBlock(bi, localPos); } + } - return -2; + for (auto& pos1 : s) { + f.setPos(pos1); + variables["x"] = static_cast(pos1.x - pos0.x) / size; + variables["y"] = static_cast(pos1.y - pos0.y) / size; + variables["z"] = static_cast(pos1.z - pos0.z) / size; + variables["rx"] = pos1.x; + variables["ry"] = pos1.y; + variables["rz"] = pos1.z; + variables["cx"] = pos1.x - pos0.x; + variables["cy"] = pos1.y - pos0.y; + variables["cz"] = pos1.z - pos0.z; + variables["ox"] = pos1.x - playerPos.x; + variables["oy"] = pos1.y - playerPos.y; + variables["oz"] = pos1.z - playerPos.z; + pattern->setBlock(variables, f, blockSource, pos1); } - //////// - long long TreeTool::set(Player* player, class BlockInstance blockInstance) { - // if (blockInstance == BlockInstance::Null) { - // - return -2; - // } - // auto bs = Level::getBlockSource(player); - // auto pos = blockInstance.getPosition(); - // setBlockSimple(bs, pos, - // StaticVanillaBlocks::mGrass); pos.y += 1; - // setBlockSimple(bs, pos, - // StaticVanillaBlocks::mSapling); auto& legacyBlock - // = blockInstance.getBlock()->getLegacyBlock(); return - // ((Sapling&)legacyBlock)._growTree(*bs, pos, - // Global->getRandom(), false); + return -2; +} - return -2; - } +//////// +long long TreeTool::set(Player* player, class BlockInstance blockInstance) { + // if (blockInstance == BlockInstance::Null) { + // + return -2; + // } + // auto bs = Level::getBlockSource(player); + // auto pos = blockInstance.getPosition(); + // setBlockSimple(bs, pos, + // StaticVanillaBlocks::mGrass); pos.y += 1; + // setBlockSimple(bs, pos, + // StaticVanillaBlocks::mSapling); auto& legacyBlock + // = blockInstance.getBlock()->getLegacyBlock(); return + // ((Sapling&)legacyBlock)._growTree(*bs, pos, + // Global->getRandom(), false); - //////// - long long DelTreeTool::set(Player* player, class BlockInstance blockInstance) { - if (blockInstance == BlockInstance::Null) { - return -2; - } + return -2; +} +//////// +long long DelTreeTool::set(Player* player, class BlockInstance blockInstance) { + if (blockInstance == BlockInstance::Null) { return -2; } -} // namespace worldedit \ No newline at end of file + return -2; +} + +} // namespace we \ No newline at end of file diff --git a/old/core/brush/tool.h b/old/core/brush/tool.h index 55ccae3..c6d5566 100644 --- a/old/core/brush/tool.h +++ b/old/core/brush/tool.h @@ -1,66 +1,64 @@ -// -// Created by OEOTYAN on 2022/05/30. -// #pragma once #ifndef WORLDEDIT_TOOL_H #define WORLDEDIT_TOOL_H #include "Brush.h" -#include -#include +#include "store/BlockNBTSet.hpp" #include +#include #include -#include "store/BlockNBTSet.hpp" +#include -namespace worldedit { - class FarWand final : public Brush { - public: - FarWand() = default; - long long lset(Player* player, class BlockInstance blockInstance) override; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class AirWand final : public Brush { - public: - AirWand() = default; - long long lset(Player* player, class BlockInstance blockInstance) override; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class InfoTool final : public Brush { - public: - InfoTool() = default; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class CyclerTool final : public Brush { - public: - CyclerTool() = default; - long long lset(Player* player, class BlockInstance blockInstance) override; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class FloodFillTool final : public Brush { - public: - bool needEdge; - FloodFillTool(std::unique_ptr bp, unsigned short r, bool needEdge) - : Brush(r, std::move(bp)), needEdge(needEdge) {} - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class RepTool final : public Brush { - public: - class BlockNBTSet blockSet; - RepTool() = default; - long long lset(Player* player, class BlockInstance blockInstance) override; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class TreeTool final : public Brush { - public: - TreeTool() = default; - long long set(Player* player, class BlockInstance blockInstance) override; - }; - class DelTreeTool final : public Brush { - public: - DelTreeTool() = default; - long long set(Player* player, class BlockInstance blockInstance) override; - }; +namespace we { +class FarWand : public Brush { +public: + FarWand() = default; + long long lset(Player* player, class BlockInstance blockInstance) override; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class AirWand : public Brush { +public: + AirWand() = default; + long long lset(Player* player, class BlockInstance blockInstance) override; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class InfoTool : public Brush { +public: + InfoTool() = default; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class CyclerTool : public Brush { +public: + CyclerTool() = default; + long long lset(Player* player, class BlockInstance blockInstance) override; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class FloodFillTool : public Brush { +public: + bool needEdge; + FloodFillTool(std::unique_ptr bp, unsigned short r, bool needEdge) + : Brush(r, std::move(bp)), + needEdge(needEdge) {} + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class RepTool : public Brush { +public: + class BlockNBTSet blockSet; + RepTool() = default; + long long lset(Player* player, class BlockInstance blockInstance) override; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class TreeTool : public Brush { +public: + TreeTool() = default; + long long set(Player* player, class BlockInstance blockInstance) override; +}; +class DelTreeTool : public Brush { +public: + DelTreeTool() = default; + long long set(Player* player, class BlockInstance blockInstance) override; +}; -} // namespace worldedit +} // namespace we -#endif // WORLDEDIT_TOOL_H \ No newline at end of file +#endif // WORLDEDIT_TOOL_H \ No newline at end of file diff --git a/old/core/builder/SimpleBuilder.cpp b/old/core/builder/SimpleBuilder.cpp index e79a451..cfef50c 100644 --- a/old/core/builder/SimpleBuilder.cpp +++ b/old/core/builder/SimpleBuilder.cpp @@ -1,295 +1,316 @@ -// -// Created by OEOTYAN on 2022/06/10. -// -#include "Globals.h" -#include "mc/BlockPos.hpp" -#include #include "SimpleBuilder.h" +#include "Globals.h" #include "WorldEdit.h" -#include #include "eval/Eval.h" +#include "mc/BlockPos.hpp" #include "store/Patterns.h" -namespace worldedit { +#include +#include +namespace we { - long long SimpleBuilder::buildCylinder(BlockPos pos, - int dim, - std::string xuid, - Pattern* pattern, - unsigned short radius, - int height, - bool hollow, - std::string mask) { - if (height == 0) { - return -1; - } else if (height < 0) { - pos.y += height; - height = -height; - } - auto range = - reinterpret_cast(Global->getDimension(dim).mHandle.lock().get())->getHeightRange(); +long long SimpleBuilder::buildCylinder( + BlockPos pos, + int dim, + std::string xuid, + Pattern* pattern, + unsigned short radius, + int height, + bool hollow, + std::string mask +) { + if (height == 0) { + return -1; + } else if (height < 0) { + pos.y += height; + height = -height; + } + auto range = + reinterpret_cast(Global->getDimension(dim).mHandle.lock().get() + ) + ->getHeightRange(); - if (pos.y < range.min) { - pos.y = range.min; - } else if (pos.y + height - 1 > range.max) { - height = range.max - pos.y + 1; - } - BoundingBox box({pos.x - radius, pos.y, pos.z - radius}, {pos.x + radius, pos.y + height, pos.z + radius}); - long long i = 0; + if (pos.y < range.min) { + pos.y = range.min; + } else if (pos.y + height - 1 > range.max) { + height = range.max - pos.y + 1; + } + BoundingBox box( + {pos.x - radius, pos.y, pos.z - radius}, + {pos.x + radius, pos.y + height, pos.z + radius} + ); + long long i = 0; - auto& playerData = getPlayersData(xuid); - auto blockSource = Level::getBlockSource(dim); + auto& playerData = getPlayersData(xuid); + auto blockSource = Level::getBlockSource(dim); - std::function const&, - std::function const&)> - maskLambda; - if (mask != "") { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { - if (cpp_eval::eval(mask, var, func) > 0.5) { - todo(); - } - }; - } else { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { todo(); }; - } + std::function< + void(EvalFunctions&, phmap::flat_hash_map const&, std::function const&)> + maskLambda; + if (mask != "") { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { + if (cpp_eval::eval(mask, var, func) > 0.5) { + todo(); + } + }; + } else { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { todo(); }; + } + + auto* player = Global->getPlayer(xuid); + + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + EvalFunctions f; + f.setbs(blockSource); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - auto* player = Global->getPlayer(xuid); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dim; + history.playerPos = box.min; - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - EvalFunctions f; - f.setbs(blockSource); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + box.forEachBlockInBox([&](BlockPos const& blockPos) { + auto localPos = blockPos - box.min; + auto blockInstance = blockSource->getBlockInstance(blockPos); + history.storeBlock(blockInstance, localPos); + }); + } + + double R = radius; + R += 0.5; + int X, Y, p; + X = 0; + Y = (int)R; + p = (int)(3 - 2 * R); - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dim; - history.playerPos = box.min; + phmap::flat_hash_set bset; - box.forEachBlockInBox([&](const BlockPos& blockPos) { - auto localPos = blockPos - box.min; - auto blockInstance = blockSource->getBlockInstance(blockPos); - history.storeBlock(blockInstance, localPos); + for (; X <= Y; X++) { + int k = hollow ? Y : X; + for (int Yi = k; Yi <= Y; Yi++) { + BlockPos blockPos = pos; + blockPos += {X, 0, Yi}; + bset.insert(blockPos); + blockPos.z = pos.z - Yi; + bset.insert(blockPos); + blockPos.x = pos.x - X; + bset.insert(blockPos); + blockPos.z = pos.z + Yi; + bset.insert(blockPos); + blockPos.x = pos.x + Yi; + blockPos.z = pos.z + X; + bset.insert(blockPos); + blockPos.z = pos.z - X; + bset.insert(blockPos); + blockPos.x = pos.x - Yi; + bset.insert(blockPos); + blockPos.z = pos.z + X; + bset.insert(blockPos); + } + if (p >= 0) { + p += 4 * (X - Y) + 10; + Y--; + } else { + p += 4 * X + 6; + } + } + for (auto b : bset) + for (int y = 0; y < height; y++) { + setFunction(variables, f, box, playerPos, b, pos.toVec3() + 0.5f); + maskLambda(f, variables, [&]() mutable { + i += pattern->setBlock(variables, f, blockSource, b); }); + b.y += 1; } - double R = radius; - R += 0.5; - int X, Y, p; - X = 0; - Y = (int)R; - p = (int)(3 - 2 * R); + return i; +} + +long long SimpleBuilder::buildSphere( + BlockPos pos, + int dim, + std::string xuid, + Pattern* pattern, + unsigned short radius, + bool hollow, + std::string mask +) { + BoundingBox box(pos - radius, pos + radius); + long long i = 0; + + auto& playerData = getPlayersData(xuid); + auto blockSource = Level::getBlockSource(dim); + + std::function< + void(EvalFunctions&, phmap::flat_hash_map const&, std::function const&)> + maskLambda; + if (mask != "") { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { + if (cpp_eval::eval(mask, var, func) > 0.5) { + todo(); + } + }; + } else { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { todo(); }; + } + + auto* player = Global->getPlayer(xuid); + + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + EvalFunctions f; + f.setbs(blockSource); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dim; + history.playerPos = box.min; + + box.forEachBlockInBox([&](BlockPos const& blockPos) { + auto localPos = blockPos - box.min; + auto blockInstance = blockSource->getBlockInstance(blockPos); + history.storeBlock(blockInstance, localPos); + }); + } - phmap::flat_hash_set bset; + phmap::flat_hash_set bset; + double R = radius + 0.5; + double nextXn = 0; + for (int x = 0; x <= radius; ++x) { + double xn = nextXn; + nextXn = (x + 1) / R; + double nextYn = 0; + for (int y = 0; y <= radius; ++y) { + double yn = nextYn; + nextYn = (y + 1) / R; + double nextZn = 0; + for (int z = 0; z <= radius; ++z) { + double zn = nextZn; + nextZn = (z + 1) / R; + if (xn * xn + yn * yn + zn * zn > 1) { + continue; + } + if (hollow) { + if (nextXn * nextXn + yn * yn + zn * zn <= 1 + && xn * xn + nextYn * nextYn + zn * zn <= 1 + && xn * xn + yn * yn + nextZn * nextZn <= 1) { + continue; + } + } - for (; X <= Y; X++) { - int k = hollow ? Y : X; - for (int Yi = k; Yi <= Y; Yi++) { - BlockPos blockPos = pos; - blockPos += {X, 0, Yi}; + BlockPos blockPos = pos; + blockPos += {x, y, z}; bset.insert(blockPos); - blockPos.z = pos.z - Yi; + blockPos.y = pos.y - y; bset.insert(blockPos); - blockPos.x = pos.x - X; + blockPos.z = pos.z - z; bset.insert(blockPos); - blockPos.z = pos.z + Yi; + blockPos.x = pos.x - x; bset.insert(blockPos); - blockPos.x = pos.x + Yi; - blockPos.z = pos.z + X; + blockPos.y = pos.y + y; bset.insert(blockPos); - blockPos.z = pos.z - X; + blockPos.x = pos.x + x; bset.insert(blockPos); - blockPos.x = pos.x - Yi; + blockPos.x = pos.x - x; + blockPos.z = pos.z + z; bset.insert(blockPos); - blockPos.z = pos.z + X; + blockPos.y = pos.y - y; bset.insert(blockPos); } - if (p >= 0) { - p += 4 * (X - Y) + 10; - Y--; - } else { - p += 4 * X + 6; - } } - for (auto b : bset) - for (int y = 0; y < height; y++) { - setFunction(variables, f, box, playerPos, b, pos.toVec3() + 0.5f); - maskLambda(f, variables, [&]() mutable { i += pattern->setBlock(variables, f, blockSource, b); }); - b.y += 1; - } - - return i; } + for (auto& b : bset) { + setFunction(variables, f, box, playerPos, b, pos.toVec3() + 0.5f); + maskLambda(f, variables, [&]() mutable { + i += pattern->setBlock(variables, f, blockSource, b); + }); + } + return i; +} - long long SimpleBuilder::buildSphere(BlockPos pos, - int dim, - std::string xuid, - Pattern* pattern, - unsigned short radius, - bool hollow, - std::string mask) { - BoundingBox box(pos - radius, pos + radius); - long long i = 0; - - auto& playerData = getPlayersData(xuid); - auto blockSource = Level::getBlockSource(dim); - - std::function const&, - std::function const&)> - maskLambda; - if (mask != "") { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { - if (cpp_eval::eval(mask, var, func) > 0.5) { - todo(); - } - }; - } else { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { todo(); }; - } - - auto* player = Global->getPlayer(xuid); - - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - EvalFunctions f; - f.setbs(blockSource); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dim; - history.playerPos = box.min; - - box.forEachBlockInBox([&](const BlockPos& blockPos) { - auto localPos = blockPos - box.min; - auto blockInstance = blockSource->getBlockInstance(blockPos); - history.storeBlock(blockInstance, localPos); - }); - } +long long SimpleBuilder::buildCube( + BlockPos pos, + int dim, + std::string xuid, + Pattern* pattern, + unsigned short size, + bool hollow, + std::string mask +) { + BoundingBox box(pos - size, pos + size); + long long i = 0; - phmap::flat_hash_set bset; - double R = radius + 0.5; - double nextXn = 0; - for (int x = 0; x <= radius; ++x) { - double xn = nextXn; - nextXn = (x + 1) / R; - double nextYn = 0; - for (int y = 0; y <= radius; ++y) { - double yn = nextYn; - nextYn = (y + 1) / R; - double nextZn = 0; - for (int z = 0; z <= radius; ++z) { - double zn = nextZn; - nextZn = (z + 1) / R; - if (xn * xn + yn * yn + zn * zn > 1) { - continue; - } - if (hollow) { - if (nextXn * nextXn + yn * yn + zn * zn <= 1 && xn * xn + nextYn * nextYn + zn * zn <= 1 && - xn * xn + yn * yn + nextZn * nextZn <= 1) { - continue; - } - } + auto& playerData = getPlayersData(xuid); + auto blockSource = Level::getBlockSource(dim); - BlockPos blockPos = pos; - blockPos += {x, y, z}; - bset.insert(blockPos); - blockPos.y = pos.y - y; - bset.insert(blockPos); - blockPos.z = pos.z - z; - bset.insert(blockPos); - blockPos.x = pos.x - x; - bset.insert(blockPos); - blockPos.y = pos.y + y; - bset.insert(blockPos); - blockPos.x = pos.x + x; - bset.insert(blockPos); - blockPos.x = pos.x - x; - blockPos.z = pos.z + z; - bset.insert(blockPos); - blockPos.y = pos.y - y; - bset.insert(blockPos); - } + std::function< + void(EvalFunctions&, phmap::flat_hash_map const&, std::function const&)> + maskLambda; + if (mask != "") { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { + if (cpp_eval::eval(mask, var, func) > 0.5) { + todo(); } - } - for (auto& b : bset) { - setFunction(variables, f, box, playerPos, b, pos.toVec3() + 0.5f); - maskLambda(f, variables, [&]() mutable { i += pattern->setBlock(variables, f, blockSource, b); }); - } - return i; + }; + } else { + maskLambda = [&](EvalFunctions& func, + const phmap::flat_hash_map& var, + std::function const& todo) mutable { todo(); }; } - long long SimpleBuilder::buildCube(BlockPos pos, - int dim, - std::string xuid, - Pattern* pattern, - unsigned short size, - bool hollow, - std::string mask) { - BoundingBox box(pos - size, pos + size); - long long i = 0; + auto* player = Global->getPlayer(xuid); - auto& playerData = getPlayersData(xuid); - auto blockSource = Level::getBlockSource(dim); + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + EvalFunctions f; + f.setbs(blockSource); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - std::function const&, - std::function const&)> - maskLambda; - if (mask != "") { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { - if (cpp_eval::eval(mask, var, func) > 0.5) { - todo(); - } - }; - } else { - maskLambda = [&](EvalFunctions& func, const phmap::flat_hash_map& var, - std::function const& todo) mutable { todo(); }; - } - - auto* player = Global->getPlayer(xuid); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dim; + history.playerPos = box.min; - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - EvalFunctions f; - f.setbs(blockSource); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + box.forEachBlockInBox([&](BlockPos const& blockPos) { + auto localPos = blockPos - box.min; + auto blockInstance = blockSource->getBlockInstance(blockPos); + history.storeBlock(blockInstance, localPos); + }); + } - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dim; - history.playerPos = box.min; + box.forEachBlockInBox([&](const BlockPos blockPos) { + if (!hollow + || (blockPos.x == box.min.x || blockPos.x == box.max.x + || blockPos.y == box.min.y || blockPos.y == box.max.y + || blockPos.z == box.min.z || blockPos.z == box.max.z)) { + setFunction(variables, f, box, playerPos, blockPos, pos.toVec3() + 0.5f); - box.forEachBlockInBox([&](const BlockPos& blockPos) { - auto localPos = blockPos - box.min; - auto blockInstance = blockSource->getBlockInstance(blockPos); - history.storeBlock(blockInstance, localPos); + maskLambda(f, variables, [&]() mutable { + pattern->setBlock(variables, f, blockSource, blockPos); + ++i; }); } - - box.forEachBlockInBox([&](const BlockPos blockPos) { - if (!hollow || (blockPos.x == box.min.x || blockPos.x == box.max.x || blockPos.y == box.min.y || - blockPos.y == box.max.y || blockPos.z == box.min.z || blockPos.z == box.max.z)) { - setFunction(variables, f, box, playerPos, blockPos, pos.toVec3() + 0.5f); - - maskLambda(f, variables, [&]() mutable { - pattern->setBlock(variables, f, blockSource, blockPos); - ++i; - }); - } - }); - return i; - } -} // namespace worldedit \ No newline at end of file + }); + return i; +} +} // namespace we \ No newline at end of file diff --git a/old/core/builder/SimpleBuilder.h b/old/core/builder/SimpleBuilder.h index 458c284..a5b85fe 100644 --- a/old/core/builder/SimpleBuilder.h +++ b/old/core/builder/SimpleBuilder.h @@ -1,34 +1,37 @@ -// -// Created by OEOTYAN on 2022/06/09. -// #pragma once # -namespace worldedit { - class SimpleBuilder { - public: - static long long buildCylinder(BlockPos pos, - int dim, - std::string xuid, - class Pattern*, - unsigned short radius = 0, - int height = 1, - bool hollow = false, - std::string mask = ""); - static long long buildSphere(BlockPos pos, - int dim, - std::string xuid, - class Pattern*, - unsigned short radius = 0, - bool hollow = false, - std::string mask = ""); - static long long buildCube(BlockPos pos, - int dim, - std::string xuid, - class Pattern*, - unsigned short size = 0, - bool hollow = false, - std::string mask = ""); - }; -} // namespace worldedit +namespace we { +class SimpleBuilder { +public: + static long long buildCylinder( + BlockPos pos, + int dim, + std::string xuid, + class Pattern*, + unsigned short radius = 0, + int height = 1, + bool hollow = false, + std::string mask = "" + ); + static long long buildSphere( + BlockPos pos, + int dim, + std::string xuid, + class Pattern*, + unsigned short radius = 0, + bool hollow = false, + std::string mask = "" + ); + static long long buildCube( + BlockPos pos, + int dim, + std::string xuid, + class Pattern*, + unsigned short size = 0, + bool hollow = false, + std::string mask = "" + ); +}; +} // namespace we diff --git a/old/core/command/BrushCommand.cpp b/old/core/command/BrushCommand.cpp index 891a338..4404ab5 100644 --- a/old/core/command/BrushCommand.cpp +++ b/old/core/command/BrushCommand.cpp @@ -1,354 +1,418 @@ -// -// Created by OEOTYAN on 2022/06/10. -// +#include "WorldEdit.h" #include "allCommand.hpp" -#include #include "brush/Brushs.h" -#include -#include -#include "store/Patterns.h" #include "filesys/download.h" -#include "WorldEdit.h" +#include "store/Patterns.h" #include "utils/StringTool.h" +#include +#include +#include -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // brush bmask bsize ruseface +// brush bmask bsize ruseface - void brushCommandSetup() { - DynamicCommand::setup( - "brush", // command name - tr("worldedit.command.description.brush"), // command description - { - // enums{enumName, {values...}} - {"sphere", {"sphere"}}, - {"mix", {"mix"}}, - {"cyl", {"cyl"}}, - {"cube", {"cube"}}, - {"color", {"color"}}, - {"clipboard", {"clipboard"}}, - {"smooth", {"smooth"}}, - {"heightmap", {"heightmap"}}, - {"none", {"none"}}, - {"flat", {"flat"}}, - {"file", {"file"}}, - {"link", {"link"}}, - }, - { - // parameters(type, name, [optional], [enumOptions(also - // enumName)], [identifier]) identifier: used to identify unique - // parameter data, if idnetifier is not set, - // it is set to be the same as enumOptions or name (identifier - // = enumOptions.empty() ? name:enumOptions) - ParamData("sphere", ParamType::Enum, "sphere"), - ParamData("cyl", ParamType::Enum, "cyl"), - ParamData("mix", ParamType::Enum, "mix"), - ParamData("cube", ParamType::Enum, "cube"), - ParamData("color", ParamType::Enum, "color"), - ParamData("clipboard", ParamType::Enum, "clipboard"), - ParamData("smooth", ParamType::Enum, "smooth"), - ParamData("flat", ParamType::Enum, "flat"), - ParamData("heightmap", ParamType::Enum, "heightmap"), - ParamData("none", ParamType::Enum, "none"), - ParamData("args", ParamType::SoftEnum, true, "-ahor", "-ahor"), - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Int, true, "radius"), - ParamData("Rf", ParamType::Float, "Rf"), - ParamData("Gf", ParamType::Float, "Gf"), - ParamData("Bf", ParamType::Float, "Bf"), - ParamData("mixBoxLerp", ParamType::Bool, true, "mixBoxLerp"), - ParamData("density", ParamType::Float, true, "density"), - ParamData("opacity", ParamType::Float, true, "opacity"), - ParamData("kernelsize", ParamType::Int, true, "kernelsize"), - ParamData("height", ParamType::Int, true, "height"), - ParamData("imagefilename", ParamType::SoftEnum, "imagefilename"), - ParamData("url", ParamType::String, "url"), - ParamData("file", ParamType::Enum, "file"), - ParamData("link", ParamType::Enum, "link"), - }, - { - // overloads{ (type == Enum ? enumOptions : name) ...} - {"clipboard", "args"}, - {"cube", "block", "radius", "args"}, - {"cube", "blockPattern", "radius", "args"}, - {"sphere", "block", "radius", "args"}, - {"flat", "radius", "density"}, - {"sphere", "blockPattern", "radius", "args"}, - {"mix", "radius", "density", "opacity", "mixBoxLerp"}, - {"color", "Rf", "Gf", "Bf", "radius", "density", "opacity", "mixBoxLerp"}, - {"color", "block", "radius", "density", "opacity", "mixBoxLerp"}, - {"color", "blockPattern", "radius", "density", "opacity", "mixBoxLerp"}, - {"cyl", "block", "radius", "height", "args"}, - {"cyl", "blockPattern", "radius", "height", "args"}, - {"smooth", "radius", "kernelsize", "density"}, - {"heightmap", "file", "imagefilename", "radius", "height", "args"}, - {"heightmap", "link", "url", "radius", "height", "args"}, - {"none"}, - }, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); +void brushCommandSetup() { + DynamicCommand::setup( + "brush", // command name + tr("worldedit.command.description.brush"), // command description + { + // enums{enumName, {values...}} + {"sphere", {"sphere"} }, + {"mix", {"mix"} }, + {"cyl", {"cyl"} }, + {"cube", {"cube"} }, + {"color", {"color"} }, + {"clipboard", {"clipboard"}}, + {"smooth", {"smooth"} }, + {"heightmap", {"heightmap"}}, + {"none", {"none"} }, + {"flat", {"flat"} }, + {"file", {"file"} }, + {"link", {"link"} }, + }, + { + // parameters(type, name, [optional], [enumOptions(also + // enumName)], [identifier]) identifier: used to identify unique + // parameter data, if idnetifier is not set, + // it is set to be the same as enumOptions or name (identifier + // = enumOptions.empty() ? name:enumOptions) + ParamData("sphere", ParamType::Enum, "sphere"), + ParamData("cyl", ParamType::Enum, "cyl"), + ParamData("mix", ParamType::Enum, "mix"), + ParamData("cube", ParamType::Enum, "cube"), + ParamData("color", ParamType::Enum, "color"), + ParamData("clipboard", ParamType::Enum, "clipboard"), + ParamData("smooth", ParamType::Enum, "smooth"), + ParamData("flat", ParamType::Enum, "flat"), + ParamData("heightmap", ParamType::Enum, "heightmap"), + ParamData("none", ParamType::Enum, "none"), + ParamData("args", ParamType::SoftEnum, true, "-ahor", "-ahor"), + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Int, true, "radius"), + ParamData("Rf", ParamType::Float, "Rf"), + ParamData("Gf", ParamType::Float, "Gf"), + ParamData("Bf", ParamType::Float, "Bf"), + ParamData("mixBoxLerp", ParamType::Bool, true, "mixBoxLerp"), + ParamData("density", ParamType::Float, true, "density"), + ParamData("opacity", ParamType::Float, true, "opacity"), + ParamData("kernelsize", ParamType::Int, true, "kernelsize"), + ParamData("height", ParamType::Int, true, "height"), + ParamData("imagefilename", ParamType::SoftEnum, "imagefilename"), + ParamData("url", ParamType::String, "url"), + ParamData("file", ParamType::Enum, "file"), + ParamData("link", ParamType::Enum, "link"), + }, + { + // overloads{ (type == Enum ? enumOptions : name) ...} + {"clipboard", "args"}, + {"cube", "block", "radius", "args"}, + {"cube", "blockPattern", "radius", "args"}, + {"sphere", "block", "radius", "args"}, + {"flat", "radius", "density"}, + {"sphere", "blockPattern", "radius", "args"}, + {"mix", "radius", "density", "opacity", "mixBoxLerp"}, + {"color", "Rf", "Gf", "Bf", "radius", "density", "opacity", "mixBoxLerp"}, + {"color", "block", "radius", "density", "opacity", "mixBoxLerp"}, + {"color", "blockPattern", "radius", "density", "opacity", "mixBoxLerp"}, + {"cyl", "block", "radius", "height", "args"}, + {"cyl", "blockPattern", "radius", "height", "args"}, + {"smooth", "radius", "kernelsize", "density"}, + {"heightmap", "file", "imagefilename", "radius", "height", "args"}, + {"heightmap", "link", "url", "radius", "height", "args"}, + {"none"}, + }, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto* item = player->getHandSlot(); + std::string brushName = item->getTypeName(); + std::string brushrName = brushName; + if (brushName == "") { + output.trError("worldedit.error.noitem"); + return; + } + stringReplace(brushrName, "minecraft:", ""); + brushName += std::to_string(item->getAuxValue()); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + unsigned short radius = 2; + int ksize = 5; + int height = 1; + if (results["radius"].isSet) { + radius = (unsigned short)(results["radius"].get()); + } + if (results["height"].isSet) { + height = results["height"].get(); + } + if (results["kernelsize"].isSet) { + ksize = results["kernelsize"].get(); + } + + bool arg_a = false, arg_h = false, arg_o = true, arg_r = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); return; } - auto* item = player->getHandSlot(); - std::string brushName = item->getTypeName(); - std::string brushrName = brushName; - if (brushName == "") { - output.trError("worldedit.error.noitem"); - return; + if (str.find("a") != std::string::npos) { + arg_a = true; } - stringReplace(brushrName, "minecraft:", ""); - brushName += std::to_string(item->getAuxValue()); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - unsigned short radius = 2; - int ksize = 5; - int height = 1; - if (results["radius"].isSet) { - radius = (unsigned short)(results["radius"].get()); + if (str.find("o") != std::string::npos) { + arg_o = false; } - if (results["height"].isSet) { - height = results["height"].get(); + if (str.find("h") != std::string::npos) { + arg_h = true; } - if (results["kernelsize"].isSet) { - ksize = results["kernelsize"].get(); + if (str.find("r") != std::string::npos) { + arg_r = true; } + } - bool arg_a = false, arg_h = false, arg_o = true, arg_r = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("a") != std::string::npos) { - arg_a = true; - } - if (str.find("o") != std::string::npos) { - arg_o = false; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } - if (str.find("r") != std::string::npos) { - arg_r = true; - } - } - - float density = 0.5f; - float opacity = 1.0f; - float mixBoxLerp = true; + float density = 0.5f; + float opacity = 1.0f; + float mixBoxLerp = true; - if (results["density"].isSet) { - density = results["density"].get(); - } + if (results["density"].isSet) { + density = results["density"].get(); + } - if (results["opacity"].isSet) { - opacity = results["opacity"].get(); - } + if (results["opacity"].isSet) { + opacity = results["opacity"].get(); + } - if (results["mixBoxLerp"].isSet) { - mixBoxLerp = results["mixBoxLerp"].get(); - } + if (results["mixBoxLerp"].isSet) { + mixBoxLerp = results["mixBoxLerp"].get(); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } - if (results["sphere"].isSet) { + if (results["sphere"].isSet) { + playerData.brushMap[brushName] = std::make_unique( + SphereBrush(radius, Pattern::createPattern(bps, xuid), arg_h) + ); + output.trSuccess("worldedit.brush.set.sphere", brushrName); + return; + } else if (results["color"].isSet) { + if (results["Rf"].isSet) { playerData.brushMap[brushName] = - std::make_unique(SphereBrush(radius, Pattern::createPattern(bps, xuid), arg_h)); - output.trSuccess("worldedit.brush.set.sphere", brushrName); - return; - } else if (results["color"].isSet) { - if (results["Rf"].isSet) { - playerData.brushMap[brushName] = std::make_unique( - ColorBrush(radius, density, opacity, - mce::Color(results["Rf"].get(), results["Gf"].get(), - results["Bf"].get()), - nullptr, mixBoxLerp)); - } else if (isColorHex(bps)) { - playerData.brushMap[brushName] = std::make_unique( - ColorBrush(radius, density, opacity, mce::Color(bps), nullptr, mixBoxLerp)); - } else { - playerData.brushMap[brushName] = std::make_unique(ColorBrush( - radius, density, opacity, mce::Color(), Pattern::createPattern(bps, xuid), mixBoxLerp)); - } - output.trSuccess("worldedit.brush.set.color", brushrName); - return; - } else if (results["mix"].isSet) { + std::make_unique(ColorBrush( + radius, + density, + opacity, + mce::Color( + results["Rf"].get(), + results["Gf"].get(), + results["Bf"].get() + ), + nullptr, + mixBoxLerp + )); + } else if (isColorHex(bps)) { playerData.brushMap[brushName] = - std::make_unique(MixBrush(radius, density, opacity, mixBoxLerp)); - output.trSuccess("worldedit.brush.set.mix", brushrName); - return; - } else if (results["flat"].isSet) { - playerData.brushMap[brushName] = std::make_unique(FlatBrush(radius, density)); - output.trSuccess("worldedit.brush.set.flat", brushrName); - return; - } else if (results["cube"].isSet) { + std::make_unique(ColorBrush( + radius, + density, + opacity, + mce::Color(bps), + nullptr, + mixBoxLerp + )); + } else { playerData.brushMap[brushName] = - std::make_unique(CubeBrush(radius, Pattern::createPattern(bps, xuid), arg_h)); - output.trSuccess("worldedit.brush.set.cube", brushrName); - return; - } else if (results["cyl"].isSet) { - playerData.brushMap[brushName] = std::make_unique( - CylinderBrush(radius, Pattern::createPattern(bps, xuid), height, arg_h)); - output.trSuccess("worldedit.brush.set.cylinder", brushrName); - return; - } else if (results["clipboard"].isSet) { - if (playerData.clipboard.used) { - playerData.brushMap[brushName] = - std::make_unique(ClipboardBrush(0, playerData.clipboard, arg_o, arg_a)); - } else { - output.trError("worldedit.error.empty-clipboard"); - return; - } - output.trSuccess("worldedit.brush.set.clipboard", brushrName); - return; - } else if (results["smooth"].isSet) { - playerData.brushMap[brushName] = std::make_unique(SmoothBrush(radius, ksize, density)); - output.trSuccess("worldedit.brush.set.smooth", brushrName); - return; - } else if (results["heightmap"].isSet) { - std::string filename; - if (results["imagefilename"].isSet) { - filename = results["imagefilename"].get(); - - filename = WE_DIR + "image/" + filename; - } else /* if (results["link"].isSet)*/ { - if (downloadImage(results["url"].get())) { - filename = WE_DIR + "imgtemp/0image"; - } else { - output.trError("worldedit.error.download-image"); - return; - } - } - - playerData.brushMap[brushName] = std::make_unique( - ImageHeightmapBrush(radius, height, loadImage(filename), arg_r)); - - output.trSuccess("worldedit.brush.set.heightmap", brushrName); - return; - } else if (results["none"].isSet) { - if (playerData.brushMap.contains(brushName)) { - playerData.brushMap.erase(brushName); - output.trSuccess("worldedit.brush.clear", brushrName); - } else { - output.trError("worldedit.error.nobrush"); - } - return; + std::make_unique(ColorBrush( + radius, + density, + opacity, + mce::Color(), + Pattern::createPattern(bps, xuid), + mixBoxLerp + )); } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "bmask", // command name - tr("worldedit.command.description.bmask"), // command description - {}, {ParamData("mask", ParamType::String, true, "mask")}, {{"mask"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + output.trSuccess("worldedit.brush.set.color", brushrName); + return; + } else if (results["mix"].isSet) { + playerData.brushMap[brushName] = std::make_unique( + MixBrush(radius, density, opacity, mixBoxLerp) + ); + output.trSuccess("worldedit.brush.set.mix", brushrName); + return; + } else if (results["flat"].isSet) { + playerData.brushMap[brushName] = + std::make_unique(FlatBrush(radius, density)); + output.trSuccess("worldedit.brush.set.flat", brushrName); + return; + } else if (results["cube"].isSet) { + playerData.brushMap[brushName] = std::make_unique( + CubeBrush(radius, Pattern::createPattern(bps, xuid), arg_h) + ); + output.trSuccess("worldedit.brush.set.cube", brushrName); + return; + } else if (results["cyl"].isSet) { + playerData.brushMap[brushName] = + std::make_unique(CylinderBrush( + radius, + Pattern::createPattern(bps, xuid), + height, + arg_h + )); + output.trSuccess("worldedit.brush.set.cylinder", brushrName); + return; + } else if (results["clipboard"].isSet) { + if (playerData.clipboard.used) { + playerData.brushMap[brushName] = std::make_unique( + ClipboardBrush(0, playerData.clipboard, arg_o, arg_a) + ); + } else { + output.trError("worldedit.error.empty-clipboard"); return; } - auto* item = player->getHandSlot(); - std::string brushName = item->getTypeName() + std::to_string(item->getAuxValue()); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.brushMap.contains(brushName)) { - auto& brush = playerData.brushMap[brushName]; - if (results["mask"].isSet) { - auto tmp = results["mask"].get(); - brush->mask = tmp; - output.trSuccess("worldedit.brush.mask.set", tmp); + output.trSuccess("worldedit.brush.set.clipboard", brushrName); + return; + } else if (results["smooth"].isSet) { + playerData.brushMap[brushName] = + std::make_unique(SmoothBrush(radius, ksize, density)); + output.trSuccess("worldedit.brush.set.smooth", brushrName); + return; + } else if (results["heightmap"].isSet) { + std::string filename; + if (results["imagefilename"].isSet) { + filename = results["imagefilename"].get(); + + filename = WE_DIR + "image/" + filename; + } else /* if (results["link"].isSet)*/ { + if (downloadImage(results["url"].get())) { + filename = WE_DIR + "imgtemp/0image"; } else { - brush->mask = ""; - output.trSuccess("worldedit.brush.mask.clear"); + output.trError("worldedit.error.download-image"); + return; } - } else { - output.trError("worldedit.error.nobrush"); } - }, - CommandPermissionLevel::GameMasters); - DynamicCommand::setup( - "bsize", // command name - tr("worldedit.command.description.bsize"), // command description - {}, {ParamData("size", ParamType::Int, "size")}, {{"size"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto* item = player->getHandSlot(); - std::string brushName = item->getTypeName() + std::to_string(item->getAuxValue()); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); + playerData.brushMap[brushName] = std::make_unique( + ImageHeightmapBrush(radius, height, loadImage(filename), arg_r) + ); + + output.trSuccess("worldedit.brush.set.heightmap", brushrName); + return; + } else if (results["none"].isSet) { if (playerData.brushMap.contains(brushName)) { - auto& brush = playerData.brushMap[brushName]; - auto size = results["size"].get(); - brush->size = size; - output.trSuccess("worldedit.brush.size.set", size); + playerData.brushMap.erase(brushName); + output.trSuccess("worldedit.brush.clear", brushrName); } else { output.trError("worldedit.error.nobrush"); } - }, - CommandPermissionLevel::GameMasters); + return; + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "ruseface", // command name - tr("worldedit.command.description.ruseface"), // command description - {}, {ParamData("bool", ParamType::Bool, "bool")}, {{"bool"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto* item = player->getHandSlot(); - std::string brushName = item->getTypeName() + std::to_string(item->getAuxValue()); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.brushMap.contains(brushName)) { - auto& brush = playerData.brushMap[brushName]; - auto useface = results["bool"].get(); - brush->needFace = useface; - output.trSuccess("worldedit.brush.ruseface.set", useface ? "true" : "false"); + DynamicCommand::setup( + "bmask", // command name + tr("worldedit.command.description.bmask"), // command description + {}, + {ParamData("mask", ParamType::String, true, "mask")}, + {{"mask"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto* item = player->getHandSlot(); + std::string brushName = + item->getTypeName() + std::to_string(item->getAuxValue()); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.brushMap.contains(brushName)) { + auto& brush = playerData.brushMap[brushName]; + if (results["mask"].isSet) { + auto tmp = results["mask"].get(); + brush->mask = tmp; + output.trSuccess("worldedit.brush.mask.set", tmp); } else { - output.trError("worldedit.error.notb"); + brush->mask = ""; + output.trSuccess("worldedit.brush.mask.clear"); } - }, - CommandPermissionLevel::GameMasters); + } else { + output.trError("worldedit.error.nobrush"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "clearallbrushs", // command name - tr("worldedit.command.description.clearallbrushs"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer()->getXuid(); - if (getPlayersDataMap().contains(player)) { - getPlayersDataMap()[player]->brushMap.clear(); - } - output.trSuccess("worldedit.clearallbrushs.success"); - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + DynamicCommand::setup( + "bsize", // command name + tr("worldedit.command.description.bsize"), // command description + {}, + {ParamData("size", ParamType::Int, "size")}, + {{"size"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto* item = player->getHandSlot(); + std::string brushName = + item->getTypeName() + std::to_string(item->getAuxValue()); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.brushMap.contains(brushName)) { + auto& brush = playerData.brushMap[brushName]; + auto size = results["size"].get(); + brush->size = size; + output.trSuccess("worldedit.brush.size.set", size); + } else { + output.trError("worldedit.error.nobrush"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "ruseface", // command name + tr("worldedit.command.description.ruseface"), // command description + {}, + {ParamData("bool", ParamType::Bool, "bool")}, + {{"bool"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto* item = player->getHandSlot(); + std::string brushName = + item->getTypeName() + std::to_string(item->getAuxValue()); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.brushMap.contains(brushName)) { + auto& brush = playerData.brushMap[brushName]; + auto useface = results["bool"].get(); + brush->needFace = useface; + output.trSuccess( + "worldedit.brush.ruseface.set", + useface ? "true" : "false" + ); + } else { + output.trError("worldedit.error.notb"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "clearallbrushs", // command name + tr("worldedit.command.description.clearallbrushs"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer()->getXuid(); + if (getPlayersDataMap().contains(player)) { + getPlayersDataMap()[player]->brushMap.clear(); + } + output.trSuccess("worldedit.clearallbrushs.success"); + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/ClipboardCommand.cpp b/old/core/command/ClipboardCommand.cpp index 324e0b7..e3198c3 100644 --- a/old/core/command/ClipboardCommand.cpp +++ b/old/core/command/ClipboardCommand.cpp @@ -1,371 +1,430 @@ -// -// Created by OEOTYAN on 2022/05/20. -// // #include "Globals.h" -#include "allCommand.hpp" -#include -#include -#include "mc/StructureTemplate.hpp" #include "WorldEdit.h" +#include "allCommand.hpp" #include "data/PlayerData.h" -#include "region/Regions.h" -#include "store/Clipboard.hpp" #include "eval/Eval.h" +#include "mc/StructureTemplate.hpp" +#include "region/Regions.h" #include "store/BlockNBTSet.hpp" +#include "store/Clipboard.hpp" +#include +#include -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // copy cut paste rotate flip clearclipboard +// copy cut paste rotate flip clearclipboard - void clipboardCommandSetup() { - DynamicCommand::setup( - "clearclipboard", // command name - tr("worldedit.command.description.clearclipboard"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - playerData.clipboard = std::move(Clipboard()); - output.trSuccess("worldedit.clipboard.clear"); - }, - CommandPermissionLevel::GameMasters); +void clipboardCommandSetup() { + DynamicCommand::setup( + "clearclipboard", // command name + tr("worldedit.command.description.clearclipboard"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + playerData.clipboard = std::move(Clipboard()); + output.trSuccess("worldedit.clipboard.clear"); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "copy", // command name - tr("worldedit.command.description.copy"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto boundingBox = region->getBoundBox(); + DynamicCommand::setup( + "copy", // command name + tr("worldedit.command.description.copy"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto boundingBox = region->getBoundBox(); - playerData.clipboard = std::move(std::move(Clipboard(boundingBox.max - boundingBox.min))); - auto pPos = origin.getWorldPosition(); - playerData.clipboard.playerPos = pPos.toBlockPos(); - playerData.clipboard.playerRelPos = pPos.toBlockPos() - boundingBox.min; - auto dimID = region->getDimensionID(); - auto blockSource = &player->getDimensionBlockSource(); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - playerData.clipboard.storeBlock(blockInstance, localPos); - }); - if (true) { - auto st = - StructureTemplate("worldedit_copy_cmd_tmp", - dAccess, 192>( - Global)); + playerData.clipboard = + std::move(std::move(Clipboard(boundingBox.max - boundingBox.min))); + auto pPos = origin.getWorldPosition(); + playerData.clipboard.playerPos = pPos.toBlockPos(); + playerData.clipboard.playerRelPos = pPos.toBlockPos() - boundingBox.min; + auto dimID = region->getDimensionID(); + auto blockSource = &player->getDimensionBlockSource(); + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + playerData.clipboard.storeBlock(blockInstance, localPos); + }); + if (true) { + auto st = StructureTemplate( + "worldedit_copy_cmd_tmp", + dAccess< + Bedrock::NonOwnerPointer, + 192>(Global) + ); - auto setting = StructureSettings(); - setting.setIgnoreBlocks(true); - setting.setIgnoreEntities(false); - setting.setMirror(Mirror::None); - setting.setStructureSize(boundingBox.max - boundingBox.min + 1); - setting.setRotation(Rotation::None); - st.fillFromWorld(*blockSource, boundingBox.min + BlockPos(0, 1, 0), setting); - // auto structure = st.toTag()->toBinaryNBT(); - // std::cout << structure << std::endl; - boundingBox += BlockPos(0, 1, 0); - playerData.clipboard.entities = - // StructureTemplate::fromWorld("worldedit_copy_cmd_tmp", - // dimID, - // boundingBox.min, boundingBox.max, - // false, true) - st.toTag(); - } - output.trSuccess("worldedit.clipboard.copy"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "cut", // command name - tr("worldedit.command.description.cut"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + auto setting = StructureSettings(); + setting.setIgnoreBlocks(true); + setting.setIgnoreEntities(false); + setting.setMirror(Mirror::None); + setting.setStructureSize(boundingBox.max - boundingBox.min + 1); + setting.setRotation(Rotation::None); + st.fillFromWorld( + *blockSource, + boundingBox.min + BlockPos(0, 1, 0), + setting + ); + // auto structure = st.toTag()->toBinaryNBT(); + // std::cout << structure << std::endl; + boundingBox += BlockPos(0, 1, 0); + playerData.clipboard.entities = + // StructureTemplate::fromWorld("worldedit_copy_cmd_tmp", + // dimID, + // boundingBox.min, boundingBox.max, + // false, true) + st.toTag(); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + output.trSuccess("worldedit.clipboard.copy"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; + DynamicCommand::setup( + "cut", // command name + tr("worldedit.command.description.cut"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - auto pPos = origin.getWorldPosition(); - - playerData.clipboard = std::move(std::move(Clipboard(boundingBox.max - boundingBox.min))); - playerData.clipboard.playerPos = pPos.toBlockPos(); - playerData.clipboard.playerRelPos = pPos.toBlockPos() - boundingBox.min; - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; auto blockInstance = blockSource->getBlockInstance(pos); - playerData.clipboard.storeBlock(blockInstance, localPos); + history.storeBlock(blockInstance, localPos); }); + } - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - auto playerPos = origin.getWorldPosition(); - Vec3 center = boundingBox.getCenter().toVec3(); + auto pPos = origin.getWorldPosition(); - region->forEachBlockInRegion([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple(blockSource, f, variables, pos); - }); - output.trSuccess("worldedit.clipboard.cut"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); + playerData.clipboard = + std::move(std::move(Clipboard(boundingBox.max - boundingBox.min))); + playerData.clipboard.playerPos = pPos.toBlockPos(); + playerData.clipboard.playerRelPos = pPos.toBlockPos() - boundingBox.min; + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + playerData.clipboard.storeBlock(blockInstance, localPos); + }); - DynamicCommand::setup( - "paste", // command name - tr("worldedit.command.description.paste"), // command description - {}, {ParamData("args", ParamType::SoftEnum, true, "-anose", "-anose")}, {{"args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.clipboard.used) { - long long i = 0; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + auto playerPos = origin.getWorldPosition(); + Vec3 center = boundingBox.getCenter().toVec3(); - bool arg_a = false, arg_n = false, arg_o = false, arg_s = false, arg_e = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("a") != std::string::npos) { - arg_a = true; - } - if (str.find("n") != std::string::npos) { - arg_n = true; - } - if (str.find("o") != std::string::npos) { - arg_o = true; - } - if (str.find("s") != std::string::npos) { - arg_s = true; - } - if (str.find("e") != std::string::npos) { - arg_e = true; - } + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + playerData.setBlockSimple(blockSource, f, variables, pos); + }); + output.trSuccess("worldedit.clipboard.cut"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "paste", // command name + tr("worldedit.command.description.paste"), // command description + {}, + {ParamData("args", ParamType::SoftEnum, true, "-anose", "-anose")}, + {{"args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.clipboard.used) { + long long i = 0; + + bool arg_a = false, arg_n = false, arg_o = false, arg_s = false, + arg_e = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - BlockPos pbPos; - if (arg_o) { - pbPos = playerData.clipboard.playerPos; - } else { - auto pPos = origin.getWorldPosition(); - pbPos = pPos.toBlockPos(); + if (str.find("a") != std::string::npos) { + arg_a = true; + } + if (str.find("n") != std::string::npos) { + arg_n = true; + } + if (str.find("o") != std::string::npos) { + arg_o = true; } + if (str.find("s") != std::string::npos) { + arg_s = true; + } + if (str.find("e") != std::string::npos) { + arg_e = true; + } + } + BlockPos pbPos; + if (arg_o) { + pbPos = playerData.clipboard.playerPos; + } else { + auto pPos = origin.getWorldPosition(); + pbPos = pPos.toBlockPos(); + } - BoundingBox box = playerData.clipboard.getBoundingBox() + pbPos; + BoundingBox box = playerData.clipboard.getBoundingBox() + pbPos; - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(&player->getDimensionBlockSource()); - f.setbox(box); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(&player->getDimensionBlockSource()); + f.setbox(box); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - BlockInstance blockInstance; + BlockInstance blockInstance; - auto dimID = origin.getPlayer()->getDimensionId(); - if (arg_s) { - if (playerData.region != nullptr && playerData.region->hasSelected()) { - playerData.region = nullptr; - } - blockInstance = Level::getBlockInstance(box.min, dimID); - playerData.changeMainPos(blockInstance, false); - blockInstance = Level::getBlockInstance(box.max, dimID); - playerData.changeVicePos(blockInstance, false); + auto dimID = origin.getPlayer()->getDimensionId(); + if (arg_s) { + if (playerData.region != nullptr + && playerData.region->hasSelected()) { + playerData.region = nullptr; } + blockInstance = Level::getBlockInstance(box.min, dimID); + playerData.changeMainPos(blockInstance, false); + blockInstance = Level::getBlockInstance(box.max, dimID); + playerData.changeVicePos(blockInstance, false); + } - auto blockSource = &player->getDimensionBlockSource(); - if (!arg_n) { - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(box.max - box.min)); - history.playerRelPos.x = dimID; - history.playerPos = box.min; + auto blockSource = &player->getDimensionBlockSource(); + if (!arg_n) { + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(box.max - box.min)); + history.playerRelPos.x = dimID; + history.playerPos = box.min; - box.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - box.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + box.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - box.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - Vec3 center = (pbPos + box.getCenter()).toVec3(); + Vec3 center = (pbPos + box.getCenter()).toVec3(); - auto playerPos = origin.getWorldPosition(); - if (arg_a) { - playerData.clipboard.forEachBlockInClipboard([&](const BlockPos& pos) { - if (playerData.clipboard.getSet(pos).getBlock() == BedrockBlocks::mAir && - playerData.clipboard.getSet(pos).getExBlock() == BedrockBlocks::mAir) { - return; - } - auto worldPos = playerData.clipboard.getPos(pos) + pbPos; - setFunction(variables, f, box, playerPos, worldPos, center); - i += playerData.clipboard.setBlocks(pos, worldPos, blockSource, playerData, f, - variables); - }); - } else { - playerData.clipboard.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = playerData.clipboard.getPos(pos) + pbPos; - setFunction(variables, f, box, playerPos, worldPos, center); + auto playerPos = origin.getWorldPosition(); + if (arg_a) { + playerData.clipboard.forEachBlockInClipboard([&](BlockPos const& + pos) { + if (playerData.clipboard.getSet(pos).getBlock() + == BedrockBlocks::mAir + && playerData.clipboard.getSet(pos).getExBlock() + == BedrockBlocks::mAir) { + return; + } + auto worldPos = playerData.clipboard.getPos(pos) + pbPos; + setFunction(variables, f, box, playerPos, worldPos, center); + i += playerData.clipboard.setBlocks( + pos, + worldPos, + blockSource, + playerData, + f, + variables + ); + }); + } else { + playerData.clipboard.forEachBlockInClipboard([&](BlockPos const& + pos) { + auto worldPos = playerData.clipboard.getPos(pos) + pbPos; + setFunction(variables, f, box, playerPos, worldPos, center); - i += playerData.clipboard.setBlocks(pos, worldPos, blockSource, playerData, f, - variables); - }); - } - } - if (arg_e && playerData.clipboard.entities != nullptr) { - auto st = - StructureTemplate("worldedit_paste_cmd_tmp", - dAccess, 192>( - Global)); - st.getData()->load(*playerData.clipboard.entities); - auto& palette = Global->getBlockPalette(); - auto setting = StructureSettings(); - setting.setMirror(playerData.clipboard.mirror); - setting.setStructureSize(st.getSize()); - setting.setRotation(playerData.clipboard.rotation); - st.placeInWorld(*blockSource, palette, - playerData.clipboard.getPos({0, 0, 0}) + pbPos + BlockPos(0, 1, 0), setting, - nullptr, false); + i += playerData.clipboard.setBlocks( + pos, + worldPos, + blockSource, + playerData, + f, + variables + ); + }); } - - output.trSuccess("worldedit.clipboard.paste", i); - } else { - output.trError("worldedit.error.empty-clipboard"); } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "flip", // command name - tr("worldedit.command.description.flip"), // command description - { - {"dir", {"me", "up", "down", "south", "north", "east", "west"}}, - }, - {ParamData("dir", ParamType::Enum, true, "dir")}, {{"dir"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + if (arg_e && playerData.clipboard.entities != nullptr) { + auto st = StructureTemplate( + "worldedit_paste_cmd_tmp", + dAccess< + Bedrock::NonOwnerPointer, + 192>(Global) + ); + st.getData()->load(*playerData.clipboard.entities); + auto& palette = Global->getBlockPalette(); + auto setting = StructureSettings(); + setting.setMirror(playerData.clipboard.mirror); + setting.setStructureSize(st.getSize()); + setting.setRotation(playerData.clipboard.rotation); + st.placeInWorld( + *blockSource, + palette, + playerData.clipboard.getPos({0, 0, 0}) + pbPos + + BlockPos(0, 1, 0), + setting, + nullptr, + false + ); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.clipboard.used) { - worldedit::FACING facing; - if (results["dir"].isSet) { - auto str = results["dir"].getRaw(); - if (str == "me") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } else { - facing = worldedit::dirStringToFacing(str); - } - } else { + + output.trSuccess("worldedit.clipboard.paste", i); + } else { + output.trError("worldedit.error.empty-clipboard"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "flip", // command name + tr("worldedit.command.description.flip"), // command description + { + {"dir", {"me", "up", "down", "south", "north", "east", "west"}}, + }, + {ParamData("dir", ParamType::Enum, true, "dir")}, + {{"dir"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.clipboard.used) { + worldedit::FACING facing; + if (results["dir"].isSet) { + auto str = results["dir"].getRaw(); + if (str == "me") { facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } else { + facing = worldedit::dirStringToFacing(str); } - playerData.clipboard.flip(facing); - output.trSuccess("worldedit.clipboard.flip"); } else { - output.trError("worldedit.error.empty-clipboard"); + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); } - }, - CommandPermissionLevel::GameMasters); + playerData.clipboard.flip(facing); + output.trSuccess("worldedit.clipboard.flip"); + } else { + output.trError("worldedit.error.empty-clipboard"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "rotate", // command name - tr("worldedit.command.description.rotate"), // command description - {}, - {ParamData("angleY", ParamType::Float, false, "angleY"), - ParamData("angleX", ParamType::Float, true, "angleX"), - ParamData("angleZ", ParamType::Float, true, "angleZ")}, - {{"angleY", "angleX", "angleZ"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + DynamicCommand::setup( + "rotate", // command name + tr("worldedit.command.description.rotate"), // command description + { + }, + {ParamData("angleY", ParamType::Float, false, "angleY"), + ParamData("angleX", ParamType::Float, true, "angleX"), + ParamData("angleZ", ParamType::Float, true, "angleZ")}, + {{"angleY", "angleX", "angleZ"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.clipboard.used) { + Vec3 angle(0, 0, 0); + if (results["angleY"].isSet) { + angle.y = results["angleY"].get(); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.clipboard.used) { - Vec3 angle(0, 0, 0); - if (results["angleY"].isSet) { - angle.y = results["angleY"].get(); - } - if (results["angleX"].isSet) { - angle.x = results["angleX"].get(); - } - if (results["angleZ"].isSet) { - angle.z = results["angleZ"].get(); - } - playerData.clipboard.rotate(angle); - output.trSuccess("worldedit.clipboard.rotate"); - } else { - output.trError("worldedit.error.empty-clipboard"); + if (results["angleX"].isSet) { + angle.x = results["angleX"].get(); + } + if (results["angleZ"].isSet) { + angle.z = results["angleZ"].get(); } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + playerData.clipboard.rotate(angle); + output.trSuccess("worldedit.clipboard.rotate"); + } else { + output.trError("worldedit.error.empty-clipboard"); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/GenerationCommand.cpp b/old/core/command/GenerationCommand.cpp index dca9a7c..9241a50 100644 --- a/old/core/command/GenerationCommand.cpp +++ b/old/core/command/GenerationCommand.cpp @@ -1,201 +1,264 @@ -// -// Created by OEOTYAN on 2022/06/10. -// +#include "WorldEdit.h" #include "allCommand.hpp" #include "builder/SimpleBuilder.h" +#include "region/Regions.h" #include "store/Patterns.h" -#include "WorldEdit.h" #include -#include "region/Regions.h" -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // cyl hcyl sphere hsphere +// cyl hcyl sphere hsphere - void generationCommandSetup() { - DynamicCommand::setup( - "cyl", // command name - tr("worldedit.command.description.cyl"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Int, "radius"), ParamData("height", ParamType::Int, true, "height"), - ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, - {{"block", "radius", "height", "args"}, {"blockPattern", "radius", "height", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto dimID = player->getDimensionId(); - auto pos = (origin.getWorldPosition()).toBlockPos(); +void generationCommandSetup() { + DynamicCommand::setup( + "cyl", // command name + tr("worldedit.command.description.cyl"), // command description + { + }, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Int, "radius"), + ParamData("height", ParamType::Int, true, "height"), + ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, + {{"block", "radius", "height", "args"}, + {"blockPattern", "radius", "height", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto dimID = player->getDimensionId(); + auto pos = (origin.getWorldPosition()).toBlockPos(); - bool arg_h = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } - } - unsigned short radius = 0; - if (results["radius"].isSet) { - radius = (unsigned short)(results["radius"].get()); + bool arg_h = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - int height = 1; - if (results["height"].isSet) { - height = results["height"].get(); + if (str.find("h") != std::string::npos) { + arg_h = true; } + } + unsigned short radius = 0; + if (results["radius"].isSet) { + radius = (unsigned short)(results["radius"].get()); + } + int height = 1; + if (results["height"].isSet) { + height = results["height"].get(); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - long long i = SimpleBuilder::buildCylinder(pos, dimID, xuid, pattern.get(), radius, height, arg_h); - i = std::max(0ll, i); - output.trSuccess("worldedit.set.success", i); - }, - CommandPermissionLevel::GameMasters); - DynamicCommand::setup( - "hcyl", // command name - tr("worldedit.command.description.hcyl"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Int, "radius"), ParamData("height", ParamType::Int, true, "height")}, - {{"block", "radius", "height"}, {"blockPattern", "radius", "height"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto dimID = player->getDimensionId(); - auto pos = (origin.getWorldPosition()).toBlockPos(); + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + long long i = SimpleBuilder::buildCylinder( + pos, + dimID, + xuid, + pattern.get(), + radius, + height, + arg_h + ); + i = std::max(0ll, i); + output.trSuccess("worldedit.set.success", i); + }, + CommandPermissionLevel::GameMasters + ); + DynamicCommand::setup( + "hcyl", // command name + tr("worldedit.command.description.hcyl"), // command description + { + }, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Int, "radius"), + ParamData("height", ParamType::Int, true, "height")}, + {{"block", "radius", "height"}, {"blockPattern", "radius", "height"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto dimID = player->getDimensionId(); + auto pos = (origin.getWorldPosition()).toBlockPos(); - bool arg_h = true; - unsigned short radius = 0; - if (results["radius"].isSet) { - radius = (unsigned short)(results["radius"].get()); - } - int height = 1; - if (results["height"].isSet) { - height = results["height"].get(); - } + bool arg_h = true; + unsigned short radius = 0; + if (results["radius"].isSet) { + radius = (unsigned short)(results["radius"].get()); + } + int height = 1; + if (results["height"].isSet) { + height = results["height"].get(); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - long long i = SimpleBuilder::buildCylinder(pos, dimID, xuid, pattern.get(), radius, height, arg_h); - i = std::max(0ll, i); - output.trSuccess("worldedit.set.success", i); - }, - CommandPermissionLevel::GameMasters); + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + long long i = SimpleBuilder::buildCylinder( + pos, + dimID, + xuid, + pattern.get(), + radius, + height, + arg_h + ); + i = std::max(0ll, i); + output.trSuccess("worldedit.set.success", i); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "sphere", // command name - tr("worldedit.command.description.sphere"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Int, "radius"), ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, - {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto dimID = player->getDimensionId(); - auto pos = (origin.getWorldPosition()).toBlockPos(); + DynamicCommand::setup( + "sphere", // command name + tr("worldedit.command.description.sphere"), // command description + { + }, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Int, "radius"), + ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, + {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto dimID = player->getDimensionId(); + auto pos = (origin.getWorldPosition()).toBlockPos(); - bool arg_h = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } + bool arg_h = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - unsigned short radius = 0; - if (results["radius"].isSet) { - radius = (unsigned short)(results["radius"].get()); + if (str.find("h") != std::string::npos) { + arg_h = true; } + } + unsigned short radius = 0; + if (results["radius"].isSet) { + radius = (unsigned short)(results["radius"].get()); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - long long i = SimpleBuilder::buildSphere(pos, dimID, xuid, pattern.get(), radius, arg_h); - i = std::max(0ll, i); - output.trSuccess("worldedit.set.success", i); - }, - CommandPermissionLevel::GameMasters); - DynamicCommand::setup( - "hsphere", // command name - tr("worldedit.command.description.hsphere"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Int, "radius")}, - {{"block", "radius"}, {"blockPattern", "radius"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto dimID = player->getDimensionId(); - auto pos = (origin.getWorldPosition()).toBlockPos(); + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + long long i = SimpleBuilder::buildSphere( + pos, + dimID, + xuid, + pattern.get(), + radius, + arg_h + ); + i = std::max(0ll, i); + output.trSuccess("worldedit.set.success", i); + }, + CommandPermissionLevel::GameMasters + ); + DynamicCommand::setup( + "hsphere", // command name + tr("worldedit.command.description.hsphere"), // command description + { + }, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Int, "radius")}, + {{"block", "radius"}, {"blockPattern", "radius"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto dimID = player->getDimensionId(); + auto pos = (origin.getWorldPosition()).toBlockPos(); - bool arg_h = true; - unsigned short radius = 0; - if (results["radius"].isSet) { - radius = (unsigned short)(results["radius"].get()); - } + bool arg_h = true; + unsigned short radius = 0; + if (results["radius"].isSet) { + radius = (unsigned short)(results["radius"].get()); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - long long i = SimpleBuilder::buildSphere(pos, dimID, xuid, pattern.get(), radius, arg_h); - i = std::max(0ll, i); - output.trSuccess("worldedit.set.success", i); - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + long long i = SimpleBuilder::buildSphere( + pos, + dimID, + xuid, + pattern.get(), + radius, + arg_h + ); + i = std::max(0ll, i); + output.trSuccess("worldedit.set.success", i); + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/HandToolCommand.cpp b/old/core/command/HandToolCommand.cpp index 55b40a1..151bf7e 100644 --- a/old/core/command/HandToolCommand.cpp +++ b/old/core/command/HandToolCommand.cpp @@ -1,160 +1,175 @@ -// -// Created by OEOTYAN on 2022/05/20. -// -#include "allCommand.hpp" #include "Globals.h" -#include "utils/StringTool.h" -#include "mc/ItemStack.hpp" #include "WorldEdit.h" -#include -#include "store/Patterns.h" +#include "allCommand.hpp" #include "brush/Brushs.h" +#include "mc/ItemStack.hpp" +#include "store/Patterns.h" +#include "utils/StringTool.h" +#include -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // tool luseface +// tool luseface - void handToolCommandSetup() { - DynamicCommand::setup( - "tool", // command name - tr("worldedit.command.description.tool"), // command description - { - // {"tree", {"tree"}}, - // {"deltree", {"deltree"}}, - {"farwand", {"farwand"}}, - {"airwand", {"airwand"}}, - // {"cycler", {"cycler"}}, - {"info", {"info"}}, - {"rep", {"rep"}}, - {"flood", {"flood"}}, - {"none", {"none"}}, - }, - { - // ParamData("tree", ParamType::Enum, "tree"), - // ParamData("deltree", ParamType::Enum, "deltree"), - ParamData("farwand", ParamType::Enum, "farwand"), - ParamData("airwand", ParamType::Enum, "airwand"), - // ParamData("cycler", ParamType::Enum, "cycler"), - ParamData("info", ParamType::Enum, "info"), - ParamData("rep", ParamType::Enum, "rep"), - ParamData("flood", ParamType::Enum, "flood"), - ParamData("none", ParamType::Enum, "none"), - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("dis", ParamType::Int, true, "dis"), - ParamData("needEdge", ParamType::Bool, true, "needEdge"), - }, - { - // {"tree"}, - // {"deltree"}, - {"farwand"}, - {"airwand"}, - // {"cycler"}, - {"info"}, - {"rep"}, - {"flood", "block", "dis", "needEdge"}, - {"flood", "blockPattern", "dis", "needEdge"}, - {"none"}, - }, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto* item = origin.getPlayer()->getHandSlot(); - std::string toolrName = item->getTypeName(); - std::string toolName = toolrName + std::to_string(item->getAuxValue()); - stringReplace(toolrName, "minecraft:", ""); - if (toolName == "") { - output.trError("worldedit.error.noitem"); - return; +void handToolCommandSetup() { + DynamicCommand::setup( + "tool", // command name + tr("worldedit.command.description.tool"), // command description + { + // {"tree", {"tree"}}, + // {"deltree", {"deltree"}}, + {"farwand", {"farwand"}}, + {"airwand", {"airwand"}}, + // {"cycler", {"cycler"}}, + {"info", {"info"} }, + {"rep", {"rep"} }, + {"flood", {"flood"} }, + {"none", {"none"} }, + }, + { + // ParamData("tree", ParamType::Enum, "tree"), + // ParamData("deltree", ParamType::Enum, "deltree"), + ParamData("farwand", ParamType::Enum, "farwand"), + ParamData("airwand", ParamType::Enum, "airwand"), + // ParamData("cycler", ParamType::Enum, "cycler"), + ParamData("info", ParamType::Enum, "info"), + ParamData("rep", ParamType::Enum, "rep"), + ParamData("flood", ParamType::Enum, "flood"), + ParamData("none", ParamType::Enum, "none"), + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("dis", ParamType::Int, true, "dis"), + ParamData("needEdge", ParamType::Bool, true, "needEdge"), + }, + { + // {"tree"}, + // {"deltree"}, + {"farwand"}, + {"airwand"}, + // {"cycler"}, + {"info"}, + {"rep"}, + {"flood", "block", "dis", "needEdge"}, + {"flood", "blockPattern", "dis", "needEdge"}, + {"none"}, + }, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto* item = origin.getPlayer()->getHandSlot(); + std::string toolrName = item->getTypeName(); + std::string toolName = toolrName + std::to_string(item->getAuxValue()); + stringReplace(toolrName, "minecraft:", ""); + if (toolName == "") { + output.trError("worldedit.error.noitem"); + return; + } + // if (results["tree"].isSet) { + // playerData.brushMap[toolName] = std::make_unique + // (TreeTool()); output.trSuccess("worldedit.tool.set.tree", toolrName); + // } else if (results["deltree"].isSet) { + // playerData.brushMap[toolName] = std::make_unique + // (DelTreeTool()); output.trSuccess("worldedit.tool.set.deltree", + // toolrName); + // } else + if (results["farwand"].isSet) { + playerData.brushMap[toolName] = std::make_unique(FarWand()); + output.trSuccess("worldedit.tool.set.farwand", toolrName); + } else if (results["airwand"].isSet) { + playerData.brushMap[toolName] = std::make_unique(AirWand()); + output.trSuccess("worldedit.tool.set.airwand", toolrName); + } + // else if (results["cycler"].isSet) { + // playerData.brushMap[toolName] = std::make_unique CyclerTool(); + // output.trSuccess("worldedit.tool.set.cycler", toolrName); + // } + else if (results["info"].isSet) { + playerData.brushMap[toolName] = std::make_unique(InfoTool()); + output.trSuccess("worldedit.tool.set.info", toolrName); + } else if (results["flood"].isSet) { + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } - // if (results["tree"].isSet) { - // playerData.brushMap[toolName] = std::make_unique (TreeTool()); - // output.trSuccess("worldedit.tool.set.tree", toolrName); - // } else if (results["deltree"].isSet) { - // playerData.brushMap[toolName] = std::make_unique (DelTreeTool()); - // output.trSuccess("worldedit.tool.set.deltree", toolrName); - // } else - if (results["farwand"].isSet) { - playerData.brushMap[toolName] = std::make_unique(FarWand()); - output.trSuccess("worldedit.tool.set.farwand", toolrName); - } else if (results["airwand"].isSet) { - playerData.brushMap[toolName] = std::make_unique(AirWand()); - output.trSuccess("worldedit.tool.set.airwand", toolrName); - } - // else if (results["cycler"].isSet) { - // playerData.brushMap[toolName] = std::make_unique CyclerTool(); - // output.trSuccess("worldedit.tool.set.cycler", toolrName); - // } - else if (results["info"].isSet) { - playerData.brushMap[toolName] = std::make_unique(InfoTool()); - output.trSuccess("worldedit.tool.set.info", toolrName); - } else if (results["flood"].isSet) { - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - int radius = 5; - if (results["dis"].isSet) { - radius = results["dis"].get(); - } - bool needEdge = false; - if (results["needEdge"].isSet) { - needEdge = results["needEdge"].get(); - } - playerData.brushMap[toolName] = std::make_unique( - FloodFillTool(Pattern::createPattern(bps, xuid), radius, needEdge)); - output.trSuccess("worldedit.tool.set.flood", toolrName); - } else if (results["rep"].isSet) { - playerData.brushMap[toolName] = std::make_unique(RepTool()); - output.trSuccess("worldedit.tool.set.rep", toolrName); - } else if (results["none"].isSet) { - if (playerData.brushMap.contains(toolName)) { - playerData.brushMap.erase(toolName); - output.trSuccess("worldedit.tool.clear", toolName); - } else { - output.trError("worldedit.error.notool"); - } + int radius = 5; + if (results["dis"].isSet) { + radius = results["dis"].get(); } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "luseface", // command name - tr("worldedit.command.description.luseface"), // command description - {}, {ParamData("bool", ParamType::Bool, "bool")}, {{"bool"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + bool needEdge = false; + if (results["needEdge"].isSet) { + needEdge = results["needEdge"].get(); } - auto* item = player->getHandSlot(); - std::string toolName = item->getTypeName() + std::to_string(item->getAuxValue()); - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); + playerData.brushMap[toolName] = std::make_unique( + FloodFillTool(Pattern::createPattern(bps, xuid), radius, needEdge) + ); + output.trSuccess("worldedit.tool.set.flood", toolrName); + } else if (results["rep"].isSet) { + playerData.brushMap[toolName] = std::make_unique(RepTool()); + output.trSuccess("worldedit.tool.set.rep", toolrName); + } else if (results["none"].isSet) { if (playerData.brushMap.contains(toolName)) { - auto& tool = playerData.brushMap[toolName]; - auto useface = results["bool"].get(); - tool->lneedFace = useface; - output.trSuccess("worldedit.tool.luseface.set", useface ? "true" : "false"); + playerData.brushMap.erase(toolName); + output.trSuccess("worldedit.tool.clear", toolName); } else { output.trError("worldedit.error.notool"); } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "luseface", // command name + tr("worldedit.command.description.luseface"), // command description + {}, + {ParamData("bool", ParamType::Bool, "bool")}, + {{"bool"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto* item = player->getHandSlot(); + std::string toolName = + item->getTypeName() + std::to_string(item->getAuxValue()); + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.brushMap.contains(toolName)) { + auto& tool = playerData.brushMap[toolName]; + auto useface = results["bool"].get(); + tool->lneedFace = useface; + output.trSuccess( + "worldedit.tool.luseface.set", + useface ? "true" : "false" + ); + } else { + output.trError("worldedit.error.notool"); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/HistoryCommand.cpp b/old/core/command/HistoryCommand.cpp index 8fe93a5..61fef06 100644 --- a/old/core/command/HistoryCommand.cpp +++ b/old/core/command/HistoryCommand.cpp @@ -1,155 +1,178 @@ -// -// Created by OEOTYAN on 2022/05/23. -// -#include "allCommand.hpp" #include "WorldEdit.h" +#include "allCommand.hpp" -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // undo redo maxhistorylength clearhistory +// undo redo maxhistorylength clearhistory - void historyCommandSetup() { - DynamicCommand::setup( - "maxhistorylength", // command name - tr("worldedit.command.description.maxhistorylength"), // command description - {}, {ParamData("num", ParamType::Int, false, "num")}, {{"num"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - playerData.maxHistoryLength = results["num"].get(); - output.trSuccess("worldedit.history.length", playerData.maxHistoryLength); - }, - CommandPermissionLevel::GameMasters); +void historyCommandSetup() { + DynamicCommand::setup( + "maxhistorylength", // command name + tr("worldedit.command.description.maxhistorylength"), // command description + {}, + {ParamData("num", ParamType::Int, false, "num")}, + {{"num"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + playerData.maxHistoryLength = results["num"].get(); + output.trSuccess("worldedit.history.length", playerData.maxHistoryLength); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "clearhistory", // command name - tr("worldedit.command.description.clearhistory"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - playerData.clearHistory(); - output.trSuccess("worldedit.clearhistory.cleared"); - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "clearhistory", // command name + tr("worldedit.command.description.clearhistory"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + playerData.clearHistory(); + output.trSuccess("worldedit.clearhistory.cleared"); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "undo", // command name - tr("worldedit.command.description.undo"), // command description - {}, {ParamData("num", ParamType::Int, true, "num")}, {{"num"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + DynamicCommand::setup( + "undo", // command name + tr("worldedit.command.description.undo"), // command description + {}, + {ParamData("num", ParamType::Int, true, "num")}, + {{"num"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + int ut = 1; + if (results["num"].isSet) { + ut = results["num"].get(); + } + for (int undoTimes = 0; undoTimes < ut; undoTimes++) { + auto uHistory = playerData.getUndoHistory(); + if (!uHistory.has_value()) { + output.trError("worldedit.undo.none"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - int ut = 1; - if (results["num"].isSet) { - ut = results["num"].get(); - } - for (int undoTimes = 0; undoTimes < ut; undoTimes++) { - auto uHistory = playerData.getUndoHistory(); - if (!uHistory.has_value()) { - output.trError("worldedit.undo.none"); - return; - } - auto& res = uHistory.value().get(); - int dimID = res.playerRelPos.x; - long long i = 0; + auto& res = uHistory.value().get(); + int dimID = res.playerRelPos.x; + long long i = 0; - Clipboard tmp(res.board); - auto blockSource = &player->getDimensionBlockSource(); - res.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = pos + res.playerPos; - auto blockInstance = blockSource->getBlockInstance(worldPos); - tmp.storeBlock(blockInstance, pos); - }); - tmp.playerRelPos.x = dimID; - tmp.playerPos = res.playerPos; + Clipboard tmp(res.board); + auto blockSource = &player->getDimensionBlockSource(); + res.forEachBlockInClipboard([&](BlockPos const& pos) { + auto worldPos = pos + res.playerPos; + auto blockInstance = blockSource->getBlockInstance(worldPos); + tmp.storeBlock(blockInstance, pos); + }); + tmp.playerRelPos.x = dimID; + tmp.playerPos = res.playerPos; - res.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = pos + res.playerPos; + res.forEachBlockInClipboard([&](BlockPos const& pos) { + auto worldPos = pos + res.playerPos; - i += res.blockslist[res.getIter(pos)].setBlockWithoutcheckGMask(worldPos, blockSource, - playerData); - }); - res = std::move(tmp); - res.used = true; - output.trSuccess("worldedit.undo.count", i); - } - output.trSuccess("worldedit.undo.undone", ut); - }, - CommandPermissionLevel::GameMasters); + i += res.blockslist[res.getIter(pos)].setBlockWithoutcheckGMask( + worldPos, + blockSource, + playerData + ); + }); + res = std::move(tmp); + res.used = true; + output.trSuccess("worldedit.undo.count", i); + } + output.trSuccess("worldedit.undo.undone", ut); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "redo", // command name - tr("worldedit.command.description.redo"), // command description - {}, {ParamData("num", ParamType::Int, true, "num")}, {{"num"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + DynamicCommand::setup( + "redo", // command name + tr("worldedit.command.description.redo"), // command description + {}, + {ParamData("num", ParamType::Int, true, "num")}, + {{"num"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + int rt = 1; + if (results["num"].isSet) { + rt = results["num"].get(); + } + for (int redoTimes = 0; redoTimes < rt; redoTimes++) { + auto rHistory = playerData.getRedoHistory(); + if (!rHistory.has_value()) { + output.trError("worldedit.redo.none"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - int rt = 1; - if (results["num"].isSet) { - rt = results["num"].get(); - } - for (int redoTimes = 0; redoTimes < rt; redoTimes++) { - auto rHistory = playerData.getRedoHistory(); - if (!rHistory.has_value()) { - output.trError("worldedit.redo.none"); - return; - } - auto& res = rHistory.value().get(); - int dimID = res.playerRelPos.x; - long long i = 0; + auto& res = rHistory.value().get(); + int dimID = res.playerRelPos.x; + long long i = 0; - Clipboard tmp(res.board); - auto blockSource = &player->getDimensionBlockSource(); - res.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = pos + res.playerPos; - auto blockInstance = blockSource->getBlockInstance(worldPos); - tmp.storeBlock(blockInstance, pos); - }); - tmp.playerRelPos.x = dimID; - tmp.playerPos = res.playerPos; + Clipboard tmp(res.board); + auto blockSource = &player->getDimensionBlockSource(); + res.forEachBlockInClipboard([&](BlockPos const& pos) { + auto worldPos = pos + res.playerPos; + auto blockInstance = blockSource->getBlockInstance(worldPos); + tmp.storeBlock(blockInstance, pos); + }); + tmp.playerRelPos.x = dimID; + tmp.playerPos = res.playerPos; - res.forEachBlockInClipboard([&](const BlockPos& pos) { - auto worldPos = pos + res.playerPos; - i += res.blockslist[res.getIter(pos)].setBlockWithoutcheckGMask(worldPos, blockSource, - playerData); - }); - res = std::move(tmp); - res.used = true; - output.trSuccess("worldedit.redo.count", i); - } - output.trSuccess("worldedit.redo.redone", rt); - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + res.forEachBlockInClipboard([&](BlockPos const& pos) { + auto worldPos = pos + res.playerPos; + i += res.blockslist[res.getIter(pos)].setBlockWithoutcheckGMask( + worldPos, + blockSource, + playerData + ); + }); + res = std::move(tmp); + res.used = true; + output.trSuccess("worldedit.redo.count", i); + } + output.trSuccess("worldedit.redo.redone", rt); + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/RegionCommand.cpp b/old/core/command/RegionCommand.cpp index ab4c4bd..d0cf8df 100644 --- a/old/core/command/RegionCommand.cpp +++ b/old/core/command/RegionCommand.cpp @@ -1,406 +1,429 @@ -// -// Created by OEOTYAN on 2022/05/17. -// -#include "allCommand.hpp" -#include #include "WorldEdit.h" +#include "allCommand.hpp" #include "region/Regions.h" +#include -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // sel pos1 pos2 hpos1 hpos2 chunk contract expand shift outset inset loftcircle +// sel pos1 pos2 hpos1 hpos2 chunk contract expand shift outset inset loftcircle - void regionCommandSetup() { - DynamicCommand::setup( - "sel", // command name - tr("worldedit.command.description.sel"), // command description - { // enums{enumName, {values...}} - {"region", {"cuboid", "extend", "poly", "sphere", "cylinder", "convex", "loft", "clear"}}, - {"remove", {"remove"}}, - {"rm", {"near", "last"}}}, - { - // parameters(type, name, [optional], [enumOptions(also - // enumName)], [identifier]) identifier: used to identify unique - // parameter data, if idnetifier is not set, - // it is set to be the same as enumOptions or name (identifier - // = enumOptions.empty() ? name:enumOptions) - ParamData("region", ParamType::Enum, "region"), - ParamData("remove", ParamType::Enum, "remove"), - ParamData("rm", ParamType::Enum, "rm"), - }, - { - // overloads{ (type == Enum ? enumOptions : name) ...} - {"region"}, - {"remove", "rm"}, // testenum +void regionCommandSetup() { + DynamicCommand::setup( + "sel", // command name + tr("worldedit.command.description.sel"), // command description + { + // enums{enumName, {values...}} + {"region", + {"cuboid", "extend", "poly", "sphere", "cylinder", "convex", "loft", "clear"} }, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - std::string action; - if (results["region"].isSet) { - action = results["region"].get(); - } else { - action = results["rm"].get(); - } + {"remove", {"remove"} }, + {"rm", {"near", "last"} } + }, + { + // parameters(type, name, [optional], [enumOptions(also + // enumName)], [identifier]) identifier: used to identify unique + // parameter data, if idnetifier is not set, + // it is set to be the same as enumOptions or name (identifier + // = enumOptions.empty() ? name:enumOptions) + ParamData("region", ParamType::Enum, "region"), + ParamData("remove", ParamType::Enum, "remove"), + ParamData("rm", ParamType::Enum, "rm"), + }, + { + // overloads{ (type == Enum ? enumOptions : name) ...} + {"region"}, + {"remove", "rm"}, // testenum + }, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + std::string action; + if (results["region"].isSet) { + action = results["region"].get(); + } else { + action = results["rm"].get(); + } - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + + if (results["remove"].isSet) { + auto dimID = origin.getPlayer()->getDimensionId(); + if (!(playerData.region != nullptr && playerData.region->hasSelected())) { + output.trError("worldedit.error.incomplete-region"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - - if (results["remove"].isSet) { - auto dimID = origin.getPlayer()->getDimensionId(); - if (!(playerData.region != nullptr && playerData.region->hasSelected())) { - output.trError("worldedit.error.incomplete-region"); + if (action == "last") { + if (playerData.region->removePoint(dimID)) { + output.trSuccess("worldedit.remove.last"); return; - } - if (action == "last") { - if (playerData.region->removePoint(dimID)) { - output.trSuccess("worldedit.remove.last"); - return; - } else { - output.trError("worldedit.remove.none"); - return; - } } else { - if (playerData.region->removePoint(dimID, (origin.getPlayer()->getPosition()).toBlockPos())) { - output.trSuccess("worldedit.remove.near"); - return; - } else { - output.trError("worldedit.remove.none"); - return; - } - } - } else if (action == "clear") { - if (playerData.region != nullptr) { - playerData.region->selecting = false; + output.trError("worldedit.remove.none"); + return; } - output.trSuccess("worldedit.region.clear"); } else { - BoundingBox tmpbox; - if (playerData.region != nullptr) { - tmpbox = playerData.region->getBoundBox(); - } - switch (do_hash2(action)) { - case do_hash2("cuboid"): - playerData.region = worldedit::Region::createRegion(worldedit::CUBOID, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.cuboid"); - break; - case do_hash2("extend"): - playerData.region = worldedit::Region::createRegion(worldedit::EXPAND, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.extend"); - break; - case do_hash2("poly"): - playerData.region = worldedit::Region::createRegion(worldedit::POLY, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.poly"); - break; - case do_hash2("sphere"): - playerData.region = worldedit::Region::createRegion(worldedit::SPHERE, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.sphere"); - break; - case do_hash2("cylinder"): - playerData.region = worldedit::Region::createRegion(worldedit::CYLINDER, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.cylinder"); - break; - case do_hash2("convex"): - playerData.region = worldedit::Region::createRegion(worldedit::CONVEX, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.convex"); - break; - case do_hash2("loft"): - playerData.region = worldedit::Region::createRegion(worldedit::LOFT, tmpbox, - origin.getPlayer()->getDimensionId()); - output.trSuccess("worldedit.region.set.loft"); - break; - default: - break; + if (playerData.region->removePoint( + dimID, + (origin.getPlayer()->getPosition()).toBlockPos() + )) { + output.trSuccess("worldedit.remove.near"); + return; + } else { + output.trError("worldedit.remove.none"); + return; } } - playerData.mainPosDim = -1; - playerData.vicePosDim = -1; - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "pos1", // command name - tr("worldedit.command.description.pos1"), // command description - {}, {ParamData("pos", ParamType::BlockPos, true, "pos")}, {{"pos"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + } else if (action == "clear") { + if (playerData.region != nullptr) { + playerData.region->selecting = false; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - BlockInstance blockInstance; - if (results["pos"].isSet) { - auto pos = results["pos"].get(); - blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); - } else { - blockInstance = - Level::getBlockInstance((origin.getWorldPosition()).toBlockPos(), player->getDimensionId()); + output.trSuccess("worldedit.region.clear"); + } else { + BoundingBox tmpbox; + if (playerData.region != nullptr) { + tmpbox = playerData.region->getBoundBox(); } - playerData.changeMainPos(blockInstance); - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "pos2", // command name - tr("worldedit.command.description.pos2"), // command description - {}, {ParamData("pos", ParamType::BlockPos, true, "pos")}, {{"pos"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - BlockInstance blockInstance; - if (results["pos"].isSet) { - auto pos = results["pos"].get(); - blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); - } else { - blockInstance = - Level::getBlockInstance((origin.getWorldPosition()).toBlockPos(), player->getDimensionId()); + switch (do_hash2(action)) { + case do_hash2("cuboid"): + playerData.region = worldedit::Region::createRegion( + worldedit::CUBOID, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.cuboid"); + break; + case do_hash2("extend"): + playerData.region = worldedit::Region::createRegion( + worldedit::EXPAND, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.extend"); + break; + case do_hash2("poly"): + playerData.region = worldedit::Region::createRegion( + worldedit::POLY, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.poly"); + break; + case do_hash2("sphere"): + playerData.region = worldedit::Region::createRegion( + worldedit::SPHERE, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.sphere"); + break; + case do_hash2("cylinder"): + playerData.region = worldedit::Region::createRegion( + worldedit::CYLINDER, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.cylinder"); + break; + case do_hash2("convex"): + playerData.region = worldedit::Region::createRegion( + worldedit::CONVEX, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.convex"); + break; + case do_hash2("loft"): + playerData.region = worldedit::Region::createRegion( + worldedit::LOFT, + tmpbox, + origin.getPlayer()->getDimensionId() + ); + output.trSuccess("worldedit.region.set.loft"); + break; + default: + break; } - playerData.changeVicePos(blockInstance); - }, - CommandPermissionLevel::GameMasters); + } + playerData.mainPosDim = -1; + playerData.vicePosDim = -1; + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "hpos1", // command name - tr("worldedit.command.description.hpos1"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - BlockInstance blockInstance; - blockInstance = player->getBlockFromViewVector(true, false, 2048.0f, true, false); - playerData.changeMainPos(blockInstance); - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "pos1", // command name + tr("worldedit.command.description.pos1"), // command description + {}, + {ParamData("pos", ParamType::BlockPos, true, "pos")}, + {{"pos"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + BlockInstance blockInstance; + if (results["pos"].isSet) { + auto pos = results["pos"].get(); + blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); + } else { + blockInstance = Level::getBlockInstance( + (origin.getWorldPosition()).toBlockPos(), + player->getDimensionId() + ); + } + playerData.changeMainPos(blockInstance); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "hpos2", // command name - tr("worldedit.command.description.hpos2"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - BlockInstance blockInstance; - blockInstance = player->getBlockFromViewVector(true, false, 2048.0f, true, false); - playerData.changeVicePos(blockInstance); - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "pos2", // command name + tr("worldedit.command.description.pos2"), // command description + {}, + {ParamData("pos", ParamType::BlockPos, true, "pos")}, + {{"pos"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + BlockInstance blockInstance; + if (results["pos"].isSet) { + auto pos = results["pos"].get(); + blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); + } else { + blockInstance = Level::getBlockInstance( + (origin.getWorldPosition()).toBlockPos(), + player->getDimensionId() + ); + } + playerData.changeVicePos(blockInstance); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "chunk", // command name - tr("worldedit.command.description.chunk"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - auto heightRange = player->getDimensionConst().getHeightRange(); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - playerData.region = nullptr; - } - BlockPos pos = (origin.getWorldPosition()).toBlockPos(); - pos.x = (pos.x >> 4) << 4; - pos.z = (pos.z >> 4) << 4; - pos.y = heightRange.min; + DynamicCommand::setup( + "hpos1", // command name + tr("worldedit.command.description.hpos1"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + BlockInstance blockInstance; + blockInstance = + player->getBlockFromViewVector(true, false, 2048.0f, true, false); + playerData.changeMainPos(blockInstance); + }, + CommandPermissionLevel::GameMasters + ); - BlockInstance blockInstance; - blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); - playerData.changeMainPos(blockInstance, false); + DynamicCommand::setup( + "hpos2", // command name + tr("worldedit.command.description.hpos2"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + BlockInstance blockInstance; + blockInstance = + player->getBlockFromViewVector(true, false, 2048.0f, true, false); + playerData.changeVicePos(blockInstance); + }, + CommandPermissionLevel::GameMasters + ); - pos.x += 15; - pos.z += 15; - pos.y = heightRange.max - 1; - blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); - playerData.changeVicePos(blockInstance, false); + DynamicCommand::setup( + "chunk", // command name + tr("worldedit.command.description.chunk"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + auto heightRange = player->getDimensionConst().getHeightRange(); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + playerData.region = nullptr; + } + BlockPos pos = (origin.getWorldPosition()).toBlockPos(); + pos.x = (pos.x >> 4) << 4; + pos.z = (pos.z >> 4) << 4; + pos.y = heightRange.min; - output.trSuccess("worldedit.chunk.success"); - }, - CommandPermissionLevel::GameMasters); + BlockInstance blockInstance; + blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); + playerData.changeMainPos(blockInstance, false); - DynamicCommand::setup( - "contract", // command name - tr("worldedit.command.description.contract"), // command description - { - {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, - }, - { - ParamData("dir", ParamType::Enum, true, "dir"), - ParamData("num", ParamType::Int, false, "num"), - ParamData("numback", ParamType::Int, true, "numback"), - }, - {{"num", "dir", "numback"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int l = results["num"].get(); - worldedit::FACING facing; - if (results["dir"].isSet) { - auto str = results["dir"].getRaw(); - if (str == "me") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } else if (str == "back") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - facing = worldedit::invFacing(facing); - } else { - facing = worldedit::dirStringToFacing(str); - } - } else { + pos.x += 15; + pos.z += 15; + pos.y = heightRange.max - 1; + blockInstance = Level::getBlockInstance(pos, player->getDimensionId()); + playerData.changeVicePos(blockInstance, false); + + output.trSuccess("worldedit.chunk.success"); + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "contract", // command name + tr("worldedit.command.description.contract"), // command description + { + {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, + }, + { + ParamData("dir", ParamType::Enum, true, "dir"), + ParamData("num", ParamType::Int, false, "num"), + ParamData("numback", ParamType::Int, true, "numback"), + }, + {{"num", "dir", "numback"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int l = results["num"].get(); + worldedit::FACING facing; + if (results["dir"].isSet) { + auto str = results["dir"].getRaw(); + if (str == "me") { facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } - std::vector list; - list.resize(0); - list.push_back(worldedit::facingToPos(facing, l)); - if (results["numback"].isSet) { - list.push_back( - worldedit::facingToPos(worldedit::invFacing(facing), results["numback"].get())); - } - auto res = playerData.region->contract(list); - if (res.second) { - output.trSuccess(res.first); + } else if (str == "back") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + facing = worldedit::invFacing(facing); } else { - output.trError(res.first); + facing = worldedit::dirStringToFacing(str); } } else { - output.trError("worldedit.error.incomplete-region"); + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "expand", // command name - tr("worldedit.command.description.expand"), // command description - {{"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, {"vert", {"vert"}}}, - { - ParamData("dir", ParamType::Enum, true, "dir"), - ParamData("num", ParamType::Int, false, "num"), - ParamData("numback", ParamType::Int, true, "numback"), - ParamData("vert", ParamType::Enum, "vert"), - }, - {{"num", "dir", "numback"}, {"vert"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + std::vector list; + list.resize(0); + list.push_back(worldedit::facingToPos(facing, l)); + if (results["numback"].isSet) { + list.push_back(worldedit::facingToPos( + worldedit::invFacing(facing), + results["numback"].get() + )); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - std::vector list; - list.resize(0); - if (results["vert"].isSet) { - auto heightRange = player->getDimensionConst().getHeightRange(); - auto& region = playerData.region; - auto boundingBox = region->getBoundBox(); - list.push_back(BlockPos(0, std::min(heightRange.min - boundingBox.min.y, 0), 0)); - list.push_back(BlockPos(0, std::max(heightRange.max - boundingBox.max.y - 1, 0), 0)); - } else { - int l = results["num"].get(); - worldedit::FACING facing; - if (results["dir"].isSet) { - auto str = results["dir"].getRaw(); - if (str == "me") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } else if (str == "back") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - facing = worldedit::invFacing(facing); - } else { - facing = worldedit::dirStringToFacing(str); - } - } else { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } - list.push_back(worldedit::facingToPos(facing, l)); - if (results["numback"].isSet) { - list.push_back( - worldedit::facingToPos(worldedit::invFacing(facing), results["numback"].get())); - } - } - auto res = playerData.region->expand(list); - if (res.second) { - output.trSuccess(res.first); - } else { - output.trError(res.first); - } + auto res = playerData.region->contract(list); + if (res.second) { + output.trSuccess(res.first); } else { - output.trError("worldedit.error.incomplete-region"); + output.trError(res.first); } - }, - CommandPermissionLevel::GameMasters); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "shift", // command name - tr("worldedit.command.description.shift"), // command description - { - {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, - }, - {ParamData("dir", ParamType::Enum, true, "dir"), ParamData("num", ParamType::Int, false, "num")}, - {{"num", "dir"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int l = results["num"].get(); + DynamicCommand::setup( + "expand", // command name + tr("worldedit.command.description.expand"), // command description + { + {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, + {"vert", {"vert"} } + }, + { + ParamData("dir", ParamType::Enum, true, "dir"), + ParamData("num", ParamType::Int, false, "num"), + ParamData("numback", ParamType::Int, true, "numback"), + ParamData("vert", ParamType::Enum, "vert"), + }, + {{"num", "dir", "numback"}, {"vert"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + std::vector list; + list.resize(0); + if (results["vert"].isSet) { + auto heightRange = player->getDimensionConst().getHeightRange(); + auto& region = playerData.region; + auto boundingBox = region->getBoundBox(); + list.push_back( + BlockPos(0, std::min(heightRange.min - boundingBox.min.y, 0), 0) + ); + list.push_back(BlockPos( + 0, + std::max(heightRange.max - boundingBox.max.y - 1, 0), + 0 + )); + } else { + int l = results["num"].get(); worldedit::FACING facing; if (results["dir"].isSet) { auto str = results["dir"].getRaw(); @@ -415,159 +438,242 @@ namespace worldedit { } else { facing = worldedit::dirToFacing(player->getViewVector(1.0f)); } - auto res = playerData.region->shift(worldedit::facingToPos(facing, l)); - if (res.second) { - output.trSuccess(res.first); - } else { - output.trError(res.first); + list.push_back(worldedit::facingToPos(facing, l)); + if (results["numback"].isSet) { + list.push_back(worldedit::facingToPos( + worldedit::invFacing(facing), + results["numback"].get() + )); } + } + auto res = playerData.region->expand(list); + if (res.second) { + output.trSuccess(res.first); } else { - output.trError("worldedit.error.incomplete-region"); + output.trError(res.first); } - }, - CommandPermissionLevel::GameMasters); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "outset", // command name - tr("worldedit.command.description.outset"), // command description - {}, - {ParamData("args", ParamType::SoftEnum, true, - "-hv" - "-hv"), - ParamData("num", ParamType::Int, false, "num")}, - {{"num", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int l = results["num"].get(); - std::vector list; - list.resize(0); - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str == "-h") { - list.push_back({0, 0, -l}); - list.push_back({0, 0, l}); - list.push_back({-l, 0, 0}); - list.push_back({l, 0, 0}); - } else if (str == "-v") { - list.push_back({0, -l, 0}); - list.push_back({0, l, 0}); - } else { - output.trError("worldedit.command.error.args", str); - return; - } + DynamicCommand::setup( + "shift", // command name + tr("worldedit.command.description.shift"), // command description + { + {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, + }, + {ParamData("dir", ParamType::Enum, true, "dir"), + ParamData("num", ParamType::Int, false, "num")}, + {{"num", "dir"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int l = results["num"].get(); + worldedit::FACING facing; + if (results["dir"].isSet) { + auto str = results["dir"].getRaw(); + if (str == "me") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } else if (str == "back") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + facing = worldedit::invFacing(facing); } else { + facing = worldedit::dirStringToFacing(str); + } + } else { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } + auto res = playerData.region->shift(worldedit::facingToPos(facing, l)); + if (res.second) { + output.trSuccess(res.first); + } else { + output.trError(res.first); + } + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "outset", // command name + tr("worldedit.command.description.outset"), // command description + { + }, + {ParamData( + "args", + ParamType::SoftEnum, + true, + "-hv" + "-hv" + ), + ParamData("num", ParamType::Int, false, "num")}, + {{"num", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int l = results["num"].get(); + std::vector list; + list.resize(0); + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str == "-h") { + list.push_back({0, 0, -l}); + list.push_back({0, 0, l}); list.push_back({-l, 0, 0}); list.push_back({l, 0, 0}); + } else if (str == "-v") { list.push_back({0, -l, 0}); list.push_back({0, l, 0}); - list.push_back({0, 0, -l}); - list.push_back({0, 0, l}); - } - auto res = playerData.region->expand(list); - if (res.second) { - output.trSuccess(res.first); } else { - output.trError(res.first); + output.trError("worldedit.command.error.args", str); + return; } } else { - output.trError("worldedit.error.incomplete-region"); + list.push_back({-l, 0, 0}); + list.push_back({l, 0, 0}); + list.push_back({0, -l, 0}); + list.push_back({0, l, 0}); + list.push_back({0, 0, -l}); + list.push_back({0, 0, l}); } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "inset", // command name - tr("worldedit.command.description.inset"), // command description - {}, - {ParamData("args", ParamType::SoftEnum, true, - "-hv" - "-hv"), - ParamData("num", ParamType::Int, false, "num")}, - {{"num", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + auto res = playerData.region->expand(list); + if (res.second) { + output.trSuccess(res.first); + } else { + output.trError(res.first); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int l = results["num"].get(); - std::vector list; - list.resize(0); - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str == "-h") { - list.push_back({0, 0, -l}); - list.push_back({0, 0, l}); - list.push_back({-l, 0, 0}); - list.push_back({l, 0, 0}); - } else if (str == "-v") { - list.push_back({0, -l, 0}); - list.push_back({0, l, 0}); - } else { - output.trError("worldedit.command.error.args", str); - return; - } - } else { + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "inset", // command name + tr("worldedit.command.description.inset"), // command description + { + }, + {ParamData( + "args", + ParamType::SoftEnum, + true, + "-hv" + "-hv" + ), + ParamData("num", ParamType::Int, false, "num")}, + {{"num", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int l = results["num"].get(); + std::vector list; + list.resize(0); + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str == "-h") { + list.push_back({0, 0, -l}); + list.push_back({0, 0, l}); list.push_back({-l, 0, 0}); list.push_back({l, 0, 0}); + } else if (str == "-v") { list.push_back({0, -l, 0}); list.push_back({0, l, 0}); - list.push_back({0, 0, -l}); - list.push_back({0, 0, l}); - } - auto res = playerData.region->contract(list); - if (res.second) { - output.trSuccess(res.first); } else { - output.trError(res.first); + output.trError("worldedit.command.error.args", str); + return; } } else { - output.trError("worldedit.error.incomplete-region"); + list.push_back({-l, 0, 0}); + list.push_back({l, 0, 0}); + list.push_back({0, -l, 0}); + list.push_back({0, l, 0}); + list.push_back({0, 0, -l}); + list.push_back({0, 0, l}); } - }, - CommandPermissionLevel::GameMasters); + auto res = playerData.region->contract(list); + if (res.second) { + output.trSuccess(res.first); + } else { + output.trError(res.first); + } + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "loftcircle", // command name - tr("worldedit.command.description.loftcircle"), // command description - {}, {ParamData("bool", ParamType::Bool, "bool")}, {{"bool"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + DynamicCommand::setup( + "loftcircle", // command name + tr("worldedit.command.description.loftcircle"), // command description + {}, + {ParamData("bool", ParamType::Bool, "bool")}, + {{"bool"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + if (region->regionType != LOFT) { + output.trError("worldedit.loftcircle.invalid-type"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - if (region->regionType != LOFT) { - output.trError("worldedit.loftcircle.invalid-type"); - return; - } - bool arg = results["bool"].get(); - static_cast(region.get())->setCircle(arg); - output.trSuccess("worldedit.loftcircle.success", (arg ? "true" : "false")); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + bool arg = results["bool"].get(); + static_cast(region.get())->setCircle(arg); + output.trSuccess( + "worldedit.loftcircle.success", + (arg ? "true" : "false") + ); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/RegionInfoCommand.cpp b/old/core/command/RegionInfoCommand.cpp index 591a7e0..60b1bf7 100644 --- a/old/core/command/RegionInfoCommand.cpp +++ b/old/core/command/RegionInfoCommand.cpp @@ -1,322 +1,387 @@ -// -// Created by OEOTYAN on 2022/05/18. -// +#include "WorldEdit.h" #include "allCommand.hpp" -#include -#include -#include -#include -#include "utils/StringTool.h" #include "mc/ItemStack.hpp" -#include "WorldEdit.h" #include "region/Regions.h" +#include "utils/StringTool.h" +#include #include -namespace worldedit { - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +#include +#include +#include +namespace we { +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - // resendpack size count distr +// resendpack size count distr - void regionInfoCommandSetup() { - DynamicCommand::setup( - "resendpack", // command name - tr("worldedit.command.description.resendpack"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto blockSource = &player->getDimensionBlockSource(); +void regionInfoCommandSetup() { + DynamicCommand::setup( + "resendpack", // command name + tr("worldedit.command.description.resendpack"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto blockSource = &player->getDimensionBlockSource(); - region->forEachBlockInRegion([&](BlockPos const& pos) { - auto exblock = &blockSource->getExtraBlock(pos); - auto block = &blockSource->getBlock(pos); - auto be = blockSource->getBlockEntity(pos); - std::unique_ptr bepacket = nullptr; - if (be) { - bepacket = be->getServerUpdatePacket(*blockSource); - } + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto exblock = &blockSource->getExtraBlock(pos); + auto block = &blockSource->getBlock(pos); + auto be = blockSource->getBlockEntity(pos); + std::unique_ptr bepacket = nullptr; + if (be) { + bepacket = be->getServerUpdatePacket(*blockSource); + } - blockSource->getDimension().forEachPlayer([&](Player& player) -> bool { - player.sendUpdateBlockPacket(pos, *exblock, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockLiquid); - player.sendUpdateBlockPacket(pos, *block, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockDefault); + blockSource->getDimension().forEachPlayer( + [&](Player& player) -> bool { + player.sendUpdateBlockPacket( + pos, + *exblock, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockLiquid + ); + player.sendUpdateBlockPacket( + pos, + *block, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockDefault + ); if (bepacket != nullptr) { player.sendNetworkPacket(*(bepacket.get())); } - player.sendUpdateBlockPacket(pos, *exblock, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockLiquid); + player.sendUpdateBlockPacket( + pos, + *exblock, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockLiquid + ); return true; - }); - }); + } + ); + }); - output.trSuccess("worldedit.resendpack.success"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); + output.trSuccess("worldedit.resendpack.success"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "size", // command name - tr("worldedit.command.description.size"), // command description - {}, {ParamData("args", ParamType::SoftEnum, true, "-ca", "-ca")}, {{"args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto blockSource = &player->getDimensionBlockSource(); - long long size = 0; - bool arg_a = false, arg_c = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("a") != std::string::npos) { - arg_a = true; - } - if (str.find("c") != std::string::npos) { - arg_c = true; - } + DynamicCommand::setup( + "size", // command name + tr("worldedit.command.description.size"), // command description + {}, + {ParamData("args", ParamType::SoftEnum, true, "-ca", "-ca")}, + {{"args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto blockSource = &player->getDimensionBlockSource(); + long long size = 0; + bool arg_a = false, arg_c = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - if (!arg_c) { - if (arg_a) { - playerData.region->forEachBlockInRegion([&](const BlockPos& pos) { size++; }); - } else { - auto dimID = playerData.region->getDimensionID(); - playerData.region->forEachBlockInRegion([&](const BlockPos& pos) { - auto block = &blockSource->getBlock(pos); - if (!(block == BedrockBlocks::mAir)) - size++; - }); - } + if (str.find("a") != std::string::npos) { + arg_a = true; + } + if (str.find("c") != std::string::npos) { + arg_c = true; + } + } + if (!arg_c) { + if (arg_a) { + playerData.region->forEachBlockInRegion([&](BlockPos const& pos) { + size++; + }); } else { - // clipboard + auto dimID = playerData.region->getDimensionID(); + playerData.region->forEachBlockInRegion([&](BlockPos const& pos) { + auto block = &blockSource->getBlock(pos); + if (!(block == BedrockBlocks::mAir)) size++; + }); } - output.trSuccess("worldedit.size.success", size); } else { - output.trError("worldedit.error.incomplete-region"); + // clipboard } - }, - CommandPermissionLevel::GameMasters); + output.trSuccess("worldedit.size.success", size); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "count", // command name - tr("worldedit.command.description.count"), // command description - { - {"-c", {"-c"}}, - }, - {ParamData("args", ParamType::SoftEnum, true, "-c", "-c"), ParamData("block", ParamType::Block, "block"), - ParamData("data", ParamType::Int, true, "data")}, - {{"block", "data", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); + DynamicCommand::setup( + "count", // command name + tr("worldedit.command.description.count"), // command description + { + {"-c", {"-c"}}, + }, + {ParamData("args", ParamType::SoftEnum, true, "-c", "-c"), + ParamData("block", ParamType::Block, "block"), + ParamData("data", ParamType::Int, true, "data")}, + {{"block", "data", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - int data = -1; - if (results["data"].isSet) { - data = results["data"].getRaw(); - } - auto blockname = results["block"] - .get() - .resolveBlock(data >= 0 ? data : 0) - .getBlock() - ->getTypeName(); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto blockSource = &player->getDimensionBlockSource(); - long long count = 0; - if (results["args"].isSet) { - // clipboard - } else { - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto block =&blockSource->getBlock(pos); - if (block->getTypeName() == blockname) { - if (data == -1 || data == (int)(block->getTileData())) - count++; - } - }); - } - output.trSuccess("worldedit.count.success", count); + auto& playerData = getPlayersData(xuid); + int data = -1; + if (results["data"].isSet) { + data = results["data"].getRaw(); + } + auto blockname = results["block"] + .get() + .resolveBlock(data >= 0 ? data : 0) + .getBlock() + ->getTypeName(); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto blockSource = &player->getDimensionBlockSource(); + long long count = 0; + if (results["args"].isSet) { + // clipboard } else { - output.trError("worldedit.error.incomplete-region"); + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto block = &blockSource->getBlock(pos); + if (block->getTypeName() == blockname) { + if (data == -1 || data == (int)(block->getTileData())) + count++; + } + }); } - }, - CommandPermissionLevel::GameMasters); + output.trSuccess("worldedit.count.success", count); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "distr", // command name - tr("worldedit.command.description.distr"), // command description - {}, {ParamData("args", ParamType::SoftEnum, true, "-cd", "-cd")}, {{"args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + DynamicCommand::setup( + "distr", // command name + tr("worldedit.command.description.distr"), // command description + {}, + {ParamData("args", ParamType::SoftEnum, true, "-cd", "-cd")}, + {{"args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + + auto& playerData = getPlayersData(xuid); + bool arg_d = false, arg_c = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); return; } - auto xuid = player->getXuid(); - - auto& playerData = getPlayersData(xuid); - bool arg_d = false, arg_c = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("d") != std::string::npos) { - arg_d = true; - } - if (str.find("c") != std::string::npos) { - arg_c = true; - } + if (str.find("d") != std::string::npos) { + arg_d = true; + } + if (str.find("c") != std::string::npos) { + arg_c = true; } + } - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto blockSource = &player->getDimensionBlockSource(); - phmap::flat_hash_map blocksMap; - std::vector> blocksMap2; - blocksMap2.resize(0); - long long all = 0; - if (arg_c) { - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto blockInstance = blockSource->getBlockInstance(pos); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto blockSource = &player->getDimensionBlockSource(); + phmap::flat_hash_map blocksMap; + std::vector> blocksMap2; + blocksMap2.resize(0); + long long all = 0; + if (arg_c) { + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto blockInstance = blockSource->getBlockInstance(pos); - if (blockInstance.hasContainer()) { - auto container = blockInstance.getContainer(); - std::queue> itemQueue; - for (auto& item : container->getAllSlots()) { - if (item->getCount() > 0) { - itemQueue.emplace(const_cast(item)->getNbt()); - } + if (blockInstance.hasContainer()) { + auto container = blockInstance.getContainer(); + std::queue> itemQueue; + for (auto& item : container->getAllSlots()) { + if (item->getCount() > 0) { + itemQueue.emplace( + const_cast(item)->getNbt() + ); } - while (!itemQueue.empty()) { - auto* item = ItemStack::create(std::move(itemQueue.front())); - itemQueue.pop(); - auto count = item->getCount(); - if (count > 0) { - all += count; - std::string name; - if (item->isBlock()) { - auto block = item->getBlock(); - name = block->getTypeName(); - if (arg_d) { - auto states = - block->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - name += " [" + states.substr(1, states.length() - 2) + "]"; - } - } else { - name = item->getTypeName(); - if (arg_d) { - name += " ["; - auto customName = item->getCustomName(); - if (customName != "") { - name += "\"name\":\"" + customName + "\""; - } - name += "]"; - } + } + while (!itemQueue.empty()) { + auto* item = + ItemStack::create(std::move(itemQueue.front())); + itemQueue.pop(); + auto count = item->getCount(); + if (count > 0) { + all += count; + std::string name; + if (item->isBlock()) { + auto block = item->getBlock(); + name = block->getTypeName(); + if (arg_d) { + auto states = + block->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + name += " [" + + states.substr(1, states.length() - 2) + + "]"; } - if (!blocksMap.contains(name)) { - blocksMap[name] = 0; + } else { + name = item->getTypeName(); + if (arg_d) { + name += " ["; + auto customName = item->getCustomName(); + if (customName != "") { + name += "\"name\":\"" + customName + "\""; + } + name += "]"; } - blocksMap[name] += count; + } + if (!blocksMap.contains(name)) { + blocksMap[name] = 0; + } + blocksMap[name] += count; - auto iNbt = item->getNbt(); - if (iNbt->contains("tag", Tag::Type::Compound) && - iNbt->getCompound("tag")->contains("Items", Tag::Type::List)) { - iNbt->getCompound("tag")->getList("Items")->forEachCompoundTag( + auto iNbt = item->getNbt(); + if (iNbt->contains("tag", Tag::Type::Compound) + && iNbt->getCompound("tag") + ->contains("Items", Tag::Type::List)) { + iNbt->getCompound("tag") + ->getList("Items") + ->forEachCompoundTag( [&](class CompoundTag const& mItem) { itemQueue.emplace(mItem.clone()); - }); - } + } + ); } - delete item; - item = nullptr; } + delete item; + item = nullptr; } - }); - } else { - region->forEachBlockInRegion([&](const BlockPos& pos) { - all++; - auto block = &blockSource->getBlock(pos); - std::string blockName = block->getTypeName(); + } + }); + } else { + region->forEachBlockInRegion([&](BlockPos const& pos) { + all++; + auto block = &blockSource->getBlock(pos); + std::string blockName = block->getTypeName(); - if (arg_d) { - auto states = block->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - blockName += " [" + states.substr(1, states.length() - 2) + "]"; - } - auto exBlock = &blockSource->getExtraBlock(pos); - if (!(exBlock == BedrockBlocks::mAir)) { - blockName += " & " + exBlock->getTypeName(); + if (arg_d) { + auto states = block->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + blockName += + " [" + states.substr(1, states.length() - 2) + "]"; + } + auto exBlock = &blockSource->getExtraBlock(pos); + if (!(exBlock == BedrockBlocks::mAir)) { + blockName += " & " + exBlock->getTypeName(); - if (arg_d) { - auto exStates = exBlock->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - blockName += +" [" + exStates.substr(1, exStates.length() - 2) + "]"; - } - } - if (blocksMap.contains(blockName)) { - blocksMap[blockName] += 1; - } else { - blocksMap[blockName] = 1; + if (arg_d) { + auto exStates = exBlock->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + blockName += +" [" + + exStates.substr(1, exStates.length() - 2) + + "]"; } - }); - } - for (auto& block : blocksMap) { - std::string name = block.first; - worldedit::stringReplace(name, "minecraft:", ""); - blocksMap2.emplace_back(std::pair(name, block.second)); - } - std::sort(blocksMap2.begin(), blocksMap2.end(), - [](const std::pair& a, - const std::pair& b) { return a.second > b.second; }); - std::string res(fmt::format(tr("worldedit.distr.total"), all)); - for (auto& block : blocksMap2) { - res += fmt::format("\n§b{} §6({}%%) §f{}", block.second, - worldedit::fto_string( - static_cast(block.second) / static_cast(all) * 100.0, 3), - block.first); + } + if (blocksMap.contains(blockName)) { + blocksMap[blockName] += 1; + } else { + blocksMap[blockName] = 1; + } + }); + } + for (auto& block : blocksMap) { + std::string name = block.first; + worldedit::stringReplace(name, "minecraft:", ""); + blocksMap2.emplace_back( + std::pair(name, block.second) + ); + } + std::sort( + blocksMap2.begin(), + blocksMap2.end(), + [](const std::pair& a, + const std::pair& b) { + return a.second > b.second; } - output.trSuccess(res); - } else { - output.trError("worldedit.error.incomplete-region"); + ); + std::string res(fmt::format(tr("worldedit.distr.total"), all)); + for (auto& block : blocksMap2) { + res += fmt::format( + "\n§b{} §6({}%%) §f{}", + block.second, + worldedit::fto_string( + static_cast(block.second) / static_cast(all) + * 100.0, + 3 + ), + block.first + ); } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + output.trSuccess(res); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/RegionOperationCommand.cpp b/old/core/command/RegionOperationCommand.cpp index ae84786..1fafe28 100644 --- a/old/core/command/RegionOperationCommand.cpp +++ b/old/core/command/RegionOperationCommand.cpp @@ -1,76 +1,268 @@ -// -// Created by OEOTYAN on 2022/05/27. -// -#include "mc/ItemInstance.hpp" +#include "WorldEdit.h" #include "allCommand.hpp" -#include "store/Patterns.h" -#include "store/BlockNBTSet.hpp" -#include "eval/blur.hpp" -#include "image/Image.h" #include "eval/Bresenham.hpp" +#include "eval/blur.hpp" #include "filesys/download.h" -#include "mc/StructureTemplate.hpp" +#include "image/Image.h" +#include "mc/CompoundTag.hpp" #include "mc/Container.hpp" +#include "mc/ItemInstance.hpp" #include "mc/ItemStack.hpp" -#include "mc/CompoundTag.hpp" -#include "mc/StaticVanillaBlocks.hpp" -#include #include "mc/ListTag.hpp" -#include "WorldEdit.h" +#include "mc/StaticVanillaBlocks.hpp" +#include "mc/StructureTemplate.hpp" #include "region/Regions.h" +#include "store/BlockNBTSet.hpp" +#include "store/Patterns.h" #include "utils/RNG.h" +#include + +namespace we { + +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; + +// set line rep center stack move gen walls faces overlay naturalize hollow +// smooth image curve | deform + +void regionOperationCommandSetup() { + DynamicCommand::setup( + "set", // command name + tr("worldedit.command.description.set"), // command description + {}, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, + {{"block"}, {"blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } -namespace worldedit { - - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; - - // set line rep center stack move gen walls faces overlay naturalize hollow - // smooth image curve | deform - - void regionOperationCommandSetup() { - DynamicCommand::setup( - "set", // command name - tr("worldedit.command.description.set"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, - {{"block"}, {"blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + i += pattern->setBlock(variables, f, blockSource, pos); + }); + + output.trSuccess("worldedit.set.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "rope", // command name + tr("worldedit.command.description.rope"), // command description + { + }, + { + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("extraLength", ParamType::Float, true, "extraLength"), + ParamData("radius", ParamType::Float, true, "radius"), + ParamData("args", ParamType::SoftEnum, true, "-h", "-h"), + }, + {{"block", "extraLength", "radius", "args"}, + {"blockPattern", "extraLength", "radius", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + + if (region->regionType != RegionType::CUBOID + && region->regionType != CONVEX) { + output.trError("worldedit.rope.invalid-type"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + double extraLength = 20; + if (results["extraLength"].isSet) { + extraLength = results["extraLength"].get(); + } + extraLength = 1.0 + extraLength / 100.0; + + float radius = 0; + if (results["radius"].isSet) { + radius = results["radius"].get(); + } + + bool arg_h = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; + } + if (str.find("h") != std::string::npos) { + arg_h = true; + } + } + + try { + phmap::flat_hash_set tmp; + region->forEachLine([&](BlockPos const& pos1, BlockPos const& pos2) { + if (extraLength > 1 && (pos1.x != pos2.x || pos1.z != pos2.z)) { + double d = pos1.distanceTo(pos2); + double dh = + sqrt(pow2(pos1.x - pos2.x) + pow2(pos1.z - pos2.z)); + double h = pos2.y - pos1.y; + double L = d * extraLength; + double a = getCatenaryParameter(dh, h, L); + double x0 = (a * log((L - h) / (L + h)) - dh) * 0.5; + double y0 = a * cosh(x0 / a); + int dx = pos2.x - pos1.x; + int dz = pos2.z - pos1.z; + x0 += dh; + y0 -= h; + double df = 1.0 / (10 * L); + for (double i = 0; i <= 1; i += df) { + double kx, kz, ky = a * cosh((i * dh - x0) / a) - y0; + ky += pos1.y; + kx = pos1.x + dx * i; + kz = pos1.z + dz * i; + BlockPos kpos = { + static_cast(std::floor(kx + 0.5)), + static_cast(std::floor(ky + 0.5)), + static_cast(std::floor(kz + 0.5)) + }; + if (radius == 0) { + tmp.insert(kpos); + boundingBox.merge(kpos); + } else { + BoundingBox( + kpos - static_cast(radius + 1), + kpos + static_cast(radius + 1) + ) + .forEachBlockInBox([&](BlockPos const& posk) { + if (sqrt( + pow2(posk.x - kx) + pow2(posk.y - ky) + + pow2(posk.z - kz) + ) + <= 0.5 + radius) { + tmp.insert(posk); + boundingBox.merge(posk); + } + }); + } + } + } else { + plotLine(pos1, pos2, [&](BlockPos const& pos) { + BoundingBox( + pos - static_cast(radius + 1), + pos + static_cast(radius + 1) + ) + .forEachBlockInBox([&](BlockPos const& posk) { + if ((pos - posk).length() <= 0.5 + radius) { + tmp.insert(posk); + boundingBox.merge(posk); + } + }); + }); + } + }); if (playerData.maxHistoryLength > 0) { auto& history = playerData.getNextHistory(); history = std::move(Clipboard(boundingBox.max - boundingBox.min)); history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; + history.playerPos = boundingBox.min; - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; auto blockInstance = blockSource->getBlockInstance(pos); history.storeBlock(blockInstance, localPos); }); } + if (arg_h) { + phmap::flat_hash_set tmp2; + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + if (tmp.contains(pos)) { + int counts = 0; + + for (auto& calPos : pos.getNeighbors()) { + if (tmp.contains(calPos)) { + counts++; + } + } + if (counts < 6) tmp2.insert(pos); + } + }); + tmp = std::move(tmp2); + } + long long i = 0; auto playerPos = origin.getWorldPosition(); auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); ; + EvalFunctions f; f.setbs(blockSource); f.setbox(boundingBox); @@ -81,784 +273,621 @@ namespace worldedit { if (results["blockPattern"].isSet) { bps = results["blockPattern"].get(); } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } auto pattern = Pattern::createPattern(bps, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { + for (auto& pos : tmp) { setFunction(variables, f, boundingBox, playerPos, pos, center); i += pattern->setBlock(variables, f, blockSource, pos); - }); + } - output.trSuccess("worldedit.set.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "rope", // command name - tr("worldedit.command.description.rope"), // command description - {}, - { - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("extraLength", ParamType::Float, true, "extraLength"), - ParamData("radius", ParamType::Float, true, "radius"), - ParamData("args", ParamType::SoftEnum, true, "-h", "-h"), - }, - {{"block", "extraLength", "radius", "args"}, {"blockPattern", "extraLength", "radius", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + output.trSuccess("worldedit.rope.success", i); + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - if (region->regionType != RegionType::CUBOID && region->regionType != CONVEX) { - output.trError("worldedit.rope.invalid-type"); - return; - } + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "line", // command name + tr("worldedit.command.description.line"), // command description + { + }, + { + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Float, true, "radius"), + ParamData("args", ParamType::SoftEnum, true, "-h", "-h"), + }, + {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + + if (region->regionType != RegionType::CUBOID + && region->regionType != CONVEX) { + output.trError("worldedit.line.invalid-type"); + return; + } - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); - double extraLength = 20; - if (results["extraLength"].isSet) { - extraLength = results["extraLength"].get(); - } - extraLength = 1.0 + extraLength / 100.0; + float radius = 0; + if (results["radius"].isSet) { + radius = results["radius"].get(); + } - float radius = 0; - if (results["radius"].isSet) { - radius = results["radius"].get(); - } + boundingBox.min -= static_cast(radius); + boundingBox.max += static_cast(radius); - bool arg_h = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } + bool arg_h = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } + if (str.find("h") != std::string::npos) { + arg_h = true; + } + } - try { - phmap::flat_hash_set tmp; - region->forEachLine([&](const BlockPos& pos1, const BlockPos& pos2) { - if (extraLength > 1 && (pos1.x != pos2.x || pos1.z != pos2.z)) { - double d = pos1.distanceTo(pos2); - double dh = sqrt(pow2(pos1.x - pos2.x) + pow2(pos1.z - pos2.z)); - double h = pos2.y - pos1.y; - double L = d * extraLength; - double a = getCatenaryParameter(dh, h, L); - double x0 = (a * log((L - h) / (L + h)) - dh) * 0.5; - double y0 = a * cosh(x0 / a); - int dx = pos2.x - pos1.x; - int dz = pos2.z - pos1.z; - x0 += dh; - y0 -= h; - double df = 1.0 / (10 * L); - for (double i = 0; i <= 1; i += df) { - double kx, kz, ky = a * cosh((i * dh - x0) / a) - y0; - ky += pos1.y; - kx = pos1.x + dx * i; - kz = pos1.z + dz * i; - BlockPos kpos = {static_cast(std::floor(kx + 0.5)), - static_cast(std::floor(ky + 0.5)), - static_cast(std::floor(kz + 0.5))}; - if (radius == 0) { - tmp.insert(kpos); - boundingBox.merge(kpos); - } else { - BoundingBox(kpos - static_cast(radius + 1), - kpos + static_cast(radius + 1)) - .forEachBlockInBox([&](const BlockPos& posk) { - if (sqrt(pow2(posk.x - kx) + pow2(posk.y - ky) + pow2(posk.z - kz)) <= - 0.5 + radius) { - tmp.insert(posk); - boundingBox.merge(posk); - } - }); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + + auto sizeDim = boundingBox.max - boundingBox.min + 3; + + long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); + try { + std::vector tmp(size, false); + region->forEachLine([&](BlockPos const& pos1, BlockPos const& pos2) { + plotLine(pos1, pos2, [&](BlockPos const& pos) { + BoundingBox( + pos - static_cast(radius + 1), + pos + static_cast(radius + 1) + ) + .forEachBlockInBox([&](BlockPos const& posk) { + if ((pos - posk).length() <= 0.5 + radius) { + auto localPos = posk - boundingBox.min + 1; + tmp.at( + (localPos.y + sizeDim.y * localPos.z) + * sizeDim.x + + localPos.x + ) = true; } - } - } else { - plotLine(pos1, pos2, [&](const BlockPos& pos) { - BoundingBox(pos - static_cast(radius + 1), pos + static_cast(radius + 1)) - .forEachBlockInBox([&](const BlockPos& posk) { - if ((pos - posk).length() <= 0.5 + radius) { - tmp.insert(posk); - boundingBox.merge(posk); - } - }); }); - } }); + }); - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - - if (arg_h) { - phmap::flat_hash_set tmp2; - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - if (tmp.contains(pos)) { - int counts = 0; + if (arg_h) { + std::vector tmp2(size, false); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + int counts = 0; - for (auto& calPos : pos.getNeighbors()) { - if (tmp.contains(calPos)) { - counts++; - } + for (auto& calPos : localPos.getNeighbors()) { + if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x]) { + counts++; } - if (counts < 6) - tmp2.insert(pos); } - }); - tmp = std::move(tmp2); - } + if (counts < 6) + tmp2 + [(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; + } + }); + tmp.assign(tmp2.begin(), tmp2.end()); + } - long long i = 0; + long long i = 0; - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); - for (auto& pos : tmp) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { i += pattern->setBlock(variables, f, blockSource, pos); } + }); - output.trSuccess("worldedit.rope.success", i); - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; - } + output.trSuccess("worldedit.line.success", i); + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); + return; + } - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "line", // command name - tr("worldedit.command.description.line"), // command description - {}, - { - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Float, true, "radius"), - ParamData("args", ParamType::SoftEnum, true, "-h", "-h"), - }, - {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "curve", // command name + tr("worldedit.command.description.curve"), // command description + { + }, + { + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius", ParamType::Float, true, "radius"), + ParamData("args", ParamType::SoftEnum, true, "-hcr", "-hcr"), + }, + {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + + if (region->regionType != RegionType::CONVEX + && region->regionType != RegionType::LOFT) { + output.trError("worldedit.curve.invalid-type"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - if (region->regionType != RegionType::CUBOID && region->regionType != CONVEX) { - output.trError("worldedit.line.invalid-type"); + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + float radius = 0; + if (results["radius"].isSet) { + radius = results["radius"].get(); + } + bool arg_h = false, arg_r = false, arg_c = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); return; } + if (str.find("h") != std::string::npos) { + arg_h = true; + } + if (str.find("r") != std::string::npos) { + arg_r = true; + } + if (str.find("c") != std::string::npos) { + arg_c = true; + } + } + + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + EvalFunctions f; + f.setbs(blockSource); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - float radius = 0; - if (results["radius"].isSet) { - radius = results["radius"].get(); - } + if (region->regionType == RegionType::LOFT) { + try { + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = + std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - boundingBox.min -= static_cast(radius); - boundingBox.max += static_cast(radius); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + f.setbox(boundingBox); + auto* loft = static_cast(region.get()); + loft->forEachBlockInLines( + static_cast(radius), + !arg_h, + [&](BlockPos const& pos) { + setFunction( + variables, + f, + boundingBox, + playerPos, + pos, + center + ); + i += pattern->setBlock(variables, f, blockSource, pos); + } + ); - bool arg_h = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); + return; + } + } else { + std::vector nodes; + nodes.clear(); + if (arg_r) { + for (auto& pos : + static_cast(region.get())->indexedVertices) { + nodes.push_back(Node( + pos, + RNG::rand() * 2 - 1, + RNG::rand() * 2 - 1, + RNG::rand() * 2 - 1 + )); } - if (str.find("h") != std::string::npos) { - arg_h = true; + } else { + for (auto& pos : + static_cast(region.get())->indexedVertices) { + nodes.push_back(Node(pos)); } } + const double quality = 16; - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); + auto interpol = KochanekBartelsInterpolation(nodes, arg_c); + const double splinelength = interpol.arcLength(0, 1); + const double step = 1.0 / splinelength / quality; + std::vector points; + points.clear(); + for (double t = 0; t <= 1; t += step) { + auto pos = interpol.getPosition(t); + boundingBox.merge(pos.toBlockPos()); + points.push_back(pos); } + boundingBox.min -= static_cast(radius) + 1; + boundingBox.max += static_cast(radius) + 1; + try { + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = + std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - auto sizeDim = boundingBox.max - boundingBox.min + 3; + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + + auto sizeDim = boundingBox.max - boundingBox.min + 3; + + long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - try { std::vector tmp(size, false); - region->forEachLine([&](const BlockPos& pos1, const BlockPos& pos2) { - plotLine(pos1, pos2, [&](const BlockPos& pos) { - BoundingBox(pos - static_cast(radius + 1), pos + static_cast(radius + 1)) - .forEachBlockInBox([&](const BlockPos& posk) { - if ((pos - posk).length() <= 0.5 + radius) { - auto localPos = posk - boundingBox.min + 1; - tmp.at((localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x) = - true; - } - }); - }); - }); + for (auto& pos : points) { + BoundingBox( + pos.toBlockPos() - (static_cast(radius) + 1), + pos.toBlockPos() + (static_cast(radius) + 1) + ) + .forEachBlockInBox([&](BlockPos const& posk) { + if ((pos.toBlockPos() - posk).length() + <= 0.5 + radius) { + auto localPos = posk - boundingBox.min + 1; + tmp.at( + (localPos.y + sizeDim.y * localPos.z) + * sizeDim.x + + localPos.x + ) = true; + } + }); + } if (arg_h) { std::vector tmp2(size, false); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { int counts = 0; for (auto& calPos : localPos.getNeighbors()) { - if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]) { + if (tmp[(calPos.y + sizeDim.y * calPos.z) + * sizeDim.x + + calPos.x]) { counts++; } } if (counts < 6) - tmp2[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; + tmp2 + [(localPos.y + sizeDim.y * localPos.z) + * sizeDim.x + + localPos.x] = true; } }); tmp.assign(tmp2.begin(), tmp2.end()); } - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - - EvalFunctions f; - f.setbs(blockSource); f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + setFunction( + variables, + f, + boundingBox, + playerPos, + pos, + center + ); auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { i += pattern->setBlock(variables, f, blockSource, pos); } }); - - output.trSuccess("worldedit.line.success", i); } catch (std::bad_alloc) { output.trError("worldedit.memory.out"); return; } - - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "curve", // command name - tr("worldedit.command.description.curve"), // command description - {}, - { - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius", ParamType::Float, true, "radius"), - ParamData("args", ParamType::SoftEnum, true, "-hcr", "-hcr"), - }, - {{"block", "radius", "args"}, {"blockPattern", "radius", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + } + output.trSuccess("worldedit.curve.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "spike", // command name + tr("worldedit.command.description.spike"), // command description + { + }, + { + ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("radius1", ParamType::Float, false, "radius1"), + ParamData("radius2", ParamType::Float, false, "radius2"), + ParamData("radius3", ParamType::Float, true, "radius3"), + ParamData("args", ParamType::SoftEnum, true, "-hcr", "-hcr"), + }, + { + {"block", "radius1", "radius2", "radius3", "args"}, + {"blockPattern", "radius1", "radius2", "radius3", "args"}, + }, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + + if (region->regionType != CONVEX) { + output.trError("worldedit.spike.invalid-type"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - if (region->regionType != RegionType::CONVEX && region->regionType != RegionType::LOFT) { - output.trError("worldedit.curve.invalid-type"); - return; - } + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + float radius1 = 0; + if (results["radius1"].isSet) { + radius1 = results["radius1"].get(); + } + float radius2 = 0; + if (results["radius2"].isSet) { + radius2 = results["radius2"].get(); + } + float radius3 = -1; + if (results["radius3"].isSet) { + radius3 = results["radius3"].get(); + } + auto radius = std::max(radius3, std::max(radius1, radius2)); - float radius = 0; - if (results["radius"].isSet) { - radius = results["radius"].get(); - } - bool arg_h = false, arg_r = false, arg_c = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } - if (str.find("r") != std::string::npos) { - arg_r = true; - } - if (str.find("c") != std::string::npos) { - arg_c = true; + auto getRadius = [&](double& t) { + if (radius3 >= 0) { + if (t < 0.5) { + return radius1 + 2 * t * (radius2 - radius1); + } else { + return radius2 + 2 * (t - 0.5) * (radius3 - radius2); } + } else { + return radius1 + t * (radius2 - radius1); } + }; - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; + bool arg_h = false, arg_r = false, arg_c = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; + } + if (str.find("h") != std::string::npos) { + arg_h = true; + } + if (str.find("r") != std::string::npos) { + arg_r = true; + } + if (str.find("c") != std::string::npos) { + arg_c = true; + } + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + std::vector nodes; + nodes.clear(); + if (arg_r) { + for (auto& pos : + static_cast(region.get())->indexedVertices) { + nodes.push_back(Node( + pos, + RNG::rand() * 2 - 1, + RNG::rand() * 2 - 1, + RNG::rand() * 2 - 1 + )); } - auto pattern = Pattern::createPattern(bps, xuid); + } else { + for (auto& pos : + static_cast(region.get())->indexedVertices) { + nodes.push_back(Node(pos)); + } + } + const double quality = 16; + + auto interpol = KochanekBartelsInterpolation(nodes, arg_c); + const double splinelength = interpol.arcLength(0, 1); + const double step = 1.0 / splinelength / quality; + std::vector points; + points.clear(); + std::vector radiuses; + radiuses.clear(); + for (double t = 0; t <= 1; t += step) { + auto pos = interpol.getPosition(t); + boundingBox.merge(pos.toBlockPos()); + points.push_back(pos); + radiuses.push_back(std::max(getRadius(t), 0.1)); + } + boundingBox.min -= static_cast(radius) + 1; + boundingBox.max += static_cast(radius) + 1; + try { + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - EvalFunctions f; - f.setbs(blockSource); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - if (region->regionType == RegionType::LOFT) { - try { - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - f.setbox(boundingBox); - auto* loft = static_cast(region.get()); - loft->forEachBlockInLines(static_cast(radius), !arg_h, [&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - i += pattern->setBlock(variables, f, blockSource, pos); - }); - - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; - } - } else { - std::vector nodes; - nodes.clear(); - if (arg_r) { - for (auto& pos : static_cast(region.get())->poss) { - nodes.push_back(Node(pos, RNG::rand() * 2 - 1, RNG::rand() * 2 - 1, - RNG::rand() * 2 - 1)); - } - } else { - for (auto& pos : static_cast(region.get())->poss) { - nodes.push_back(Node(pos)); - } - } - const double quality = 16; - - auto interpol = KochanekBartelsInterpolation(nodes, arg_c); - const double splinelength = interpol.arcLength(0, 1); - const double step = 1.0 / splinelength / quality; - std::vector points; - points.clear(); - for (double t = 0; t <= 1; t += step) { - auto pos = interpol.getPosition(t); - boundingBox.merge(pos.toBlockPos()); - points.push_back(pos); - } - boundingBox.min -= static_cast(radius) + 1; - boundingBox.max += static_cast(radius) + 1; - try { - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - - auto sizeDim = boundingBox.max - boundingBox.min + 3; - - long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - - std::vector tmp(size, false); - for (auto& pos : points) { - BoundingBox(pos.toBlockPos() - (static_cast(radius) + 1), - pos.toBlockPos() + (static_cast(radius) + 1)) - .forEachBlockInBox([&](const BlockPos& posk) { - if ((pos.toBlockPos() - posk).length() <= 0.5 + radius) { - auto localPos = posk - boundingBox.min + 1; - tmp.at((localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x) = - true; - } - }); - } + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - if (arg_h) { - std::vector tmp2(size, false); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - int counts = 0; + auto sizeDim = boundingBox.max - boundingBox.min + 3; - for (auto& calPos : localPos.getNeighbors()) { - if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]) { - counts++; - } - } - if (counts < 6) - tmp2[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; - } - }); - tmp.assign(tmp2.begin(), tmp2.end()); - } + long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - f.setbox(boundingBox); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - i += pattern->setBlock(variables, f, blockSource, pos); + std::vector tmp(size, false); + int iter = 0; + for (auto& pos : points) { + BoundingBox( + pos.toBlockPos() - (static_cast(radius) + 1), + pos.toBlockPos() + (static_cast(radius) + 1) + ) + .forEachBlockInBox([&](BlockPos const& posk) { + if ((pos - (posk.toVec3() + 0.5)).length() + <= 0.5 + radiuses[iter]) { + auto localPos = posk - boundingBox.min + 1; + tmp.at( + (localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x + ) = true; } }); - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; - } - } - output.trSuccess("worldedit.curve.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "spike", // command name - tr("worldedit.command.description.spike"), // command description - {}, - { - ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("radius1", ParamType::Float, false, "radius1"), - ParamData("radius2", ParamType::Float, false, "radius2"), - ParamData("radius3", ParamType::Float, true, "radius3"), - ParamData("args", ParamType::SoftEnum, true, "-hcr", "-hcr"), - }, - { - {"block", "radius1", "radius2", "radius3", "args"}, - {"blockPattern", "radius1", "radius2", "radius3", "args"}, - }, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - - if (region->regionType != CONVEX) { - output.trError("worldedit.spike.invalid-type"); - return; - } - - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - float radius1 = 0; - if (results["radius1"].isSet) { - radius1 = results["radius1"].get(); + iter++; } - float radius2 = 0; - if (results["radius2"].isSet) { - radius2 = results["radius2"].get(); - } - float radius3 = -1; - if (results["radius3"].isSet) { - radius3 = results["radius3"].get(); - } - auto radius = std::max(radius3, std::max(radius1, radius2)); - - auto getRadius = [&](double& t) { - if (radius3 >= 0) { - if (t < 0.5) { - return radius1 + 2 * t * (radius2 - radius1); - } else { - return radius2 + 2 * (t - 0.5) * (radius3 - radius2); - } - } else { - return radius1 + t * (radius2 - radius1); - } - }; - bool arg_h = false, arg_r = false, arg_c = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } - if (str.find("r") != std::string::npos) { - arg_r = true; - } - if (str.find("c") != std::string::npos) { - arg_c = true; - } - } - - std::vector nodes; - nodes.clear(); - if (arg_r) { - for (auto& pos : static_cast(region.get())->poss) { - nodes.push_back(Node(pos, RNG::rand() * 2 - 1, RNG::rand() * 2 - 1, - RNG::rand() * 2 - 1)); - } - } else { - for (auto& pos : static_cast(region.get())->poss) { - nodes.push_back(Node(pos)); - } - } - const double quality = 16; - - auto interpol = KochanekBartelsInterpolation(nodes, arg_c); - const double splinelength = interpol.arcLength(0, 1); - const double step = 1.0 / splinelength / quality; - std::vector points; - points.clear(); - std::vector radiuses; - radiuses.clear(); - for (double t = 0; t <= 1; t += step) { - auto pos = interpol.getPosition(t); - boundingBox.merge(pos.toBlockPos()); - points.push_back(pos); - radiuses.push_back(std::max(getRadius(t), 0.1)); - } - boundingBox.min -= static_cast(radius) + 1; - boundingBox.max += static_cast(radius) + 1; - try { - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - - auto sizeDim = boundingBox.max - boundingBox.min + 3; - - long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - - std::vector tmp(size, false); - int iter = 0; - for (auto& pos : points) { - BoundingBox(pos.toBlockPos() - (static_cast(radius) + 1), - pos.toBlockPos() + (static_cast(radius) + 1)) - .forEachBlockInBox([&](const BlockPos& posk) { - if ((pos - (posk.toVec3() + 0.5)).length() <= 0.5 + radiuses[iter]) { - auto localPos = posk - boundingBox.min + 1; - tmp.at((localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x) = true; - } - }); - iter++; - } - - if (arg_h) { - std::vector tmp2(size, false); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - int counts = 0; + if (arg_h) { + std::vector tmp2(size, false); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + int counts = 0; - for (auto& calPos : localPos.getNeighbors()) { - if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]) { - counts++; - } + for (auto& calPos : localPos.getNeighbors()) { + if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x]) { + counts++; } - if (counts < 6) - tmp2[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; } - }); - tmp.assign(tmp2.begin(), tmp2.end()); - } - - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - i += pattern->setBlock(variables, f, blockSource, pos); + if (counts < 6) + tmp2 + [(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; } }); - - output.trSuccess("worldedit.spike.success", i); - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; - } - - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "rep", // command name - tr("worldedit.command.description.rep"), // command description - {}, - {ParamData("blockAfter", ParamType::Block, "blockAfter"), - ParamData("blockBefore", ParamType::Block, true, "blockBefore"), - ParamData("blockAfterS", ParamType::String, "blockAfterS"), - ParamData("blockBeforeS", ParamType::String, true, "blockBeforeS")}, - {{"blockBefore", "blockAfter"}, - {"blockBeforeS", "blockAfterS"}, - {"blockBeforeS", "blockAfter"}, - {"blockBefore", "blockAfterS"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); + tmp.assign(tmp2.begin(), tmp2.end()); } long long i = 0; @@ -866,6 +895,7 @@ namespace worldedit { auto playerPos = origin.getWorldPosition(); auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); ; + EvalFunctions f; f.setbs(blockSource); f.setbox(boundingBox); @@ -873,728 +903,1143 @@ namespace worldedit { playerData.setVarByPlayer(variables); std::string bps = "minecraft:air"; - if (results["blockAfterS"].isSet) { - bps = results["blockAfterS"].get(); - } else if (results["blockAfter"].isSet) { - bps = results["blockAfter"].get().resolveBlock(0).getBlock()->getTypeName(); - } - std::string bps2 = "minecraft:air"; - if (results["blockBeforeS"].isSet) { - bps2 = results["blockBeforeS"].get(); - } else if (results["blockBefore"].isSet) { - bps2 = results["blockBefore"].get().resolveBlock(0).getBlock()->getTypeName(); + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } auto pattern = Pattern::createPattern(bps, xuid); - auto blockFilter = Pattern::createPattern(bps2, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { + + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { setFunction(variables, f, boundingBox, playerPos, pos, center); - if (blockFilter->hasBlock(&blockSource->getBlock(pos))) { + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { i += pattern->setBlock(variables, f, blockSource, pos); } }); - output.trSuccess("worldedit.rep.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "center", // command name - tr("worldedit.command.description.center"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, - {{"block"}, {"blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + output.trSuccess("worldedit.spike.success", i); + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto dimID = region->getDimensionID(); - auto center = region->getCenter(); - BoundingBox boundingBox; - boundingBox.min.x = static_cast(floor(center.x - 0.49)); - boundingBox.min.y = static_cast(floor(center.y - 0.49)); - boundingBox.min.z = static_cast(floor(center.z - 0.49)); - boundingBox.max.x = static_cast(floor(center.x + 0.49)); - boundingBox.max.y = static_cast(floor(center.y + 0.49)); - boundingBox.max.z = static_cast(floor(center.z + 0.49)); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "rep", // command name + tr("worldedit.command.description.rep"), // command description + { + }, + {ParamData("blockAfter", ParamType::Block, "blockAfter"), + ParamData("blockBefore", ParamType::Block, true, "blockBefore"), + ParamData("blockAfterS", ParamType::String, "blockAfterS"), + ParamData("blockBeforeS", ParamType::String, true, "blockBeforeS")}, + {{"blockBefore", "blockAfter"}, + {"blockBeforeS", "blockAfterS"}, + {"blockBeforeS", "blockAfter"}, + {"blockBefore", "blockAfterS"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockAfterS"].isSet) { + bps = results["blockAfterS"].get(); + } else if (results["blockAfter"].isSet) { + bps = results["blockAfter"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + std::string bps2 = "minecraft:air"; + if (results["blockBeforeS"].isSet) { + bps2 = results["blockBeforeS"].get(); + } else if (results["blockBefore"].isSet) { + bps2 = results["blockBefore"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + auto blockFilter = Pattern::createPattern(bps2, xuid); + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + if (blockFilter->hasBlock(&blockSource->getBlock(pos))) { + i += pattern->setBlock(variables, f, blockSource, pos); } - auto pattern = Pattern::createPattern(bps, xuid); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - pattern->setBlock(variables, f, blockSource, pos); + }); + + output.trSuccess("worldedit.rep.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "center", // command name + tr("worldedit.command.description.center"), // command description + {}, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, + {{"block"}, {"blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto dimID = region->getDimensionID(); + auto center = region->getCenter(); + BoundingBox boundingBox; + boundingBox.min.x = static_cast(floor(center.x - 0.49)); + boundingBox.min.y = static_cast(floor(center.y - 0.49)); + boundingBox.min.z = static_cast(floor(center.z - 0.49)); + boundingBox.max.x = static_cast(floor(center.x + 0.49)); + boundingBox.max.y = static_cast(floor(center.y + 0.49)); + boundingBox.max.z = static_cast(floor(center.z + 0.49)); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); }); + } - output.trSuccess("worldedit.center.success"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "stack", // command name - tr("worldedit.command.description.stack"), // command description - { - {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, - }, - {ParamData("times", ParamType::Int, true, "times"), ParamData("dir", ParamType::Enum, true, "dir"), - ParamData("args", ParamType::SoftEnum, true, "-sale", "-sale")}, - {{"times", "dir", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto times = 1; - if (results["times"].isSet) { - times = results["times"].get(); - } - bool arg_a = false, arg_s = false, arg_l = false, arg_e = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("a") != std::string::npos) { - arg_a = true; - } - if (str.find("s") != std::string::npos) { - arg_s = true; - } - if (str.find("l") != std::string::npos) { - arg_l = true; - } - if (str.find("e") != std::string::npos) { - arg_e = true; - } + auto pattern = Pattern::createPattern(bps, xuid); + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + pattern->setBlock(variables, f, blockSource, pos); + }); + + output.trSuccess("worldedit.center.success"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "stack", // command name + tr("worldedit.command.description.stack"), // command description + { + {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, + }, + {ParamData("times", ParamType::Int, true, "times"), + ParamData("dir", ParamType::Enum, true, "dir"), + ParamData("args", ParamType::SoftEnum, true, "-sale", "-sale")}, + {{"times", "dir", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto times = 1; + if (results["times"].isSet) { + times = results["times"].get(); + } + bool arg_a = false, arg_s = false, arg_l = false, arg_e = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - worldedit::FACING facing; - if (results["dir"].isSet) { - auto str = results["dir"].getRaw(); - if (str == "me") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } else if (str == "back") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - facing = worldedit::invFacing(facing); - } else { - facing = worldedit::dirStringToFacing(str); - } - } else { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + if (str.find("a") != std::string::npos) { + arg_a = true; } - BlockPos faceVec = worldedit::facingToPos(facing, 1); - - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto boundingBoxLast = boundingBox; - auto blockSource = &player->getDimensionBlockSource(); - - BlockPos movingVec; - if (arg_l) { - movingVec = faceVec; - } else { - movingVec = faceVec * (boundingBox.max - boundingBox.min + 1); + if (str.find("s") != std::string::npos) { + arg_s = true; } - - boundingBoxLast.min = boundingBoxLast.min + movingVec * times; - boundingBoxLast.max = boundingBoxLast.max + movingVec * times; - auto boundingBoxHistory = boundingBoxLast.merge(boundingBox); - - Clipboard* history = nullptr; - if (playerData.maxHistoryLength > 0) { - history = &playerData.getNextHistory(); - *history = Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + if (str.find("l") != std::string::npos) { + arg_l = true; + } + if (str.find("e") != std::string::npos) { + arg_e = true; + } + } + worldedit::FACING facing; + if (results["dir"].isSet) { + auto str = results["dir"].getRaw(); + if (str == "me") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } else if (str == "back") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + facing = worldedit::invFacing(facing); } else { - history = new Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + facing = worldedit::dirStringToFacing(str); } - history->playerRelPos.x = dimID; - history->playerPos = boundingBoxHistory.min; - - boundingBoxHistory.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBoxHistory.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history->storeBlock(blockInstance, localPos); - }); + } else { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } + BlockPos faceVec = worldedit::facingToPos(facing, 1); + + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto boundingBoxLast = boundingBox; + auto blockSource = &player->getDimensionBlockSource(); + + BlockPos movingVec; + if (arg_l) { + movingVec = faceVec; + } else { + movingVec = faceVec * (boundingBox.max - boundingBox.min + 1); + } - long long i = 0; + boundingBoxLast.min = boundingBoxLast.min + movingVec * times; + boundingBoxLast.max = boundingBoxLast.max + movingVec * times; + auto boundingBoxHistory = boundingBoxLast.merge(boundingBox); - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - region->forEachBlockInRegion([&](const BlockPos& posk) { - auto localPos = posk - boundingBoxHistory.min; - for (int j = 1; j <= times; ++j) { - auto pos = posk + movingVec * j; - setFunction(variables, f, boundingBox, playerPos, pos, center); - if ((arg_a && (&blockSource->getBlock(posk) != BedrockBlocks::mAir)) || !arg_a) { - auto& set = history->getSet(localPos); - if (set.blocks.has_value()) - if ((arg_l && (set.blocks.value().first != BedrockBlocks::mAir)) || !arg_l) { - i += set.setBlock(pos, blockSource, playerData, f, variables); - } - } - } - }); - if (playerData.maxHistoryLength <= 0) { - delete history; - } - if (arg_e) { - auto st = - StructureTemplate("worldedit_stack_cmd_tmp", - dAccess, 192>( - Global)); - auto setting = StructureSettings(); - setting.setIgnoreBlocks(true); - setting.setIgnoreEntities(false); - setting.setStructureSize(boundingBox.max - boundingBox.min + 1); - st.fillFromWorld(*blockSource, boundingBox.min + BlockPos(0, 1, 0), setting); - auto& palette = Global->getBlockPalette(); - for (int j = 1; j <= times; ++j) { - auto pos = boundingBox.min + BlockPos(0, 1, 0) + movingVec * j; - st.placeInWorld(*blockSource, palette, pos, setting, nullptr, false); + Clipboard* history = nullptr; + if (playerData.maxHistoryLength > 0) { + history = &playerData.getNextHistory(); + *history = Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + } else { + history = + new Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + } + history->playerRelPos.x = dimID; + history->playerPos = boundingBoxHistory.min; + + boundingBoxHistory.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBoxHistory.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history->storeBlock(blockInstance, localPos); + }); + + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + region->forEachBlockInRegion([&](BlockPos const& posk) { + auto localPos = posk - boundingBoxHistory.min; + for (int j = 1; j <= times; ++j) { + auto pos = posk + movingVec * j; + setFunction(variables, f, boundingBox, playerPos, pos, center); + if ((arg_a + && (&blockSource->getBlock(posk) != BedrockBlocks::mAir)) + || !arg_a) { + auto& set = history->getSet(localPos); + if (set.blocks.has_value()) + if ((arg_l + && (set.blocks.value().first != BedrockBlocks::mAir)) + || !arg_l) { + i += set.setBlock( + pos, + blockSource, + playerData, + f, + variables + ); + } } } - if (arg_s) { - playerData.region->shift(movingVec * times); + }); + if (playerData.maxHistoryLength <= 0) { + delete history; + } + if (arg_e) { + auto st = StructureTemplate( + "worldedit_stack_cmd_tmp", + dAccess< + Bedrock::NonOwnerPointer, + 192>(Global) + ); + auto setting = StructureSettings(); + setting.setIgnoreBlocks(true); + setting.setIgnoreEntities(false); + setting.setStructureSize(boundingBox.max - boundingBox.min + 1); + st.fillFromWorld( + *blockSource, + boundingBox.min + BlockPos(0, 1, 0), + setting + ); + auto& palette = Global->getBlockPalette(); + for (int j = 1; j <= times; ++j) { + auto pos = boundingBox.min + BlockPos(0, 1, 0) + movingVec * j; + st.placeInWorld( + *blockSource, + palette, + pos, + setting, + nullptr, + false + ); } - output.trSuccess("worldedit.stack.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "move", // command name - tr("worldedit.command.description.move"), // command description - { - {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, - }, - {ParamData("dis", ParamType::Int, true, "dis"), ParamData("dir", ParamType::Enum, true, "dir"), - ParamData("args", ParamType::SoftEnum, true, "-sa", "-sa"), - ParamData("block", ParamType::Block, true, "block"), - ParamData("blockPattern", ParamType::SoftEnum, true, "blockPattern")}, - {{"dis", "dir", "block", "args"}, {"dis", "dir", "blockPattern", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto dis = 1; - if (results["dis"].isSet) { - dis = results["dis"].get(); - } - bool arg_a = false, arg_s = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("a") != std::string::npos) { - arg_a = true; - } - if (str.find("s") != std::string::npos) { - arg_s = true; - } + if (arg_s) { + playerData.region->shift(movingVec * times); + } + output.trSuccess("worldedit.stack.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "move", // command name + tr("worldedit.command.description.move"), // command description + { + {"dir", {"me", "back", "up", "down", "south", "north", "east", "west"}}, + }, + {ParamData("dis", ParamType::Int, true, "dis"), + ParamData("dir", ParamType::Enum, true, "dir"), + ParamData("args", ParamType::SoftEnum, true, "-sa", "-sa"), + ParamData("block", ParamType::Block, true, "block"), + ParamData("blockPattern", ParamType::SoftEnum, true, "blockPattern")}, + {{"dis", "dir", "block", "args"}, {"dis", "dir", "blockPattern", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto dis = 1; + if (results["dis"].isSet) { + dis = results["dis"].get(); + } + bool arg_a = false, arg_s = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - worldedit::FACING facing; - if (results["dir"].isSet) { - auto str = results["dir"].getRaw(); - if (str == "me") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - } else if (str == "back") { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); - facing = worldedit::invFacing(facing); - } else { - facing = worldedit::dirStringToFacing(str); - } - } else { - facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + if (str.find("a") != std::string::npos) { + arg_a = true; } - BlockPos faceVec = worldedit::facingToPos(facing, dis); - - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto boundingBoxLast = boundingBox; - auto blockSource = &player->getDimensionBlockSource(); - - boundingBoxLast.min = boundingBoxLast.min + faceVec; - boundingBoxLast.max = boundingBoxLast.max + faceVec; - auto boundingBoxHistory = boundingBoxLast.merge(boundingBox); - - Clipboard* history = nullptr; - if (playerData.maxHistoryLength > 0) { - history = &playerData.getNextHistory(); - *history = std::move(Clipboard(boundingBoxHistory.max - boundingBoxHistory.min)); + if (str.find("s") != std::string::npos) { + arg_s = true; + } + } + worldedit::FACING facing; + if (results["dir"].isSet) { + auto str = results["dir"].getRaw(); + if (str == "me") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } else if (str == "back") { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + facing = worldedit::invFacing(facing); } else { - history = new Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + facing = worldedit::dirStringToFacing(str); } + } else { + facing = worldedit::dirToFacing(player->getViewVector(1.0f)); + } + BlockPos faceVec = worldedit::facingToPos(facing, dis); + + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto boundingBoxLast = boundingBox; + auto blockSource = &player->getDimensionBlockSource(); + + boundingBoxLast.min = boundingBoxLast.min + faceVec; + boundingBoxLast.max = boundingBoxLast.max + faceVec; + auto boundingBoxHistory = boundingBoxLast.merge(boundingBox); + + Clipboard* history = nullptr; + if (playerData.maxHistoryLength > 0) { + history = &playerData.getNextHistory(); + *history = std::move( + Clipboard(boundingBoxHistory.max - boundingBoxHistory.min) + ); + } else { + history = + new Clipboard(boundingBoxHistory.max - boundingBoxHistory.min); + } + + history->playerRelPos.x = dimID; + history->playerPos = boundingBoxHistory.min; - history->playerRelPos.x = dimID; - history->playerPos = boundingBoxHistory.min; + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBoxHistory.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history->storeBlock(blockInstance, localPos); + }); - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBoxHistory.min; + boundingBoxLast.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBoxHistory.min; + if (!history->getSet(localPos).blocks.has_value()) { auto blockInstance = blockSource->getBlockInstance(pos); history->storeBlock(blockInstance, localPos); - }); - - boundingBoxLast.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBoxHistory.min; - if (!history->getSet(localPos).blocks.has_value()) { - auto blockInstance = blockSource->getBlockInstance(pos); - history->storeBlock(blockInstance, localPos); - } - }); - - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); } - auto pattern = Pattern::createPattern(bps, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - pattern->setBlock(variables, f, blockSource, pos); - }); - - region->forEachBlockInRegion([&](const BlockPos& posk) { - auto pos = posk + faceVec; - auto localPos = posk - boundingBoxHistory.min; - auto block = history->getSet(localPos).getBlock(); - setFunction(variables, f, boundingBox, playerPos, pos, center); - if ((arg_a && (block != BedrockBlocks::mAir)) || !arg_a) { - auto& set = history->getSet(localPos); - if (set.blocks.has_value()) { - i += set.setBlock(pos, blockSource, playerData, f, variables); - } - } - }); - if (playerData.maxHistoryLength <= 0) { - delete history; + }); + + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + pattern->setBlock(variables, f, blockSource, pos); + }); + + region->forEachBlockInRegion([&](BlockPos const& posk) { + auto pos = posk + faceVec; + auto localPos = posk - boundingBoxHistory.min; + auto block = history->getSet(localPos).getBlock(); + setFunction(variables, f, boundingBox, playerPos, pos, center); + if ((arg_a && (block != BedrockBlocks::mAir)) || !arg_a) { + auto& set = history->getSet(localPos); + if (set.blocks.has_value()) { + i += set.setBlock(pos, blockSource, playerData, f, variables); + } + } + }); + if (playerData.maxHistoryLength <= 0) { + delete history; + } + if (arg_s) { + playerData.region->shift(faceVec); + } + output.trSuccess("worldedit.move.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "gen", // command name + tr("worldedit.command.description.gen"), // command description + { + }, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), + ParamData("function", ParamType::String, "function"), + ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, + {{"block", "function", "args"}, {"blockPattern", "function", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + bool arg_h = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - if (arg_s) { - playerData.region->shift(faceVec); + if (str.find("h") != std::string::npos) { + arg_h = true; } - output.trSuccess("worldedit.move.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "gen", // command name - tr("worldedit.command.description.gen"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern"), - ParamData("function", ParamType::String, "function"), - ParamData("args", ParamType::SoftEnum, true, "-h", "-h")}, - {{"block", "function", "args"}, {"blockPattern", "function", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - bool arg_h = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("h") != std::string::npos) { - arg_h = true; - } - } - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - long long i = 0; + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - auto genfunc = results["function"].get(); + long long i = 0; - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + auto genfunc = results["function"].get(); - auto sizeDim = boundingBox.max - boundingBox.min + 3; + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); + auto sizeDim = boundingBox.max - boundingBox.min + 3; - try { - std::vector tmp(size, false); - std::vector caled(size, false); + long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - region->forEachBlockInRegion([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - auto localPos = pos - boundingBox.min + 1; - if (cpp_eval::eval(genfunc, variables, f) > 0.5) { - tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; - } - caled[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; - }); + try { + std::vector tmp(size, false); + std::vector caled(size, false); - if (arg_h) { - std::vector tmp2(size, false); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - int counts = 0; + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + auto localPos = pos - boundingBox.min + 1; + if (cpp_eval::eval(genfunc, variables, f) > 0.5) { + tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; + } + caled + [(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; + }); - for (auto& calPos : localPos.getNeighbors()) { - if (!caled[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]) { - setFunction(variables, f, boundingBox, playerPos, - calPos + boundingBox.min - 1, center); - tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x] = - cpp_eval::eval(genfunc, variables, f) > 0.5; + if (arg_h) { + std::vector tmp2(size, false); + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + int counts = 0; - caled[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x] = true; - } - if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]) { - counts++; - } + for (auto& calPos : localPos.getNeighbors()) { + if (!caled + [(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x]) { + setFunction( + variables, + f, + boundingBox, + playerPos, + calPos + boundingBox.min - 1, + center + ); + tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x] = + cpp_eval::eval(genfunc, variables, f) + > 0.5; + + caled + [(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x] = true; + } + if (tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x]) { + counts++; } - if (counts < 6) - tmp2[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; } - }); - tmp.assign(tmp2.begin(), tmp2.end()); - } - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - i += pattern->setBlock(variables, f, blockSource, pos); + if (counts < 6) + tmp2 + [(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; } }); - - output.trSuccess("worldedit.gen.success", genfunc, i); - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; + tmp.assign(tmp2.begin(), tmp2.end()); } - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "walls", // command name - tr("worldedit.command.description.walls"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, - {{"block"}, {"blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); std::string bps = "minecraft:air"; if (results["blockPattern"].isSet) { bps = results["blockPattern"].get(); } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } auto pattern = Pattern::createPattern(bps, xuid); - if (region->regionType == RegionType::LOFT) { - auto* loft = static_cast(region.get()); - loft->forEachBlockInLines(2, true, [&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + setFunction( + variables, + f, + boundingBox, + playerPos, + pos, + center + ); i += pattern->setBlock(variables, f, blockSource, pos); - }); - if (!(loft->circle)) { - loft->forEachBlockInLines(2, false, [&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - - i += pattern->setBlock(variables, f, blockSource, pos); - }); } - } else { - region->forEachBlockInRegion([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - int counts = 0; - for (auto& calPos : pos.getNeighbors()) { - if (calPos.y <= boundingBox.max.y && calPos.y >= boundingBox.min.y) { - counts += region->contains(calPos); - } else { - counts += 1; - } - } - if (counts < 6) { - i += pattern->setBlock(variables, f, blockSource, pos); - } - }); - } + }); - output.trSuccess("worldedit.walls.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "faces", // command name - tr("worldedit.command.description.faces"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, - {{"block"}, {"blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + output.trSuccess("worldedit.gen.success", genfunc, i); + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "walls", // command name + tr("worldedit.command.description.walls"), // command description + {}, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, + {{"block"}, {"blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + if (region->regionType == RegionType::LOFT) { + auto* loft = static_cast(region.get()); + loft->forEachBlockInLines(2, true, [&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + i += pattern->setBlock(variables, f, blockSource, pos); + }); + if (!(loft->circle)) { + loft->forEachBlockInLines(2, false, [&](BlockPos const& pos) { + setFunction( + variables, + f, + boundingBox, + playerPos, + pos, + center + ); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); + i += pattern->setBlock(variables, f, blockSource, pos); }); } + } else { + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + int counts = 0; + for (auto& calPos : pos.getNeighbors()) { + if (calPos.y <= boundingBox.max.y + && calPos.y >= boundingBox.min.y) { + counts += region->contains(calPos); + } else { + counts += 1; + } + } + if (counts < 6) { + i += pattern->setBlock(variables, f, blockSource, pos); + } + }); + } - long long i = 0; + output.trSuccess("worldedit.walls.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "faces", // command name + tr("worldedit.command.description.faces"), // command description + {}, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, + {{"block"}, {"blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + int counts = 0; + for (auto& calPos : pos.getNeighbors()) { + counts += region->contains(calPos); + } + if (counts < 6) { + i += pattern->setBlock(variables, f, blockSource, pos); } - auto pattern = Pattern::createPattern(bps, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { + }); + + output.trSuccess("worldedit.faces.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "overlay", // command name + tr("worldedit.command.description.overlay"), // command description + {}, + {ParamData("block", ParamType::Block, "block"), + ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, + {{"block"}, {"blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forTopBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + std::string bps = "minecraft:air"; + if (results["blockPattern"].isSet) { + bps = results["blockPattern"].get(); + } else if (results["block"].isSet) { + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); + } + auto pattern = Pattern::createPattern(bps, xuid); + region->forTopBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + i += pattern->setBlock(variables, f, blockSource, pos); + }); + output.trSuccess("worldedit.overlay.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "naturalize", // command name + tr("worldedit.command.description.naturalize"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + region->forTopBlockInRegion([&](BlockPos const& posk) { + BlockPos pos(posk.x, posk.y - 1, posk.z); + if (&blockSource->getBlock(pos) == StaticVanillaBlocks::mStone + && region->contains(pos)) { setFunction(variables, f, boundingBox, playerPos, pos, center); + playerData.setBlockSimple( + blockSource, + f, + variables, + pos, + StaticVanillaBlocks::mGrass + ); + } + for (int mY = -2; mY >= -4; mY--) { + BlockPos pos(posk.x, posk.y + mY, posk.z); + if (&blockSource->getBlock(pos) == StaticVanillaBlocks::mStone + && region->contains(pos)) { + setFunction( + variables, + f, + boundingBox, + playerPos, + pos, + center + ); + + playerData.setBlockSimple( + blockSource, + f, + variables, + pos, + StaticVanillaBlocks::mDirt + ); + } + } + }); + output.trSuccess("worldedit.naturalize.success"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "hollow", // command name + tr("worldedit.command.description.hollow"), // command description + { + }, + {ParamData("num", ParamType::Int, true, "num"), + ParamData("block", ParamType::Block, true, "block"), + ParamData("blockPattern", ParamType::SoftEnum, true, "blockPattern")}, + {{"num", "block"}, {"num", "blockPattern"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int layer = 0; + if (results["num"].isSet) { + layer = results["num"].get(); + } + + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } + + auto sizeDim = boundingBox.max - boundingBox.min + 3; + + long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); + + try { + std::vector tmp(size, false); + + region->forEachBlockInRegion([&](BlockPos const& pos) { int counts = 0; + for (auto& calPos : pos.getNeighbors()) { - counts += region->contains(calPos); + counts += + &blockSource->getBlock(calPos) != BedrockBlocks::mAir; } - if (counts < 6) { - i += pattern->setBlock(variables, f, blockSource, pos); + if (counts == 6) { + auto localPos = pos - boundingBox.min + 1; + tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = true; } }); - output.trSuccess("worldedit.faces.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "overlay", // command name - tr("worldedit.command.description.overlay"), // command description - {}, - {ParamData("block", ParamType::Block, "block"), - ParamData("blockPattern", ParamType::SoftEnum, "blockPattern")}, - {{"block"}, {"blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forTopBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); + for (int manhattan = 0; manhattan < layer; manhattan++) { + std::vector tmp2(tmp); + region->forEachBlockInRegion([&](BlockPos const& pos) { + int counts = 0; + auto localPos = pos - boundingBox.min + 1; + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + for (auto& calPos : localPos.getNeighbors()) { + counts += + tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + + calPos.x]; + } + if (counts < 6) { + tmp2 + [(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x] = false; + } + } }); + tmp.assign(tmp2.begin(), tmp2.end()); } - long long i = 0; - auto playerPos = origin.getWorldPosition(); auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); ; @@ -1603,737 +2048,645 @@ namespace worldedit { f.setbox(boundingBox); phmap::flat_hash_map variables; playerData.setVarByPlayer(variables); + + long long i = 0; + std::string bps = "minecraft:air"; if (results["blockPattern"].isSet) { bps = results["blockPattern"].get(); } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); + bps = results["block"] + .get() + .resolveBlock(0) + .getBlock() + ->getTypeName(); } auto pattern = Pattern::createPattern(bps, xuid); - region->forTopBlockInRegion([&](const BlockPos& pos) { + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min + 1; setFunction(variables, f, boundingBox, playerPos, pos, center); - i += pattern->setBlock(variables, f, blockSource, pos); + if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + + localPos.x]) { + i += pattern->setBlock(variables, f, blockSource, pos); + } }); - output.trSuccess("worldedit.overlay.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "naturalize", // command name - tr("worldedit.command.description.naturalize"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); + output.trSuccess("worldedit.hollow.success", i); + } catch (std::bad_alloc) { + output.trError("worldedit.memory.out"); return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "smooth", // command name + tr("worldedit.command.description.smooth"), // command description + { + }, + {ParamData("num", ParamType::Int, true, "num"), + ParamData("mask", ParamType::String, true, "mask")}, + {{"num", "mask"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + int ksize = 5; + if (results["num"].isSet) { + ksize = results["num"].get(); + } - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); - region->forTopBlockInRegion([&](const BlockPos& posk) { - BlockPos pos(posk.x, posk.y - 1, posk.z); - if (&blockSource->getBlock(pos) == StaticVanillaBlocks::mStone && region->contains(pos)) { - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple(blockSource, f, variables, pos, StaticVanillaBlocks::mGrass); - } - for (int mY = -2; mY >= -4; mY--) { - BlockPos pos(posk.x, posk.y + mY, posk.z); - if (&blockSource->getBlock(pos) == StaticVanillaBlocks::mStone && region->contains(pos)) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - playerData.setBlockSimple(blockSource, f, variables, pos, StaticVanillaBlocks::mDirt); - } - } + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); }); - output.trSuccess("worldedit.naturalize.success"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "hollow", // command name - tr("worldedit.command.description.hollow"), // command description - {}, - {ParamData("num", ParamType::Int, true, "num"), ParamData("block", ParamType::Block, true, "block"), - ParamData("blockPattern", ParamType::SoftEnum, true, "blockPattern")}, - {{"num", "block"}, {"num", "blockPattern"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int layer = 0; - if (results["num"].isSet) { - layer = results["num"].get(); - } - - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - - auto sizeDim = boundingBox.max - boundingBox.min + 3; - - long long size = (sizeDim.x) * (sizeDim.y) * (sizeDim.z); - - try { - std::vector tmp(size, false); - - region->forEachBlockInRegion([&](const BlockPos& pos) { - int counts = 0; - - for (auto& calPos : pos.getNeighbors()) { - counts += &blockSource->getBlock(calPos) != BedrockBlocks::mAir; - } - if (counts == 6) { - auto localPos = pos - boundingBox.min + 1; - tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = true; - } - }); - for (int manhattan = 0; manhattan < layer; manhattan++) { - std::vector tmp2(tmp); - region->forEachBlockInRegion([&](const BlockPos& pos) { - int counts = 0; - auto localPos = pos - boundingBox.min + 1; - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - for (auto& calPos : localPos.getNeighbors()) { - counts += tmp[(calPos.y + sizeDim.y * calPos.z) * sizeDim.x + calPos.x]; - } - if (counts < 6) { - tmp2[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x] = false; - } - } - }); - tmp.assign(tmp2.begin(), tmp2.end()); - } - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - long long i = 0; - - std::string bps = "minecraft:air"; - if (results["blockPattern"].isSet) { - bps = results["blockPattern"].get(); - } else if (results["block"].isSet) { - bps = results["block"].get().resolveBlock(0).getBlock()->getTypeName(); - } - auto pattern = Pattern::createPattern(bps, xuid); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min + 1; - setFunction(variables, f, boundingBox, playerPos, pos, center); - if (tmp[(localPos.y + sizeDim.y * localPos.z) * sizeDim.x + localPos.x]) { - i += pattern->setBlock(variables, f, blockSource, pos); - } - }); - output.trSuccess("worldedit.hollow.success", i); - } catch (std::bad_alloc) { - output.trError("worldedit.memory.out"); - return; - } - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "smooth", // command name - tr("worldedit.command.description.smooth"), // command description - {}, {ParamData("num", ParamType::Int, true, "num"), ParamData("mask", ParamType::String, true, "mask")}, - {{"num", "mask"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + std::string mask = ""; + if (results["mask"].isSet) { + mask = results["mask"].get(); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - int ksize = 5; - if (results["num"].isSet) { - ksize = results["num"].get(); - } - - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); + auto heightMap = region->getHeightMap(mask); + int sizex = boundingBox.max.x - boundingBox.min.x + 1; + int sizez = boundingBox.max.z - boundingBox.min.z + 1; + + auto smoothedHeightMap = blur2D(heightMap, ksize, sizex, sizez); + region->applyHeightMap(smoothedHeightMap, mask); + + output.trSuccess("worldedit.smooth.success"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "exportstr", // command name + tr("worldedit.command.description.exportstr"), // command description + { + }, + { + ParamData("strname", ParamType::String, false, "strname"), + ParamData("args", ParamType::SoftEnum, true, "-l", "-l"), + }, + {{"strname", "args"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + std::string filename; + filename = results["strname"].get(); + auto st = StructureTemplate( + filename, + dAccess< + Bedrock::NonOwnerPointer, + 192>(Global) + ); + + auto setting = StructureSettings(); + setting.setIgnoreBlocks(false); + setting.setIgnoreEntities(false); + setting.setStructureSize(boundingBox.max - boundingBox.min + 1); + st.fillFromWorld( + *blockSource, + boundingBox.min + BlockPos(0, 1, 0), + setting + ); + auto structure = st.toTag()->toBinaryNBT(); + + std::ofstream outStr( + WE_DIR + "structures/" + filename + ".mcstructure", + std::ios::out | std::ios::binary + ); + outStr << structure; + outStr.close(); + output.trSuccess("worldedit.exportstr.str"); + + bool arg_l = false; + if (results["args"].isSet) { + auto str = results["args"].getRaw(); + if (str.find("-") == std::string::npos) { + output.trError("worldedit.command.error.args", str); + return; } - - std::string mask = ""; - if (results["mask"].isSet) { - mask = results["mask"].get(); + if (str.find("l") != std::string::npos) { + arg_l = true; } - - auto heightMap = region->getHeightMap(mask); - int sizex = boundingBox.max.x - boundingBox.min.x + 1; - int sizez = boundingBox.max.z - boundingBox.min.z + 1; - - auto smoothedHeightMap = blur2D(heightMap, ksize, sizex, sizez); - region->applyHeightMap(smoothedHeightMap, mask); - - output.trSuccess("worldedit.smooth.success"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "exportstr", // command name - tr("worldedit.command.description.exportstr"), // command description - {}, - { - ParamData("strname", ParamType::String, false, "strname"), - ParamData("args", ParamType::SoftEnum, true, "-l", "-l"), - }, - {{"strname", "args"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); - - std::string filename; - filename = results["strname"].get(); - auto st = StructureTemplate(filename, - dAccess, 192>( - Global)); - - auto setting = StructureSettings(); - setting.setIgnoreBlocks(false); - setting.setIgnoreEntities(false); - setting.setStructureSize(boundingBox.max - boundingBox.min + 1); - st.fillFromWorld(*blockSource, boundingBox.min + BlockPos(0, 1, 0), setting); - auto structure = st.toTag()->toBinaryNBT(); - std::ofstream outStr(WE_DIR + "structures/" + filename + ".mcstructure", - std::ios::out | std::ios::binary); - outStr << structure; - outStr.close(); - output.trSuccess("worldedit.exportstr.str"); - - bool arg_l = false; - if (results["args"].isSet) { - auto str = results["args"].getRaw(); - if (str.find("-") == std::string::npos) { - output.trError("worldedit.command.error.args", str); - return; - } - if (str.find("l") != std::string::npos) { - arg_l = true; + if (arg_l) { + phmap::flat_hash_map blocksMap; + std::vector> blocksMap2; + blocksMap2.resize(0); + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto block = &blockSource->getBlock(pos); + std::string blockName; + if (!(block == BedrockBlocks::mAir)) { + blockName = block->getTypeName(); + + auto states = block->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + blockName += + " [" + states.substr(1, states.length() - 2) + "]"; + } + + auto exBlock = &blockSource->getExtraBlock(pos); + std::string exBlockName; + if (!(exBlock == BedrockBlocks::mAir)) { + exBlockName = exBlock->getTypeName(); + + auto exStates = exBlock->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + exBlockName += + " [" + exStates.substr(1, exStates.length() - 2) + "]"; + } + if (blockName != "") { + if (blocksMap.contains(blockName)) { + blocksMap[blockName] += 1; + } else { + blocksMap[blockName] = 1; + } } - } - - if (arg_l) { - phmap::flat_hash_map blocksMap; - std::vector> blocksMap2; - blocksMap2.resize(0); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto block = &blockSource->getBlock(pos); - std::string blockName; - if (!(block == BedrockBlocks::mAir)) { - blockName = block->getTypeName(); - - auto states = block->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - blockName += " [" + states.substr(1, states.length() - 2) + "]"; + if (exBlockName != "") { + if (blocksMap.contains(exBlockName)) { + blocksMap[exBlockName] += 1; + } else { + blocksMap[exBlockName] = 1; } + } + auto blockInstance = blockSource->getBlockInstance(pos); - auto exBlock = &blockSource->getExtraBlock(pos); - std::string exBlockName; - if (!(exBlock == BedrockBlocks::mAir)) { - exBlockName = exBlock->getTypeName(); - - auto exStates = exBlock->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - exBlockName += " [" + exStates.substr(1, exStates.length() - 2) + "]"; - } - if (blockName != "") { - if (blocksMap.contains(blockName)) { - blocksMap[blockName] += 1; - } else { - blocksMap[blockName] = 1; - } - } - if (exBlockName != "") { - if (blocksMap.contains(exBlockName)) { - blocksMap[exBlockName] += 1; - } else { - blocksMap[exBlockName] = 1; + if (blockInstance.hasContainer()) { + auto container = blockInstance.getContainer(); + std::queue> itemQueue; + for (auto& item : container->getAllSlots()) { + if (item->getCount() > 0) { + itemQueue.emplace( + const_cast(item)->getNbt() + ); } } - auto blockInstance = blockSource->getBlockInstance(pos); + while (!itemQueue.empty()) { + auto* item = + ItemStack::create(std::move(itemQueue.front())); + itemQueue.pop(); + auto count = item->getCount(); + if (count > 0) { + std::string name; + if (item->isBlock()) { + auto block = item->getBlock(); + name = block->getTypeName(); + + auto states = + block->getNbt() + ->value() + .at("states") + .asCompoundTag() + ->toSNBT(0, SnbtFormat::Minimize); + name += " [" + + states.substr(1, states.length() - 2) + + "]"; - if (blockInstance.hasContainer()) { - auto container = blockInstance.getContainer(); - std::queue> itemQueue; - for (auto& item : container->getAllSlots()) { - if (item->getCount() > 0) { - itemQueue.emplace(const_cast(item)->getNbt()); - } - } - while (!itemQueue.empty()) { - auto* item = ItemStack::create(std::move(itemQueue.front())); - itemQueue.pop(); - auto count = item->getCount(); - if (count > 0) { - std::string name; - if (item->isBlock()) { - auto block = item->getBlock(); - name = block->getTypeName(); - - auto states = block->getNbt()->value().at("states").asCompoundTag()->toSNBT( - 0, SnbtFormat::Minimize); - name += " [" + states.substr(1, states.length() - 2) + "]"; - - } else { - name = item->getTypeName(); - - name += " ["; - auto customName = item->getCustomName(); - if (customName != "") { - name += "\"name\":\"" + customName + "\""; - } - name += "]"; - } - if (!blocksMap.contains(name)) { - blocksMap[name] = count; - } else { - blocksMap[name] += count; + } else { + name = item->getTypeName(); + + name += " ["; + auto customName = item->getCustomName(); + if (customName != "") { + name += "\"name\":\"" + customName + "\""; } + name += "]"; + } + if (!blocksMap.contains(name)) { + blocksMap[name] = count; + } else { + blocksMap[name] += count; + } - auto iNbt = item->getNbt(); - if (iNbt->contains("tag", Tag::Type::Compound) && - iNbt->getCompound("tag")->contains("Items", Tag::Type::List)) { - iNbt->getCompound("tag")->getList("Items")->forEachCompoundTag( + auto iNbt = item->getNbt(); + if (iNbt->contains("tag", Tag::Type::Compound) + && iNbt->getCompound("tag") + ->contains("Items", Tag::Type::List)) { + iNbt->getCompound("tag") + ->getList("Items") + ->forEachCompoundTag( [&](class CompoundTag const& mItem) { itemQueue.emplace(mItem.clone()); - }); - } + } + ); } - delete item; - item = nullptr; } + delete item; + item = nullptr; } - }); - - for (auto& block : blocksMap) { - std::string name = block.first; - blocksMap2.emplace_back(std::pair(name, block.second)); - } - std::sort(blocksMap2.begin(), blocksMap2.end(), - [](const std::pair& a, - const std::pair& b) { return a.second > b.second; }); - std::ofstream outStr(WE_DIR + "structures/" + filename + "_list.txt", std::ios::out); - for (auto& block : blocksMap2) { - outStr << fmt::format("{} {}\n", block.second, block.first); } - outStr.close(); - output.trSuccess("worldedit.exportstr.list"); + }); + + for (auto& block : blocksMap) { + std::string name = block.first; + blocksMap2.emplace_back( + std::pair(name, block.second) + ); + } + std::sort( + blocksMap2.begin(), + blocksMap2.end(), + [](const std::pair& a, + const std::pair& b) { + return a.second > b.second; + } + ); + std::ofstream outStr( + WE_DIR + "structures/" + filename + "_list.txt", + std::ios::out + ); + for (auto& block : blocksMap2) { + outStr << fmt::format("{} {}\n", block.second, block.first); } - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "image", // command name - tr("worldedit.command.description.image"), // command description - { - {"fliptype", {"none", "flipu", "flipv", "flipuv"}}, - {"rotation", {"none", "rotate90", "rotate180", "rotate270"}}, - {"file", {"file"}}, - {"link", {"link"}}, - }, - { - ParamData("imagefilename", ParamType::SoftEnum, "imagefilename"), - ParamData("url", ParamType::String, "url"), - ParamData("fliptype", ParamType::Enum, true, "fliptype"), - ParamData("rotation", ParamType::Enum, true, "rotation"), - ParamData("file", ParamType::Enum, "file"), - ParamData("link", ParamType::Enum, "link"), - }, - { - {"file", "imagefilename", "fliptype", "rotation"}, - {"link", "url", "fliptype", "rotation"}, - }, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; + outStr.close(); + output.trSuccess("worldedit.exportstr.list"); } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto size = boundingBox.max - boundingBox.min; - auto blockSource = &player->getDimensionBlockSource(); - - int flipInt = 0; - - if (results["fliptype"].isSet) { - auto fliptype = results["fliptype"].getRaw(); - if (fliptype == "flipu") { - flipInt = 1; - } else if (fliptype == "flipv") { - flipInt = 2; - } else if (fliptype == "flipuv") { - flipInt = 3; - } + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "image", // command name + tr("worldedit.command.description.image"), // command description + { + {"fliptype", {"none", "flipu", "flipv", "flipuv"} }, + {"rotation", {"none", "rotate90", "rotate180", "rotate270"}}, + {"file", {"file"} }, + {"link", {"link"} }, + }, + { + ParamData("imagefilename", ParamType::SoftEnum, "imagefilename"), + ParamData("url", ParamType::String, "url"), + ParamData("fliptype", ParamType::Enum, true, "fliptype"), + ParamData("rotation", ParamType::Enum, true, "rotation"), + ParamData("file", ParamType::Enum, "file"), + ParamData("link", ParamType::Enum, "link"), + }, + { + {"file", "imagefilename", "fliptype", "rotation"}, + {"link", "url", "fliptype", "rotation"}, + }, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto size = boundingBox.max - boundingBox.min; + auto blockSource = &player->getDimensionBlockSource(); + + int flipInt = 0; + + if (results["fliptype"].isSet) { + auto fliptype = results["fliptype"].getRaw(); + if (fliptype == "flipu") { + flipInt = 1; + } else if (fliptype == "flipv") { + flipInt = 2; + } else if (fliptype == "flipuv") { + flipInt = 3; } + } - int rotationInt = 0; + int rotationInt = 0; - if (results["rotation"].isSet) { - auto rotation = results["rotation"].getRaw(); - if (rotation == "rotate90") { - rotationInt = 1; - } else if (rotation == "rotate180") { - rotationInt = 2; - } else if (rotation == "rotate270") { - rotationInt = 3; - } + if (results["rotation"].isSet) { + auto rotation = results["rotation"].getRaw(); + if (rotation == "rotate90") { + rotationInt = 1; + } else if (rotation == "rotate180") { + rotationInt = 2; + } else if (rotation == "rotate270") { + rotationInt = 3; } + } - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; - boundingBox.forEachBlockInBox([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } + boundingBox.forEachBlockInBox([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + auto blockInstance = blockSource->getBlockInstance(pos); + history.storeBlock(blockInstance, localPos); + }); + } - auto blockColorMap = getColorBlockMap(); + auto blockColorMap = getColorBlockMap(); - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); - long long i = 0; + long long i = 0; - std::string filename; - if (results["imagefilename"].isSet) { - filename = results["imagefilename"].get(); + std::string filename; + if (results["imagefilename"].isSet) { + filename = results["imagefilename"].get(); - filename = WE_DIR + "image/" + filename; - } else /* if (results["link"].isSet)*/ { - if (downloadImage(results["url"].get())) { - filename = WE_DIR + "imgtemp/0image"; - } else { - output.trError("worldedit.error.download-image"); - return; - } + filename = WE_DIR + "image/" + filename; + } else /* if (results["link"].isSet)*/ { + if (downloadImage(results["url"].get())) { + filename = WE_DIR + "imgtemp/0image"; + } else { + output.trError("worldedit.error.download-image"); + return; } + } - auto texture2D = loadImage(filename); - - Sampler sampler(SamplerType::Bilinear, EdgeType::CLAMP); - - std::function rotate; - - switch (rotationInt) { - case 1: - rotate = [&](double& u, double& v) { - std::swap(u, v); - u = 1 - u; - }; - break; - case 2: - rotate = [&](double& u, double& v) { - u = 1 - u; - v = 1 - v; - }; - break; - case 3: - rotate = [&](double& u, double& v) { - std::swap(u, v); - v = 1 - v; - }; - break; - default: - rotate = [&](double& u, double& v) {}; - } - - region->forEachBlockUVInRegion([&](const BlockPos& pos, double u, double v) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + auto texture2D = loadImage(filename); - if (flipInt != 3) { - if (flipInt != 1) { - u = 1 - u; - } - if (flipInt != 2) { - v = 1 - v; - } - } + Sampler sampler(SamplerType::Bilinear, EdgeType::CLAMP); - rotate(u, v); + std::function rotate; + + switch (rotationInt) { + case 1: + rotate = [&](double& u, double& v) { + std::swap(u, v); + u = 1 - u; + }; + break; + case 2: + rotate = [&](double& u, double& v) { + u = 1 - u; + v = 1 - v; + }; + break; + case 3: + rotate = [&](double& u, double& v) { + std::swap(u, v); + v = 1 - v; + }; + break; + default: + rotate = [&](double& u, double& v) {}; + } - auto color = texture2D.sample(sampler, u, v); + region->forEachBlockUVInRegion([&](BlockPos const& pos, double u, double v + ) { + setFunction(variables, f, boundingBox, playerPos, pos, center); - double minDist = DBL_MAX; - Block const* minBlock = (Block const*)BedrockBlocks::mAir; - for (auto& i : blockColorMap) { - if (i.first.a == 1) { - auto dst = i.first.distanceTo(color); - if (dst < minDist) { - minDist = dst; - minBlock = i.second; - } - } + if (flipInt != 3) { + if (flipInt != 1) { + u = 1 - u; } - if (RNG::rand() <= color.a) { - i += playerData.setBlockSimple(blockSource, f, variables, pos, minBlock); + if (flipInt != 2) { + v = 1 - v; } - }); + } - output.trSuccess("worldedit.image.success"); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - - DynamicCommand::setup( - "removeitem", // command name - tr("worldedit.command.description.removeitem"), // command description - {}, - {ParamData("item", ParamType::Item, true, "item"), ParamData("num", ParamType::Int, true, "num"), - ParamData("data", ParamType::Int, true, "data")}, - {{"item", "num", "data"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (playerData.region != nullptr && playerData.region->hasSelected()) { - auto& region = playerData.region; - auto center = region->getCenter(); - auto dimID = region->getDimensionID(); - auto boundingBox = region->getBoundBox(); - auto blockSource = &player->getDimensionBlockSource(); + rotate(u, v); - if (playerData.maxHistoryLength > 0) { - auto& history = playerData.getNextHistory(); - history = std::move(Clipboard(boundingBox.max - boundingBox.min)); - history.playerRelPos.x = dimID; - history.playerPos = boundingBox.min; + auto color = texture2D.sample(sampler, u, v); - region->forEachBlockInRegion([&](const BlockPos& pos) { - auto localPos = pos - boundingBox.min; - auto blockInstance = blockSource->getBlockInstance(pos); - history.storeBlock(blockInstance, localPos); - }); - } - int num = -1; - if (results["num"].isSet) { - num = results["num"].get(); - } - int data = -2144000000; - if (results["data"].isSet) { - data = results["data"].get(); + double minDist = DBL_MAX; + Block const* minBlock = (Block const*)BedrockBlocks::mAir; + for (auto& i : blockColorMap) { + if (i.first.a == 1) { + auto dst = i.first.distanceTo(color); + if (dst < minDist) { + minDist = dst; + minBlock = i.second; + } + } } - long long i = 0; - - auto playerPos = origin.getWorldPosition(); - auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); - ; - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - - auto cmdItem = results["item"] - .getRaw() - .createInstance(1, data, nullptr, true) - .value_or(ItemInstance::EMPTY_ITEM); - region->forEachBlockInRegion([&](const BlockPos& pos) { - setFunction(variables, f, boundingBox, playerPos, pos, center); + if (RNG::rand() <= color.a) { + i += + playerData + .setBlockSimple(blockSource, f, variables, pos, minBlock); + } + }); + + output.trSuccess("worldedit.image.success"); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); + + DynamicCommand::setup( + "removeitem", // command name + tr("worldedit.command.description.removeitem"), // command description + { + }, + {ParamData("item", ParamType::Item, true, "item"), + ParamData("num", ParamType::Int, true, "num"), + ParamData("data", ParamType::Int, true, "data")}, + {{"item", "num", "data"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (playerData.region != nullptr && playerData.region->hasSelected()) { + auto& region = playerData.region; + auto center = region->getCenter(); + auto dimID = region->getDimensionID(); + auto boundingBox = region->getBoundBox(); + auto blockSource = &player->getDimensionBlockSource(); + + if (playerData.maxHistoryLength > 0) { + auto& history = playerData.getNextHistory(); + history = std::move(Clipboard(boundingBox.max - boundingBox.min)); + history.playerRelPos.x = dimID; + history.playerPos = boundingBox.min; + + region->forEachBlockInRegion([&](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; auto blockInstance = blockSource->getBlockInstance(pos); - if (blockInstance.hasContainer()) { - auto container = blockInstance.getContainer(); - for (auto& constItem : container->getAllSlots()) { - auto item = const_cast(constItem); - int count = item->getCount(); - if (count <= 0) { + history.storeBlock(blockInstance, localPos); + }); + } + int num = -1; + if (results["num"].isSet) { + num = results["num"].get(); + } + int data = -2144000000; + if (results["data"].isSet) { + data = results["data"].get(); + } + long long i = 0; + + auto playerPos = origin.getWorldPosition(); + auto playerRot = origin.getRotation().value_or(Vec2::UNIT_X); + ; + EvalFunctions f; + f.setbs(blockSource); + f.setbox(boundingBox); + phmap::flat_hash_map variables; + playerData.setVarByPlayer(variables); + + auto cmdItem = results["item"] + .getRaw() + .createInstance(1, data, nullptr, true) + .value_or(ItemInstance::EMPTY_ITEM); + region->forEachBlockInRegion([&](BlockPos const& pos) { + setFunction(variables, f, boundingBox, playerPos, pos, center); + auto blockInstance = blockSource->getBlockInstance(pos); + if (blockInstance.hasContainer()) { + auto container = blockInstance.getContainer(); + for (auto& constItem : container->getAllSlots()) { + auto item = const_cast(constItem); + int count = item->getCount(); + if (count <= 0) { + continue; + } + auto iNbt = item->getNbt(); + if (iNbt->contains("tag", Tag::Type::Compound) + && iNbt->getCompound("tag") + ->contains("Items", Tag::Type::List)) { + if (count != 1) { continue; } - auto iNbt = item->getNbt(); - if (iNbt->contains("tag", Tag::Type::Compound) && - iNbt->getCompound("tag")->contains("Items", Tag::Type::List)) { - if (count != 1) { + auto& cmap = + iNbt->getCompound("tag")->getList("Items")->value(); + std::vector afterVal; + afterVal.clear(); + for (auto& mItem : cmap) { + auto* shulkItem = + ItemStack::create(mItem->asCompoundTag()->clone() + ); + int count2 = shulkItem->getCount(); + + if (count2 <= 0 + || !( + cmdItem == ItemInstance::EMPTY_ITEM + || shulkItem->sameItemAndAuxAndBlockData( + cmdItem + ) + ) + || (data >= -2140000000 + && data != shulkItem->getAuxValue())) { + delete shulkItem; continue; } - auto& cmap = iNbt->getCompound("tag")->getList("Items")->value(); - std::vector afterVal; - afterVal.clear(); - for (auto& mItem : cmap) { - auto* shulkItem = ItemStack::create(mItem->asCompoundTag()->clone()); - int count2 = shulkItem->getCount(); - - if (count2 <= 0 || - !(cmdItem == ItemInstance::EMPTY_ITEM || - shulkItem->sameItemAndAuxAndBlockData(cmdItem)) || - (data >= -2140000000 && data != shulkItem->getAuxValue())) { - delete shulkItem; - continue; - } - int removeNum2 = num > 0 ? std::min(num, count2) : count2; - i += removeNum2; - if (num > 0) { - num -= removeNum2; - } - if (removeNum2 == count2) { - delete shulkItem; - continue; - } - shulkItem->remove(removeNum2); - afterVal.push_back(shulkItem->getNbt().get()); + int removeNum2 = + num > 0 ? std::min(num, count2) : count2; + i += removeNum2; + if (num > 0) { + num -= removeNum2; + } + if (removeNum2 == count2) { delete shulkItem; + continue; } - cmap = afterVal; - item->setNbt(iNbt.get()); - continue; + shulkItem->remove(removeNum2); + afterVal.push_back(shulkItem->getNbt().get()); + delete shulkItem; } + cmap = afterVal; + item->setNbt(iNbt.get()); + continue; + } - if (!(cmdItem == ItemInstance::EMPTY_ITEM || - item->sameItemAndAuxAndBlockData(cmdItem)) || - (data >= -2140000000 && data != item->getAuxValue())) { - continue; - } + if (!(cmdItem == ItemInstance::EMPTY_ITEM + || item->sameItemAndAuxAndBlockData(cmdItem)) + || (data >= -2140000000 && data != item->getAuxValue())) { + continue; + } - int removeNum = num > 0 ? std::min(num, count) : count; - item->remove(removeNum); - i += removeNum; - if (num > 0) { - num -= removeNum; - } - if (num == 0) { - return; - } + int removeNum = num > 0 ? std::min(num, count) : count; + item->remove(removeNum); + i += removeNum; + if (num > 0) { + num -= removeNum; + } + if (num == 0) { + return; } } - }); + } + }); - output.trSuccess("worldedit.removeitem.success", i); - } else { - output.trError("worldedit.error.incomplete-region"); - } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + output.trSuccess("worldedit.removeitem.success", i); + } else { + output.trError("worldedit.error.incomplete-region"); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/allCommand.cpp b/old/core/command/allCommand.cpp index f582b42..57c0abe 100644 --- a/old/core/command/allCommand.cpp +++ b/old/core/command/allCommand.cpp @@ -1,267 +1,321 @@ -// -// Created by OEOTYAN on 2022/09/04. -// #include "allCommand.hpp" -#include -#include "filesys/file.h" -#include "eval/Eval.h" #include "WorldEdit.h" +#include "eval/Eval.h" +#include "filesys/file.h" #include "utils/StringTool.h" +#include #include -#include "mc/Level.hpp" #include "mc/Block.hpp" -#include "mc/MobSpawnRules.hpp" #include "mc/BlockTypeRegistry.hpp" +#include "mc/Level.hpp" +#include "mc/MobSpawnRules.hpp" #include "mc/SpawnGroupData.hpp" #include "mc/SpawnGroupRegistry.hpp" -namespace worldedit { - void updateFile() { - Global->setSoftEnumValues("imagefilename", getWEFiles("image")); - Global->setSoftEnumValues( - "modelfilename", - getWEFiles("models", [](std::string_view s) -> bool { return s.substr(s.size() - 4) == ".obj"; })); - } +namespace we { +void updateFile() { + Global->setSoftEnumValues("imagefilename", getWEFiles("image")); + Global->setSoftEnumValues( + "modelfilename", + getWEFiles( + "models", + [](std::string_view s) -> bool { return s.substr(s.size() - 4) == ".obj"; } + ) + ); +} - void commandsSetup() { - brushCommandSetup(); - regionCommandSetup(); - historyCommandSetup(); - handToolCommandSetup(); - clipboardCommandSetup(); - regionInfoCommandSetup(); - generationCommandSetup(); - regionOperationCommandSetup(); +void commandsSetup() { + brushCommandSetup(); + regionCommandSetup(); + historyCommandSetup(); + handToolCommandSetup(); + clipboardCommandSetup(); + regionInfoCommandSetup(); + generationCommandSetup(); + regionOperationCommandSetup(); - Schedule::delay( - [&]() { - updateFile(); - setArg("-ahor"); - setArg("-anose"); - setArg("-h"); - setArg("-l"); - setArg("-c"); - setArg("-ca"); - setArg("-cd"); - setArg("-hv"); - setArg("-hcr"); - setArg("-sa"); - setArg("-sale"); - std::vector blocksName; - blocksName.clear(); - blocksName.push_back("#clipboard"); - blocksName.push_back("#lighten"); - blocksName.push_back("#darken"); - blocksName.push_back("#hand"); + Schedule::delay( + [&]() { + updateFile(); + setArg("-ahor"); + setArg("-anose"); + setArg("-h"); + setArg("-l"); + setArg("-c"); + setArg("-ca"); + setArg("-cd"); + setArg("-hv"); + setArg("-hcr"); + setArg("-sa"); + setArg("-sale"); + std::vector blocksName; + blocksName.clear(); + blocksName.push_back("#clipboard"); + blocksName.push_back("#lighten"); + blocksName.push_back("#darken"); + blocksName.push_back("#hand"); - for (auto& b : getJavaBlockMap()) { - if (!isBEBlock(b.first)) { - blocksName.push_back(b.first); - } + for (auto& b : getJavaBlockMap()) { + if (!isBEBlock(b.first)) { + blocksName.push_back(b.first); } + } - Global->setSoftEnumValues("blockPattern", blocksName); + Global->setSoftEnumValues("blockPattern", blocksName); - addFileWatch(WE_DIR + "image", - [&](const std::filesystem::path& path, const filewatch::Event change_type) { - if (change_type == filewatch::Event::modified) { - return; - } - auto fileName = UTF82String(path.u8string()); + addFileWatch( + WE_DIR + "image", + [&](const std::filesystem::path& path, + const filewatch::Event change_type) { + if (change_type == filewatch::Event::modified) { + return; + } + auto fileName = UTF82String(path.u8string()); - if (fileName.find(".") == std::string::npos) { - return; - } + if (fileName.find(".") == std::string::npos) { + return; + } - ReplaceStr(fileName, "\\", "/"); - std::vector fileEnum{fileName}; - switch (change_type) { - case filewatch::Event::renamed_new: - case filewatch::Event::added: - Global->addSoftEnumValues("imagefilename", fileEnum); - break; - case filewatch::Event::renamed_old: - case filewatch::Event::removed: - Global->removeSoftEnumValues("imagefilename", fileEnum); - break; - } - }); + ReplaceStr(fileName, "\\", "/"); + std::vector fileEnum{fileName}; + switch (change_type) { + case filewatch::Event::renamed_new: + case filewatch::Event::added: + Global->addSoftEnumValues( + "imagefilename", + fileEnum + ); + break; + case filewatch::Event::renamed_old: + case filewatch::Event::removed: + Global->removeSoftEnumValues( + "imagefilename", + fileEnum + ); + break; + } + } + ); - addFileWatch( - WE_DIR + "models", [&](const std::filesystem::path& path, const filewatch::Event change_type) { - if (change_type == filewatch::Event::modified) { - return; - } - auto fileName = UTF82String(path.u8string()); + addFileWatch( + WE_DIR + "models", + [&](const std::filesystem::path& path, + const filewatch::Event change_type) { + if (change_type == filewatch::Event::modified) { + return; + } + auto fileName = UTF82String(path.u8string()); - if (fileName.find(".") == std::string::npos || fileName.substr(fileName.size() - 4) != ".obj") { - return; - } + if (fileName.find(".") == std::string::npos + || fileName.substr(fileName.size() - 4) != ".obj") { + return; + } - ReplaceStr(fileName, "\\", "/"); - std::vector fileEnum{fileName}; - switch (change_type) { - case filewatch::Event::renamed_new: - case filewatch::Event::added: - Global->addSoftEnumValues("modelfilename", fileEnum); - break; - case filewatch::Event::renamed_old: - case filewatch::Event::removed: - Global->removeSoftEnumValues("modelfilename", fileEnum); - break; - } - }); - }, - 20); + ReplaceStr(fileName, "\\", "/"); + std::vector fileEnum{fileName}; + switch (change_type) { + case filewatch::Event::renamed_new: + case filewatch::Event::added: + Global->addSoftEnumValues( + "modelfilename", + fileEnum + ); + break; + case filewatch::Event::renamed_old: + case filewatch::Event::removed: + Global->removeSoftEnumValues( + "modelfilename", + fileEnum + ); + break; + } + } + ); + }, + 20 + ); - // DynamicCommand::setup( - // "updatefile", // command name - // tr("worldedit.command.description.updatefile"), // command description - // {}, {}, {{}}, - // // dynamic command callback - // [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - // std::unordered_map& results) { - // updateFile(); - // output.trSuccess("worldedit.updatefile.success"); - // }, - // CommandPermissionLevel::GameMasters); + // DynamicCommand::setup( + // "updatefile", // command name + // tr("worldedit.command.description.updatefile"), // command description + // {}, {}, {{}}, + // // dynamic command callback + // [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& + // output, + // std::unordered_map& results) { + // updateFile(); + // output.trSuccess("worldedit.updatefile.success"); + // }, + // CommandPermissionLevel::GameMasters); - DynamicCommand::setup( - "gmask", // command name - tr("worldedit.command.description.gmask"), // command description - {}, {ParamData("mask", ParamType::String, true, "mask")}, {{"mask"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (results["mask"].isSet) { - auto str = results["mask"].getRaw(); - playerData.gMask = str; - output.trSuccess("worldedit.gmask.success", str); - } else { - playerData.gMask = ""; - output.trSuccess("worldedit.gmask.clear"); - } - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "gmask", // command name + tr("worldedit.command.description.gmask"), // command description + {}, + {ParamData("mask", ParamType::String, true, "mask")}, + {{"mask"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (results["mask"].isSet) { + auto str = results["mask"].getRaw(); + playerData.gMask = str; + output.trSuccess("worldedit.gmask.success", str); + } else { + playerData.gMask = ""; + output.trSuccess("worldedit.gmask.clear"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "neighberupdate", // command name - tr("worldedit.command.description.neighberupdate"), // command description - {}, {ParamData("bool", ParamType::Bool, "bool")}, {{"bool"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (results["bool"].get()) { - playerData.updateArg = 1; - output.trSuccess("worldedit.neighberupdate.on"); - } else { - playerData.updateArg = 0; - output.trSuccess("worldedit.neighberupdate.off"); - } - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "neighberupdate", // command name + tr("worldedit.command.description.neighberupdate"), // command description + {}, + {ParamData("bool", ParamType::Bool, "bool")}, + {{"bool"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (results["bool"].get()) { + playerData.updateArg = 1; + output.trSuccess("worldedit.neighberupdate.on"); + } else { + playerData.updateArg = 0; + output.trSuccess("worldedit.neighberupdate.off"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "blockupdate", // command name - tr("worldedit.command.description.blockupdate"), // command description - {}, {ParamData("bool", ParamType::Bool, "bool")}, {{"bool"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto xuid = player->getXuid(); - auto& playerData = getPlayersData(xuid); - if (results["bool"].get()) { - playerData.updateExArg = 1; - output.trSuccess("worldedit.blockupdate.on"); - } else { - playerData.updateExArg = 0; - output.trSuccess("worldedit.blockupdate.off"); - } - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "blockupdate", // command name + tr("worldedit.command.description.blockupdate"), // command description + {}, + {ParamData("bool", ParamType::Bool, "bool")}, + {{"bool"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto xuid = player->getXuid(); + auto& playerData = getPlayersData(xuid); + if (results["bool"].get()) { + playerData.updateExArg = 1; + output.trSuccess("worldedit.blockupdate.on"); + } else { + playerData.updateExArg = 0; + output.trSuccess("worldedit.blockupdate.off"); + } + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "wand", // command name - tr("worldedit.command.description.wand"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - Level::runcmdAs(player, "give @s wooden_axe"); - output.trSuccess(""); - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "wand", // command name + tr("worldedit.command.description.wand"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + Level::runcmdAs(player, "give @s wooden_axe"); + output.trSuccess(""); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "clearplayerdatas", // command name - tr("worldedit.command.description.clearplayerdatas"), // command description - {}, {}, {{}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - getPlayersDataMap().erase(player->getXuid()); - output.trSuccess("worldedit.clearplayerdatas.success"); - }, - CommandPermissionLevel::GameMasters); + DynamicCommand::setup( + "clearplayerdatas", // command name + tr("worldedit.command.description.clearplayerdatas"), // command description + {}, + {}, + {{}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + getPlayersDataMap().erase(player->getXuid()); + output.trSuccess("worldedit.clearplayerdatas.success"); + }, + CommandPermissionLevel::GameMasters + ); - DynamicCommand::setup( - "wetest", // command name - "wetest", // command description - {}, - { - ParamData("block", ParamType::Block, "block"), - ParamData("blockstates", ParamType::BlockState, "blockstates"), - }, - {{"block", "blockstates"}}, - // dynamic command callback - [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, - std::unordered_map& results) { - auto player = origin.getPlayer(); - if (player == nullptr) { - output.trError("worldedit.error.noplayer"); - return; - } - auto dimID = player->getDimensionId(); - auto blockSource = &player->getDimensionBlockSource(); + DynamicCommand::setup( + "wetest", // command name + "wetest", // command description + { + }, + { + ParamData("block", ParamType::Block, "block"), + ParamData("blockstates", ParamType::BlockState, "blockstates"), + }, + {{"block", "blockstates"}}, + // dynamic command callback + [](DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results) { + auto player = origin.getPlayer(); + if (player == nullptr) { + output.trError("worldedit.error.noplayer"); + return; + } + auto dimID = player->getDimensionId(); + auto blockSource = &player->getDimensionBlockSource(); - auto states = results["blockstates"].get>(); + auto states = + results["blockstates"].get>(); - output.success(BlockTypeRegistry::getBlockNameFromNameHash(results["block"].get())); - for (auto& state : states) { - output.success(state.mBlockState + " : " + state.mValue); - } - }, - CommandPermissionLevel::GameMasters); - } -} // namespace worldedit \ No newline at end of file + output.success(BlockTypeRegistry::getBlockNameFromNameHash( + results["block"].get() + )); + for (auto& state : states) { + output.success(state.mBlockState + " : " + state.mValue); + } + }, + CommandPermissionLevel::GameMasters + ); +} +} // namespace we \ No newline at end of file diff --git a/old/core/command/allCommand.hpp b/old/core/command/allCommand.hpp index d3b6c0d..9f94eea 100644 --- a/old/core/command/allCommand.hpp +++ b/old/core/command/allCommand.hpp @@ -1,30 +1,27 @@ -// -// Created by OEOTYAN on 2022/05/16. -// -#include #include "llapi/utils/StringHelper.h" +#include -namespace worldedit { - // Direct setup of dynamic command with necessary information - using ParamType = DynamicCommand::ParameterType; - using ParamData = DynamicCommand::ParameterData; +namespace we { +// Direct setup of dynamic command with necessary information +using ParamType = DynamicCommand::ParameterType; +using ParamData = DynamicCommand::ParameterData; - inline void setArg(std::string_view args) { - std::vector arg; - arg.clear(); - for (auto& c : args.substr(1)) { - arg.push_back(std::string("-") + c); - } - Global->setSoftEnumValues(asString(args), arg); +inline void setArg(std::string_view args) { + std::vector arg; + arg.clear(); + for (auto& c : args.substr(1)) { + arg.push_back(std::string("-") + c); } + Global->setSoftEnumValues(asString(args), arg); +} - void commandsSetup(); - void brushCommandSetup(); - void regionCommandSetup(); - void historyCommandSetup(); - void handToolCommandSetup(); - void clipboardCommandSetup(); - void regionInfoCommandSetup(); - void generationCommandSetup(); - void regionOperationCommandSetup(); -} // namespace worldedit \ No newline at end of file +void commandsSetup(); +void brushCommandSetup(); +void regionCommandSetup(); +void historyCommandSetup(); +void handToolCommandSetup(); +void clipboardCommandSetup(); +void regionInfoCommandSetup(); +void generationCommandSetup(); +void regionOperationCommandSetup(); +} // namespace we \ No newline at end of file diff --git a/old/core/data/PlayerData.cpp b/old/core/data/PlayerData.cpp index fb82732..8d20783 100644 --- a/old/core/data/PlayerData.cpp +++ b/old/core/data/PlayerData.cpp @@ -1,233 +1,244 @@ -// -// Created by OEOTYAN on 2023/01/28. -// #pragma once #include "PlayerData.h" #include "WorldEdit.h" -#include "eval/Eval.h" #include "eval/CppEval.h" -#include +#include "eval/Eval.h" +#include "region/Regions.h" #include -#include +#include #include #include -#include +#include +#include +#include #include +#include +#include #include -#include #include -#include -#include -#include "region/Regions.h" -namespace worldedit { +namespace we { - void PlayerData::clearHistory() { - historyList.clear(); - historyList.resize(maxHistoryLength); - historyFlag1 = 0; - historyFlag2 = 0; - } +void PlayerData::clearHistory() { + historyList.clear(); + historyList.resize(maxHistoryLength); + historyFlag1 = 0; + historyFlag2 = 0; +} - PlayerData::PlayerData() { - historyList.resize(0); - } +PlayerData::PlayerData() { historyList.resize(0); } - PlayerData::PlayerData(::Player* player) { - historyList.resize(maxHistoryLength); - xuid = player->getXuid(); - } +PlayerData::PlayerData(::Player* player) { + historyList.resize(maxHistoryLength); + xuid = player->getXuid(); +} - bool PlayerData::changeVicePos(BlockInstance blockInstance, bool output) { - Player* player = Global->getPlayer(xuid); - if (blockInstance == BlockInstance::Null) { - if (output) - player->trSendText("worldedit.selection.empty.explain.secondary"); - return false; - } - if (region == nullptr) { - region = Region::createRegion(RegionType::CUBOID); - } - auto pos = blockInstance.getPosition(); - if (player->getDimensionId() != region->getDimensionID()) { - region->selecting = false; - } - if (region->setVicePos(pos, player->getDimensionId())) { - if (output) - player->trSendText("worldedit.selection." + region->getName() + ".explain.secondary", pos.toString(), - region->size()); - vicePos = pos; - vicePosTime = 0; - vicePosDim = player->getDimensionId(); - return true; - } else { - if (output) - player->trSendText("worldedit.selection.failed.explain.secondary"); - } +bool PlayerData::changeVicePos(BlockInstance blockInstance, bool output) { + Player* player = Global->getPlayer(xuid); + if (blockInstance == BlockInstance::Null) { + if (output) player->trSendText("worldedit.selection.empty.explain.secondary"); return false; } + if (region == nullptr) { + region = Region::createRegion(RegionType::CUBOID); + } + auto pos = blockInstance.getPosition(); + if (player->getDimensionId() != region->getDimensionID()) { + region->selecting = false; + } + if (region->setVicePos(pos, player->getDimensionId())) { + if (output) + player->trSendText( + "worldedit.selection." + region->getName() + ".explain.secondary", + pos.toString(), + region->size() + ); + vicePos = pos; + vicePosTime = 0; + vicePosDim = player->getDimensionId(); + return true; + } else { + if (output) player->trSendText("worldedit.selection.failed.explain.secondary"); + } + return false; +} - bool PlayerData::changeMainPos(BlockInstance blockInstance, bool output) { - Player* player = Global->getPlayer(xuid); - if (blockInstance == BlockInstance::Null) { - if (output) - player->trSendText("worldedit.selection.empty.explain.primary"); - return false; - } - if (region == nullptr) { - region = Region::createRegion(RegionType::CUBOID); - } - auto pos = blockInstance.getPosition(); - if (player->getDimensionId() != region->getDimensionID()) { - region->selecting = false; - } - if (region->setMainPos(pos, player->getDimensionId())) { - if (output) - player->trSendText("worldedit.selection." + region->getName() + ".explain.primary", pos.toString(), - region->size()); - mainPos = pos; - mainPosTime = 0; - mainPosDim = player->getDimensionId(); - if (region->needResetVice) { - vicePosDim = -1; - } - return true; - } else { - if (output) - player->trSendText("worldedit.selection.failed.explain.primary"); - } +bool PlayerData::changeMainPos(BlockInstance blockInstance, bool output) { + Player* player = Global->getPlayer(xuid); + if (blockInstance == BlockInstance::Null) { + if (output) player->trSendText("worldedit.selection.empty.explain.primary"); return false; } - - void PlayerData::setVarByPlayer(phmap::flat_hash_map<::std::string, double>& variables) { - Player* player = Global->getPlayer(xuid); - auto playerPos = player->getPosition(); - auto playerRot = player->getRotation(); - variables["px"] = playerPos.x; - variables["py"] = playerPos.y; - variables["pz"] = playerPos.z; - variables["pp"] = playerRot.x; - variables["pt"] = playerRot.y; + if (region == nullptr) { + region = Region::createRegion(RegionType::CUBOID); + } + auto pos = blockInstance.getPosition(); + if (player->getDimensionId() != region->getDimensionID()) { + region->selecting = false; + } + if (region->setMainPos(pos, player->getDimensionId())) { + if (output) + player->trSendText( + "worldedit.selection." + region->getName() + ".explain.primary", + pos.toString(), + region->size() + ); + mainPos = pos; + mainPosTime = 0; + mainPosDim = player->getDimensionId(); + if (region->needResetVice) { + vicePosDim = -1; + } + return true; + } else { + if (output) player->trSendText("worldedit.selection.failed.explain.primary"); } + return false; +} - bool PlayerData::setBlockWithoutcheckGMask(BlockSource* blockSource, - const BlockPos& pos, - Block const* block, - Block const* exblock, - std::optional const& biomeId) { - bool res = false; +void PlayerData::setVarByPlayer(phmap::flat_hash_map<::std::string, double>& variables) { + Player* player = Global->getPlayer(xuid); + auto playerPos = player->getPosition(); + auto playerRot = player->getRotation(); + variables["px"] = playerPos.x; + variables["py"] = playerPos.y; + variables["pz"] = playerPos.z; + variables["pp"] = playerRot.x; + variables["pt"] = playerRot.y; +} - auto& dim = blockSource->getDimension(); - ChunkBlockPos cpos(pos, dim.getMinHeight()); - SubChunkPos scpos(pos); - LevelChunk* chunk = blockSource->getChunkAt(pos); - if (chunk == nullptr || chunk->isReadOnly()) { - return false; - } +bool PlayerData::setBlockWithoutcheckGMask( + BlockSource* blockSource, + BlockPos const& pos, + Block const* block, + Block const* exblock, + std::optional const& biomeId +) { + bool res = false; - BlockActor* be = chunk->getBlockEntity(cpos); - if (be != nullptr) { - if (be->getType() != block->getBlockEntityType()) { - chunk->removeBlockEntity(pos); - } + auto& dim = blockSource->getDimension(); + ChunkBlockPos cpos(pos, dim.getMinHeight()); + SubChunkPos scpos(pos); + LevelChunk* chunk = blockSource->getChunkAt(pos); + if (chunk == nullptr || chunk->isReadOnly()) { + return false; + } + + BlockActor* be = chunk->getBlockEntity(cpos); + if (be != nullptr) { + if (be->getType() != block->getBlockEntityType()) { + chunk->removeBlockEntity(pos); } + } - if (updateExArg % 2 == 1) { - res |= blockSource->setExtraBlock(pos, *BedrockBlocks::mAir, updateArg); - res |= blockSource->setBlock(pos, *block, updateArg, nullptr, nullptr); - if (block != StaticVanillaBlocks::mBubbleColumn) { - if (exblock != BedrockBlocks::mAir) { - res |= blockSource->setExtraBlock(pos, *exblock, updateArg); - } - } else { - exblock = StaticVanillaBlocks::mFlowingWater; - res |= blockSource->setExtraBlock(pos, *exblock, updateArg + 2); - res |= blockSource->setBlock(pos, *block, updateArg + 2, nullptr, nullptr); + if (updateExArg % 2 == 1) { + res |= blockSource->setExtraBlock(pos, *BedrockBlocks::mAir, updateArg); + res |= blockSource->setBlock(pos, *block, updateArg, nullptr, nullptr); + if (block != StaticVanillaBlocks::mBubbleColumn) { + if (exblock != BedrockBlocks::mAir) { + res |= blockSource->setExtraBlock(pos, *exblock, updateArg); } } else { - auto* sc = chunk->getSubChunk(scpos.y); - auto index = cpos.toLegacyIndex(); - if (&chunk->getBlock(cpos) != block) { - res = true; - sc->_setBlock(0, index, *block); - } - if (&chunk->getExtraBlock(cpos) != exblock) { - res = true; - sc->_setBlock(1, index, *exblock); - } + exblock = StaticVanillaBlocks::mFlowingWater; + res |= blockSource->setExtraBlock(pos, *exblock, updateArg + 2); + res |= blockSource->setBlock(pos, *block, updateArg + 2, nullptr, nullptr); } - if (res) { - dim.forEachPlayer([&](Player& player) -> bool { - player.sendUpdateBlockPacket(pos, *exblock, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockLiquid); - player.sendUpdateBlockPacket(pos, *block, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockDefault); - player.sendUpdateBlockPacket(pos, *exblock, UpdateBlockFlags::BlockUpdateAll, - UpdateBlockLayer::UpdateBlockLiquid); - return true; - }); + } else { + auto* sc = chunk->getSubChunk(scpos.y); + auto index = cpos.toLegacyIndex(); + if (&chunk->getBlock(cpos) != block) { + res = true; + sc->_setBlock(0, index, *block); } - if (biomeId.has_value()) { - chunk->_setBiome(*Biome::fromId(biomeId.value()), cpos, false); + if (&chunk->getExtraBlock(cpos) != exblock) { + res = true; + sc->_setBlock(1, index, *exblock); } - return res; } + if (res) { + dim.forEachPlayer([&](Player& player) -> bool { + player.sendUpdateBlockPacket( + pos, + *exblock, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockLiquid + ); + player.sendUpdateBlockPacket( + pos, + *block, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockDefault + ); + player.sendUpdateBlockPacket( + pos, + *exblock, + UpdateBlockFlags::BlockUpdateAll, + UpdateBlockLayer::UpdateBlockLiquid + ); + return true; + }); + } + if (biomeId.has_value()) { + chunk->_setBiome(*Biome::fromId(biomeId.value()), cpos, false); + } + return res; +} - bool PlayerData::setBlockSimple(BlockSource* blockSource, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - const BlockPos& pos, - Block const* block, - Block const* exblock, - std::optional const& biomeId) { - if (gMask != "") { - if (cpp_eval::eval(gMask, var, funcs) <= 0.5) { - return false; - } +bool PlayerData::setBlockSimple( + BlockSource* blockSource, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + BlockPos const& pos, + Block const* block, + Block const* exblock, + std::optional const& biomeId +) { + if (gMask != "") { + if (cpp_eval::eval(gMask, var, funcs) <= 0.5) { + return false; } - return setBlockWithoutcheckGMask(blockSource, pos, block, exblock, biomeId); } + return setBlockWithoutcheckGMask(blockSource, pos, block, exblock, biomeId); +} - class Clipboard& PlayerData::getNextHistory() { - historyFlag2 += 1; - historyFlag2 %= maxHistoryLength; - historyFlag1 = historyFlag2; - return historyList[historyFlag2]; - } +class Clipboard& PlayerData::getNextHistory() { + historyFlag2 += 1; + historyFlag2 %= maxHistoryLength; + historyFlag1 = historyFlag2; + return historyList[historyFlag2]; +} - class Clipboard& PlayerData::getCurrentHistory() { - return historyList[historyFlag2]; - } +class Clipboard& PlayerData::getCurrentHistory() { return historyList[historyFlag2]; } - std::optional> PlayerData::getUndoHistory() { - int maximum = (historyFlag1 + 1) % maxHistoryLength; - int current = historyFlag2; - if (maximum == current) { - return std::nullopt; - } - auto& res = historyList[current]; - if (res.used == false) { - return std::nullopt; - } - current -= 1; - if (current < 0) { - current += maxHistoryLength; - } - historyFlag2 = current; - return res; +std::optional> PlayerData::getUndoHistory() { + int maximum = (historyFlag1 + 1) % maxHistoryLength; + int current = historyFlag2; + if (maximum == current) { + return std::nullopt; + } + auto& res = historyList[current]; + if (res.used == false) { + return std::nullopt; } + current -= 1; + if (current < 0) { + current += maxHistoryLength; + } + historyFlag2 = current; + return res; +} - std::optional> PlayerData::getRedoHistory() { - int maximum = (historyFlag1 + 1) % maxHistoryLength; - int current = historyFlag2 + 1; - current %= maxHistoryLength; - if (maximum == current) { - return std::nullopt; - } - auto& res = historyList[current]; - if (res.used == false) { - return std::nullopt; - } - historyFlag2 = current; - return res; +std::optional> PlayerData::getRedoHistory() { + int maximum = (historyFlag1 + 1) % maxHistoryLength; + int current = historyFlag2 + 1; + current %= maxHistoryLength; + if (maximum == current) { + return std::nullopt; + } + auto& res = historyList[current]; + if (res.used == false) { + return std::nullopt; } -} // namespace worldedit \ No newline at end of file + historyFlag2 = current; + return res; +} +} // namespace we \ No newline at end of file diff --git a/old/core/data/PlayerData.h b/old/core/data/PlayerData.h index bf35cb7..65f0bcb 100644 --- a/old/core/data/PlayerData.h +++ b/old/core/data/PlayerData.h @@ -1,61 +1,62 @@ -// -// Created by OEOTYAN on 2023/01/28. -// #pragma once -#include +#include "brush/Brush.h" +#include "region/Region.h" #include "store/Clipboard.hpp" #include "store/History.h" -#include "region/Region.h" -#include "brush/Brush.h" #include -namespace worldedit { - class PlayerData { - public: - std::string xuid = ""; - int maxHistoryLength = 20; - int updateArg = 0; - int updateExArg = 1; +#include +namespace we { +class PlayerData { +public: + std::string xuid = ""; + int maxHistoryLength = 20; + int updateArg = 0; + int updateExArg = 1; - BlockPos mainPos; - int mainPosTime = 0; - int mainPosDim = -1; + BlockPos mainPos; + int mainPosTime = 0; + int mainPosDim = -1; - BlockPos vicePos; - int vicePosTime = 0; - int vicePosDim = -1; + BlockPos vicePos; + int vicePosTime = 0; + int vicePosDim = -1; - std::string gMask = ""; + std::string gMask = ""; - std::unique_ptr region = nullptr; - class Clipboard clipboard; - std::vector historyList; - int historyFlag1 = 0; - int historyFlag2 = 0; - phmap::flat_hash_map> brushMap; + std::unique_ptr region = nullptr; + class Clipboard clipboard; + std::vector historyList; + int historyFlag1 = 0; + int historyFlag2 = 0; + phmap::flat_hash_map> brushMap; - PlayerData(); - PlayerData(class Player*); + PlayerData(); + PlayerData(class Player*); - void clearHistory(); - class Clipboard& getNextHistory(); - class Clipboard& getCurrentHistory(); - std::optional> getUndoHistory(); - std::optional> getRedoHistory(); - bool changeMainPos(BlockInstance blockInstance, bool output = true); - bool changeVicePos(BlockInstance blockInstance, bool output = true); - void setVarByPlayer(phmap::flat_hash_map<::std::string, double>& variables); - bool setBlockSimple(class BlockSource* blockSource, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - const BlockPos& pos, - class Block const* block =BedrockBlocks::mAir, - class Block const* exblock = BedrockBlocks::mAir, - std::optional const& biomeId = std::nullopt); - bool setBlockWithoutcheckGMask(class BlockSource* blockSource, - const BlockPos& pos, - class Block const* block, - class Block const* exblock, - std::optional const& biomeId = std::nullopt); - }; + void clearHistory(); + class Clipboard& getNextHistory(); + class Clipboard& getCurrentHistory(); + std::optional> getUndoHistory(); + std::optional> getRedoHistory(); + bool changeMainPos(BlockInstance blockInstance, bool output = true); + bool changeVicePos(BlockInstance blockInstance, bool output = true); + void setVarByPlayer(phmap::flat_hash_map<::std::string, double>& variables); + bool setBlockSimple( + class BlockSource* blockSource, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + BlockPos const& pos, + class Block const* block = BedrockBlocks::mAir, + class Block const* exblock = BedrockBlocks::mAir, + std::optional const& biomeId = std::nullopt + ); + bool setBlockWithoutcheckGMask( + class BlockSource* blockSource, + BlockPos const& pos, + class Block const* block, + class Block const* exblock, + std::optional const& biomeId = std::nullopt + ); +}; -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/eval/Bresenham.cpp b/old/core/eval/Bresenham.cpp deleted file mode 100644 index eb3931a..0000000 --- a/old/core/eval/Bresenham.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// -// Created by OEOTYAN on 2022/06/13. -// - -#include "Bresenham.hpp" -#include "Eval.h" -namespace worldedit { - - double getCatenaryParameter(double d, double h, double L) { - const double m = sqrt(pow2(L) - pow2(h)) / d; - double x = acosh(m) + 1; - for (int i = 0; i < 10; i++) { - x -= (sinh(x) - m * x) / (cosh(x) - m); - } - return d / (2 * x); - } - - void plotLine(BlockPos const& pos0, BlockPos const& pos1, std::function const& todo) { - int x0 = pos0.x; - int y0 = pos0.y; - int z0 = pos0.z; - int x1 = pos1.x; - int y1 = pos1.y; - int z1 = pos1.z; - int dx = abs(x1 - x0); - int dy = abs(y1 - y0); - int dz = abs(z1 - z0); - int sx = x0 < x1 ? 1 : -1; - int sy = y0 < y1 ? 1 : -1; - int sz = z0 < z1 ? 1 : -1; - - int dMax = std::max(dx, std::max(dy, dz)); - if (dMax == dx) { - for (int domstep = 0; domstep <= dx; domstep++) { - int tipx = x0 + domstep * sx; - int tipy = (int)round(y0 + domstep / ((double)dx) * ((double)dy) * sy); - int tipz = (int)round(z0 + domstep / ((double)dx) * ((double)dz) * sz); - todo(BlockPos(tipx, tipy, tipz)); - } - } else if (dMax == dy) { - for (int domstep = 0; domstep <= dy; domstep++) { - int tipx = (int)round(x0 + domstep / ((double)dy) * ((double)dx) * sx); - int tipy = y0 + domstep * sy; - int tipz = (int)round(z0 + domstep / ((double)dy) * ((double)dz) * sz); - todo(BlockPos(tipx, tipy, tipz)); - } - } else { - for (int domstep = 0; domstep <= dz; domstep++) { - int tipx = (int)round(x0 + domstep / ((double)dz) * ((double)dx) * sx); - int tipy = (int)round(y0 + domstep / ((double)dz) * ((double)dy) * sy); - int tipz = z0 + domstep * sz; - todo(BlockPos(tipx, tipy, tipz)); - } - } - return; - } - - Vec3 KochanekBartelsInterpolation::retrieve(int index) const { - if (index < 0) { - if (circle) { - return nodes[(int)(round(posfmod(index, (double)(nodes.size()))))].getVec3(); - } else { - return nodes[0].getVec3(); - } - } else if (index >= nodes.size()) { - if (circle) { - return nodes[(int)(round(posfmod(index, (double)(nodes.size()))))].getVec3(); - } else { - return nodes[nodes.size() - 1].getVec3(); - } - } - return nodes[index].getVec3(); - } - Vec3 KochanekBartelsInterpolation::linearCombination(int baseIndex, - double f1, - double f2, - double f3, - double f4) const { - return retrieve(baseIndex - 1) * (float)f1 + retrieve(baseIndex) * (float)f2 + - retrieve(baseIndex + 1) * (float)f3 + retrieve(baseIndex + 2) * (float)f4; - } - - void KochanekBartelsInterpolation::recalc() { - int nNodes = (int)nodes.size(); - if (circle) { - nNodes += 1; - } - coeffA.resize(nNodes); - coeffB.resize(nNodes); - coeffC.resize(nNodes); - coeffD.resize(nNodes); - if (nNodes < 1) { - return; - } - Node nodeB = nodes[0]; - double tensionB = nodeB.tension; - double biasB = nodeB.bias; - double continuityB = nodeB.continuity; - for (int i = 0; i < nNodes; ++i) { - const double tensionA = tensionB; - const double biasA = biasB; - const double continuityA = continuityB; - if (i + 1 < nNodes) { - if (circle) { - nodeB = nodes[(int)(round(posfmod(i + 1, (double)(nodes.size()))))]; - } else { - nodeB = nodes[i + 1]; - } - tensionB = nodeB.tension; - biasB = nodeB.bias; - continuityB = nodeB.continuity; - } - - const double ta = (1 - tensionA) * (1 + biasA) * (1 + continuityA) / 2; - const double tb = (1 - tensionA) * (1 - biasA) * (1 - continuityA) / 2; - const double tc = (1 - tensionB) * (1 + biasB) * (1 - continuityB) / 2; - const double td = (1 - tensionB) * (1 - biasB) * (1 + continuityB) / 2; - - coeffA[i] = linearCombination(i, -ta, ta - tb - tc + 2, tb + tc - td - 2, td); - coeffB[i] = linearCombination(i, 2 * ta, -2 * ta + 2 * tb + tc - 3, -2 * tb - tc + td + 3, -td); - coeffC[i] = linearCombination(i, -ta, ta - tb, tb, 0); - coeffD[i] = retrieve(i); - } - scaling = (int)nodes.size(); - if (!circle) { - scaling -= 1; - } - } - void KochanekBartelsInterpolation::setNodes(std::vector const& nodes) { - this->nodes = nodes; - recalc(); - } - - Vec3 KochanekBartelsInterpolation::getPosition(double position) const { - position = std::max(0.0, std::min(position, 1.0)); - position *= scaling; - int index = (int)position; - float f = (float)(position - index); - return ((coeffA[index] * f + coeffB[index]) * f + coeffC[index]) * f + coeffD[index]; - } - - Vec3 KochanekBartelsInterpolation::get1stDerivative(double position) const { - position = std::max(0.0, std::min(position, 1.0)); - position *= scaling; - int index = (int)position; - return ((coeffA[index] * (float)(1.5 * position - 3.0 * index) + coeffB[index]) * (float)(2.0 * position) + - (coeffA[index] * (float)(1.5 * index) - coeffB[index]) * (float)(2.0 * index) + coeffC[index]) * - (float)scaling; - } - - double KochanekBartelsInterpolation::arcLength(double positionA, double positionB) const { - if (positionA > positionB) { - std::swap(positionA, positionB); - } - positionA = std::max(0.0, std::min(positionA, 1.0)); - positionB = std::max(0.0, std::min(positionB, 1.0)); - positionA *= scaling; - positionB *= scaling; - int indexA = (int)positionA; - int indexB = (int)positionB; - double fA = positionA - indexA; - double fB = positionB - indexB; - return arcLengthRecursive(indexA, fA, indexB, fB); - } - - double KochanekBartelsInterpolation::arcLengthRecursive(int indexLeft, - double remainderLeft, - int indexRight, - double remainderRight) const { - switch (indexRight - indexLeft) { - case 0: - return arcLengthRecursive(indexLeft, remainderLeft, remainderRight); - - case 1: - // This case is merely a speed-up for a very common case - return arcLengthRecursive(indexLeft, remainderLeft, 1.0) + - arcLengthRecursive(indexRight, 0.0, remainderRight); - - default: - return arcLengthRecursive(indexLeft, remainderLeft, indexRight - 1, 1.0) + - arcLengthRecursive(indexRight, 0.0, remainderRight); - } - } - - double KochanekBartelsInterpolation::arcLengthRecursive(int index, - double remainderLeft, - double remainderRight) const { - auto a = coeffA[index] * 3; - auto b = coeffB[index] * 2; - auto c = coeffC[index]; - - const int nPoints = 8; - - double accum = ((a * (float)remainderLeft + b) * (float)remainderLeft + c).length() * 0.5; - for (int i = 0; i < nPoints - 1; ++i) { - float t = (float)((double)i / (double)nPoints); - t = (float)((remainderRight - remainderLeft) * t + remainderLeft); - accum += ((a * t + b) * t + c).length(); - } - accum += ((a * (float)remainderRight + b) * (float)remainderRight + c).length() * 0.5; - return accum * (remainderRight - remainderLeft) / (double)nPoints; - } - - int KochanekBartelsInterpolation::getSegment(double position) const { - position = std::max(0.0, std::min(position, 1.0)); - position *= scaling; - int index = (int)position; - return index; - } - -} // namespace worldedit \ No newline at end of file diff --git a/old/core/eval/Bresenham.hpp b/old/core/eval/Bresenham.hpp deleted file mode 100644 index 8d364c4..0000000 --- a/old/core/eval/Bresenham.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by OEOTYAN on 2022/06/14. -// -#pragma once -#include "Globals.h" -namespace worldedit { - double getCatenaryParameter(double d, double h, double L); - - void plotLine(BlockPos const& pos0, BlockPos const& pos1, std::function const& todo); - class Node final : public Vec3 { - public: - double tension = 0; - double bias = 0; - double continuity = 0; - Node(BlockPos const& pos, double tension = 0, double bias = 0, double continuity = 0) - : Vec3(pos.toVec3() + 0.5), tension(tension), bias(bias), continuity(continuity) {} - Node(Vec3 const& pos, double tension = 0, double bias = 0, double continuity = 0) - : Vec3(pos), tension(tension), bias(bias), continuity(continuity) {} - Vec3 getVec3() const { return Vec3(x, y, z); } - }; - class KochanekBartelsInterpolation { - public: - std::vector nodes; - std::vector coeffA; - std::vector coeffB; - std::vector coeffC; - std::vector coeffD; - double scaling; - bool circle = false; - KochanekBartelsInterpolation(bool c = false) : circle(c) { nodes.clear(); } - KochanekBartelsInterpolation(std::vector const& n, bool c = false) : circle(c) { - nodes.clear(); - setNodes(n); - } - Vec3 retrieve(int index) const; - void setNodes(std::vector const& nodes); - Vec3 getPosition(double position) const; - Vec3 get1stDerivative(double position) const; - double arcLength(double positionA = 0, double positionB = 1) const; - int getSegment(double position) const; - - private: - void recalc(); - Vec3 linearCombination(int baseIndex, double f1, double f2, double f3, double f4) const; - double arcLengthRecursive(int indexLeft, double remainderLeft, int indexRight, double remainderRight) const; - double arcLengthRecursive(int index, double remainderLeft, double remainderRight) const; - }; -} // namespace worldedit diff --git a/old/core/eval/Eval.cpp b/old/core/eval/Eval.cpp index 6395bd8..5d6610a 100644 --- a/old/core/eval/Eval.cpp +++ b/old/core/eval/Eval.cpp @@ -1,650 +1,703 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "Eval.h" -#include +#include "FastNoiseLite.h" +#include "I18nAPI.h" +#include "utils/RNG.h" +#include "utils/StringTool.h" #include +#include #include +#include #include -#include -#include "FastNoiseLite.h" -#include "utils/StringTool.h" -#include "utils/RNG.h" -#include "I18nAPI.h" -#define tryGetParameter(size, params, n, f, t) \ - if (size >= n) { \ - f(static_cast(params[n - 1])); \ +#define tryGetParameter(size, params, n, f, t) \ + if (size >= n) { \ + f(static_cast(params[n - 1])); \ } -namespace worldedit { - double posfmod(double x, double y) { - return x - floor(x / y) * y; - } - int getHighestTerrainBlock(BlockSource* blockSource, int x, int z, int minY, int maxY, std::string filter) { - EvalFunctions f; - f.setbs(blockSource); - // auto& chunk = blockSource->getChunkAt(BlockPos(x, maxY, z)); - phmap::flat_hash_map variables; - for (int y = maxY; y >= minY; y--) { - BlockPos pos(x, y, z); - auto* block = &blockSource->getBlock(pos); - if (block != BedrockBlocks::mAir) { - if (filter == "") { +namespace we { +double posfmod(double x, double y) { return x - floor(x / y) * y; } +int getHighestTerrainBlock( + BlockSource* blockSource, + int x, + int z, + int minY, + int maxY, + std::string filter + ) { + EvalFunctions f; + f.setbs(blockSource); + // auto& chunk = blockSource->getChunkAt(BlockPos(x, maxY, z)); + phmap::flat_hash_map variables; + for (int y = maxY; y >= minY; y--) { + BlockPos pos(x, y, z); + auto* block = &blockSource->getBlock(pos); + if (block != BedrockBlocks::mAir) { + if (filter == "") { + return y; + } else { + f.setPos(pos); + variables["rx"] = pos.x; + variables["ry"] = pos.y; + variables["rz"] = pos.z; + if (cpp_eval::eval(filter, variables, f) > 0.5) { return y; - } else { - f.setPos(pos); - variables["rx"] = pos.x; - variables["ry"] = pos.y; - variables["rz"] = pos.z; - if (cpp_eval::eval(filter, variables, f) > 0.5) { - return y; - } } } } - return minY - 1; } + return minY - 1; +} + +void EvalFunctions::setbox(BoundingBox box) { + normalSearchBox = box; + normalSearchBox.min -= normalSearchDis; + normalSearchBox.max += normalSearchDis; + size = normalSearchBox.max - normalSearchBox.min + 1; + posMap.clear(); + solidMap.clear(); + searchBoxInitialized = true; +} - void EvalFunctions::setbox(BoundingBox box) { - normalSearchBox = box; - normalSearchBox.min -= normalSearchDis; - normalSearchBox.max += normalSearchDis; - size = normalSearchBox.max - normalSearchBox.min + 1; - posMap.clear(); - solidMap.clear(); - searchBoxInitialized = true; +void EvalFunctions::buildSearchCache() { + if (!searchBoxInitialized || searchCacheBuilded) { + return; } + try { + posMap.resize(size.x * size.y * size.z + 1); + solidMap = std::vector(size.x * size.y * size.z + 1, 0); + } catch (std::bad_alloc) { + Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); + return; + } + posMap[size.x * size.y * size.z] = {0, 0, 0}; + solidMap[size.x * size.y * size.z] = 0; - void EvalFunctions::buildSearchCache() { - if (!searchBoxInitialized || searchCacheBuilded) { + normalSearchBox.forEachBlockInBox([&](const BlockPos& pos) { + if (&blockSource->getBlock(pos) == BedrockBlocks::mAir) { return; } - try { - posMap.resize(size.x * size.y * size.z + 1); - solidMap = std::vector(size.x * size.y * size.z + 1, 0); - } catch (std::bad_alloc) { - Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); - return; + auto index = getIndex(pos); + int counts = 0; + for (auto& calPos : pos.getNeighbors()) { + counts += &blockSource->getBlock(calPos) != BedrockBlocks::mAir; } - posMap[size.x * size.y * size.z] = {0, 0, 0}; - solidMap[size.x * size.y * size.z] = 0; - - normalSearchBox.forEachBlockInBox([&](const BlockPos& pos) { - if (&blockSource->getBlock(pos) == BedrockBlocks::mAir) { - return; + solidMap[index] = counts == 6; + if (counts == 6) { + posMap[index].x = pos.x; + posMap[index].y = pos.y; + posMap[index].z = pos.z; + } + }); + for (int x = 1; x < size.x; ++x) + for (int y = 0; y < size.y; ++y) + for (int z = 0; z < size.z; ++z) { + long long index = (y + size.y * z) * size.x + x; + long long indexf = (y + size.y * z) * size.x + (x - 1); + solidMap[index] = solidMap[index] + solidMap[indexf]; + posMap[index].x = posMap[index].x + posMap[indexf].x; + posMap[index].y = posMap[index].y + posMap[indexf].y; + posMap[index].z = posMap[index].z + posMap[indexf].z; } - auto index = getIndex(pos); - int counts = 0; - for (auto& calPos : pos.getNeighbors()) { - counts += &blockSource->getBlock(calPos) != BedrockBlocks::mAir; + for (int y = 1; y < size.y; ++y) + for (int x = 0; x < size.x; ++x) + for (int z = 0; z < size.z; ++z) { + long long index = (y + size.y * z) * size.x + x; + long long indexf = ((y - 1) + size.y * z) * size.x + x; + solidMap[index] = solidMap[index] + solidMap[indexf]; + posMap[index].x = posMap[index].x + posMap[indexf].x; + posMap[index].y = posMap[index].y + posMap[indexf].y; + posMap[index].z = posMap[index].z + posMap[indexf].z; } - solidMap[index] = counts == 6; - if (counts == 6) { - posMap[index].x = pos.x; - posMap[index].y = pos.y; - posMap[index].z = pos.z; + for (int z = 1; z < size.z; ++z) + for (int x = 0; x < size.x; ++x) + for (int y = 0; y < size.y; ++y) { + long long index = (y + size.y * z) * size.x + x; + long long indexf = (y + size.y * (z - 1)) * size.x + x; + solidMap[index] = solidMap[index] + solidMap[indexf]; + posMap[index].x = posMap[index].x + posMap[indexf].x; + posMap[index].y = posMap[index].y + posMap[indexf].y; + posMap[index].z = posMap[index].z + posMap[indexf].z; } - }); - for (int x = 1; x < size.x; ++x) - for (int y = 0; y < size.y; ++y) - for (int z = 0; z < size.z; ++z) { - long long index = (y + size.y * z) * size.x + x; - long long indexf = (y + size.y * z) * size.x + (x - 1); - solidMap[index] = solidMap[index] + solidMap[indexf]; - posMap[index].x = posMap[index].x + posMap[indexf].x; - posMap[index].y = posMap[index].y + posMap[indexf].y; - posMap[index].z = posMap[index].z + posMap[indexf].z; - } - for (int y = 1; y < size.y; ++y) - for (int x = 0; x < size.x; ++x) - for (int z = 0; z < size.z; ++z) { - long long index = (y + size.y * z) * size.x + x; - long long indexf = ((y - 1) + size.y * z) * size.x + x; - solidMap[index] = solidMap[index] + solidMap[indexf]; - posMap[index].x = posMap[index].x + posMap[indexf].x; - posMap[index].y = posMap[index].y + posMap[indexf].y; - posMap[index].z = posMap[index].z + posMap[indexf].z; - } - for (int z = 1; z < size.z; ++z) - for (int x = 0; x < size.x; ++x) - for (int y = 0; y < size.y; ++y) { - long long index = (y + size.y * z) * size.x + x; - long long indexf = (y + size.y * (z - 1)) * size.x + x; - solidMap[index] = solidMap[index] + solidMap[indexf]; - posMap[index].x = posMap[index].x + posMap[indexf].x; - posMap[index].y = posMap[index].y + posMap[indexf].y; - posMap[index].z = posMap[index].z + posMap[indexf].z; - } - searchCacheBuilded = true; + searchCacheBuilded = true; +} +long long EvalFunctions::getIndex(const BlockPos& pos) { + auto localPos = pos - normalSearchBox.min; + if (pos.x < normalSearchBox.min.x || pos.y < normalSearchBox.min.y + || pos.z < normalSearchBox.min.z || pos.x > normalSearchBox.max.x + || pos.y > normalSearchBox.max.y || pos.z > normalSearchBox.max.z) + return size.y * size.z * size.x; + return (localPos.y + size.y * localPos.z) * size.x + localPos.x; +} +long long EvalFunctions::getSolidMap(const BlockPos& pos1, const BlockPos& pos2) { + long long res = 0; + res = solidMap[getIndex(pos2)]; + res -= solidMap[getIndex({pos1.x - 1, pos2.y, pos2.z})]; + res -= solidMap[getIndex({pos2.x, pos1.y - 1, pos2.z})]; + res -= solidMap[getIndex({pos2.x, pos2.y, pos1.z - 1})]; + res += solidMap[getIndex({pos2.x, pos1.y - 1, pos1.z - 1})]; + res += solidMap[getIndex({pos1.x - 1, pos2.y, pos1.z - 1})]; + res += solidMap[getIndex({pos1.x - 1, pos1.y - 1, pos2.z})]; + res -= solidMap[getIndex(pos1 - 1)]; + return res; +} +LongLong3 EvalFunctions::getPosMap(const BlockPos& pos1, const BlockPos& pos2) { + LongLong3 res; + res = posMap[getIndex(pos2)]; + res -= posMap[getIndex({pos1.x - 1, pos2.y, pos2.z})]; + res -= posMap[getIndex({pos2.x, pos1.y - 1, pos2.z})]; + res -= posMap[getIndex({pos2.x, pos2.y, pos1.z - 1})]; + res += posMap[getIndex({pos2.x, pos1.y - 1, pos1.z - 1})]; + res += posMap[getIndex({pos1.x - 1, pos2.y, pos1.z - 1})]; + res += posMap[getIndex({pos1.x - 1, pos1.y - 1, pos2.z})]; + res -= posMap[getIndex(pos1 - 1)]; + return res; +} +double +EvalFunctions::operator()(std::string_view name, const std::vector& params) { + auto size = params.size(); + BlockPos tmp = here; + if (size == 3) { + tmp += BlockPos( + static_cast(floor(params[0])), + static_cast(floor(params[1])), + static_cast(floor(params[2])) + ); } - long long EvalFunctions::getIndex(const BlockPos& pos) { - auto localPos = pos - normalSearchBox.min; - if (pos.x < normalSearchBox.min.x || pos.y < normalSearchBox.min.y || pos.z < normalSearchBox.min.z || - pos.x > normalSearchBox.max.x || pos.y > normalSearchBox.max.y || pos.z > normalSearchBox.max.z) - return size.y * size.z * size.x; - return (localPos.y + size.y * localPos.z) * size.x + localPos.x; - } - long long EvalFunctions::getSolidMap(const BlockPos& pos1, const BlockPos& pos2) { - long long res = 0; - res = solidMap[getIndex(pos2)]; - res -= solidMap[getIndex({pos1.x - 1, pos2.y, pos2.z})]; - res -= solidMap[getIndex({pos2.x, pos1.y - 1, pos2.z})]; - res -= solidMap[getIndex({pos2.x, pos2.y, pos1.z - 1})]; - res += solidMap[getIndex({pos2.x, pos1.y - 1, pos1.z - 1})]; - res += solidMap[getIndex({pos1.x - 1, pos2.y, pos1.z - 1})]; - res += solidMap[getIndex({pos1.x - 1, pos1.y - 1, pos2.z})]; - res -= solidMap[getIndex(pos1 - 1)]; - return res; - } - LongLong3 EvalFunctions::getPosMap(const BlockPos& pos1, const BlockPos& pos2) { - LongLong3 res; - res = posMap[getIndex(pos2)]; - res -= posMap[getIndex({pos1.x - 1, pos2.y, pos2.z})]; - res -= posMap[getIndex({pos2.x, pos1.y - 1, pos2.z})]; - res -= posMap[getIndex({pos2.x, pos2.y, pos1.z - 1})]; - res += posMap[getIndex({pos2.x, pos1.y - 1, pos1.z - 1})]; - res += posMap[getIndex({pos1.x - 1, pos2.y, pos1.z - 1})]; - res += posMap[getIndex({pos1.x - 1, pos1.y - 1, pos2.z})]; - res -= posMap[getIndex(pos1 - 1)]; - return res; - } - double EvalFunctions::operator()(std::string_view name, const std::vector& params) { - auto size = params.size(); - BlockPos tmp = here; - if (size == 3) { - tmp += BlockPos(static_cast(floor(params[0])), static_cast(floor(params[1])), - static_cast(floor(params[2]))); - } - switch (do_hash2(name)) { - case do_hash2("rand"): - if (size == 0) { - return RNG::rand(); - } else if (size == 2) { - return RNG::rand(params[0], params[1]); - } - break; - case do_hash2("saturate"): - if (size == 3) - return std::min(1.0, std::max(0.0, params[0])); - break; - case do_hash2("clamp"): - if (size == 3) - return std::min(params[2], std::max(params[1], params[0])); - break; - case do_hash2("lerp"): - if (size == 3) - return params[0] * (1 - params[2]) + params[1] * params[2]; - break; - case do_hash2("mod"): - if (size == 2) - return posfmod(params[0], params[1]); - break; - case do_hash2("abs"): - if (size == 1) - return abs(params[0]); - break; - case do_hash2("sin"): - if (size == 1) - return sin(params[0]); - break; - case do_hash2("cos"): - if (size == 1) - return cos(params[0]); - break; - case do_hash2("sign"): - if (size == 1) - return params[0] == 0.0 ? 0.0 : (params[0] > 0.0 ? 1.0 : -1.0); - break; - case do_hash2("log10"): - case do_hash2("lg"): - if (size == 1) - return log10(params[0]); - break; - case do_hash2("ln"): - if (size == 1) - return log(params[0]); - break; - case do_hash2("log2"): - if (size == 1) - return log2(params[0]); - break; - case do_hash2("round"): - if (size == 1) - return round(params[0]); - break; - case do_hash2("floor"): - if (size == 1) - return floor(params[0]); - break; - case do_hash2("ceil"): - if (size == 1) - return ceil(params[0]); - break; - case do_hash2("exp"): - if (size == 1) - return exp(params[0]); - break; - case do_hash2("exp2"): - if (size == 1) - return exp2(params[0]); - break; - case do_hash2("sqrt"): - if (size == 1) - return sqrt(params[0]); - break; - case do_hash2("tan"): - if (size == 1) - return tan(params[0]); - break; - case do_hash2("atan"): - if (size == 1) - return atan(params[0]); - break; - case do_hash2("atan2"): - if (size == 2) - return atan2(params[0], params[1]); - break; - case do_hash2("asin"): - if (size == 1) - return asin(params[0]); - break; - case do_hash2("acos"): - if (size == 1) - return acos(params[0]); - break; - case do_hash2("sinh"): - if (size == 1) - return sinh(params[0]); - break; - case do_hash2("cosh"): - if (size == 1) - return cosh(params[0]); - break; - case do_hash2("tanh"): - if (size == 1) - return tanh(params[0]); - break; - case do_hash2("gamma"): - if (size == 1) - return tgamma(params[0]); - break; - case do_hash2("isslimechunk"): - if (size == 0) { - int x = here.x >> 4; - int z = here.z >> 4; - auto seed = (x * 0x1f1f1f1fu) ^ (uint32_t)z; - std::mt19937 mt(seed); - return mt() % 10 == 0; - } else if (size == 2) { - int x = static_cast(round(params[0])); - int z = static_cast(round(params[1])); - auto seed = (x * 0x1f1f1f1fu) ^ (uint32_t)z; - std::mt19937 mt(seed); - return mt() % 10 == 0; - } - break; - case do_hash2("sum"): - return std::accumulate(params.begin(), params.end(), 0.0); - break; - case do_hash2("min"): - return *min_element(params.begin(), params.end()); - break; - case do_hash2("max"): - return *max_element(params.begin(), params.end()); - break; - case do_hash2("id"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getId(); - } - return 0; - break; - case do_hash2("runtimeid"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getRuntimeId(); - } - return 0; - break; - case do_hash2("hsa"): - if (blockdataInitialized) { - for (auto& hsa : blockSource->getChunkAt(tmp)->getSpawningAreas()) { - if (((hsa.aabb.max.x - hsa.aabb.min.x + 1) / 2 + hsa.aabb.min.x == tmp.x) && - ((hsa.aabb.max.z - hsa.aabb.min.z + 1) / 2 + hsa.aabb.min.z == tmp.z) && - tmp.y >= hsa.aabb.min.y) { - if (hsa.type == LevelChunk::HardcodedSpawnAreaType::SWAMP_HUT || - hsa.type == LevelChunk::HardcodedSpawnAreaType::PILLAGER_OUTPOST) { - if (tmp.y <= hsa.aabb.max.y - 3) { - return static_cast(hsa.type); - } - } else { - if (tmp.y <= hsa.aabb.max.y) { - return static_cast(hsa.type); - } - } + switch (do_hash2(name)) { + case do_hash2("rand"): + if (size == 0) { + return RNG::rand(); + } else if (size == 2) { + return RNG::rand(params[0], params[1]); + } + break; + case do_hash2("saturate"): + if (size == 3) return std::min(1.0, std::max(0.0, params[0])); + break; + case do_hash2("clamp"): + if (size == 3) return std::min(params[2], std::max(params[1], params[0])); + break; + case do_hash2("lerp"): + if (size == 3) return params[0] * (1 - params[2]) + params[1] * params[2]; + break; + case do_hash2("mod"): + if (size == 2) return posfmod(params[0], params[1]); + break; + case do_hash2("abs"): + if (size == 1) return abs(params[0]); + break; + case do_hash2("sin"): + if (size == 1) return sin(params[0]); + break; + case do_hash2("cos"): + if (size == 1) return cos(params[0]); + break; + case do_hash2("sign"): + if (size == 1) return params[0] == 0.0 ? 0.0 : (params[0] > 0.0 ? 1.0 : -1.0); + break; + case do_hash2("log10"): + case do_hash2("lg"): + if (size == 1) return log10(params[0]); + break; + case do_hash2("ln"): + if (size == 1) return log(params[0]); + break; + case do_hash2("log2"): + if (size == 1) return log2(params[0]); + break; + case do_hash2("round"): + if (size == 1) return round(params[0]); + break; + case do_hash2("floor"): + if (size == 1) return floor(params[0]); + break; + case do_hash2("ceil"): + if (size == 1) return ceil(params[0]); + break; + case do_hash2("exp"): + if (size == 1) return exp(params[0]); + break; + case do_hash2("exp2"): + if (size == 1) return exp2(params[0]); + break; + case do_hash2("sqrt"): + if (size == 1) return sqrt(params[0]); + break; + case do_hash2("tan"): + if (size == 1) return tan(params[0]); + break; + case do_hash2("atan"): + if (size == 1) return atan(params[0]); + break; + case do_hash2("atan2"): + if (size == 2) return atan2(params[0], params[1]); + break; + case do_hash2("asin"): + if (size == 1) return asin(params[0]); + break; + case do_hash2("acos"): + if (size == 1) return acos(params[0]); + break; + case do_hash2("sinh"): + if (size == 1) return sinh(params[0]); + break; + case do_hash2("cosh"): + if (size == 1) return cosh(params[0]); + break; + case do_hash2("tanh"): + if (size == 1) return tanh(params[0]); + break; + case do_hash2("gamma"): + if (size == 1) return tgamma(params[0]); + break; + case do_hash2("isslimechunk"): + if (size == 0) { + int x = here.x >> 4; + int z = here.z >> 4; + auto seed = (x * 0x1f1f1f1fu) ^ (uint32_t)z; + std::mt19937 mt(seed); + return mt() % 10 == 0; + } else if (size == 2) { + int x = static_cast(round(params[0])); + int z = static_cast(round(params[1])); + auto seed = (x * 0x1f1f1f1fu) ^ (uint32_t)z; + std::mt19937 mt(seed); + return mt() % 10 == 0; + } + break; + case do_hash2("sum"): + return std::accumulate(params.begin(), params.end(), 0.0); + break; + case do_hash2("min"): + return *min_element(params.begin(), params.end()); + break; + case do_hash2("max"): + return *max_element(params.begin(), params.end()); + break; + case do_hash2("id"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getId(); + } + return 0; + break; + case do_hash2("runtimeid"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getRuntimeId(); + } + return 0; + break; + case do_hash2("hsa"): + if (blockdataInitialized) { + for (auto& hsa : blockSource->getChunkAt(tmp)->getSpawningAreas()) { + if (((hsa.aabb.max.x - hsa.aabb.min.x + 1) / 2 + hsa.aabb.min.x == tmp.x) + && ((hsa.aabb.max.z - hsa.aabb.min.z + 1) / 2 + hsa.aabb.min.z + == tmp.z) + && tmp.y >= hsa.aabb.min.y) { + if (hsa.type == LevelChunk::HardcodedSpawnAreaType::SWAMP_HUT + || hsa.type + == LevelChunk::HardcodedSpawnAreaType::PILLAGER_OUTPOST) { + if (tmp.y <= hsa.aabb.max.y - 3) { + return static_cast(hsa.type); } - } - return 0; - } - return 0; - break; - case do_hash2("biome"): - if (blockdataInitialized) { - return blockSource->getConstBiome(tmp).getId(); - } - return 0; - break; - case do_hash2("hasplayer"): - if (blockdataInitialized) { - auto& dimension = blockSource->getDimensionConst(); - if (size == 1) { - return nullptr != - dimension.fetchAnyInteractablePlayer(here.toVec3(), static_cast(params[0])); - } else if (size == 4) { - return nullptr != dimension.fetchAnyInteractablePlayer( - here.toVec3() + Vec3(params[1], params[2], params[3]), - static_cast(params[0])); - } - } - return 0; - break; - case do_hash2("noplayer"): - if (blockdataInitialized) { - auto& dimension = blockSource->getDimensionConst(); - Vec3 tmpVec; - if (size == 1) { - tmpVec = here.toVec3(); - } else if (size == 4) { - tmpVec = here.toVec3() + Vec3(params[1], params[2], params[3]); - } - float playerDistance = FLT_MAX; - dimension.forEachPlayer([&](Player& player) { - float dis = (float)player.getPosition().distanceToSqr(tmpVec); - playerDistance = std::min(dis, playerDistance); - return true; - }); - return playerDistance == FLT_MAX || playerDistance >= pow2(static_cast(params[0])); - } - return 0; - break; - case do_hash2("hasuntickedchunk"): - if (blockdataInitialized) { - if (size == 1) { - return blockSource->hasUntickedNeighborChunk(ChunkPos(here), static_cast(params[0])); - } else if (size == 4) { - return blockSource->hasUntickedNeighborChunk( - ChunkPos(here + BlockPos(static_cast(floor(params[1])), - static_cast(floor(params[2])), - static_cast(floor(params[3])))), - static_cast(params[0])); - } - } - return 0; - case do_hash2("chunksfullyloaded"): - if (blockdataInitialized) { - if (size == 1) { - return blockSource->areChunksFullyLoaded(here, static_cast(params[0])); - } else if (size == 4) { - return blockSource->areChunksFullyLoaded( - (here + BlockPos(static_cast(floor(params[1])), static_cast(floor(params[2])), - static_cast(floor(params[3])))), - static_cast(params[0])); - } - } - return 0; - break; - case do_hash2("data"): - if (blockdataInitialized) { - return (const_cast(blockSource->getBlock(tmp))).getTileData(); - } - return 0; - break; - case do_hash2("issolid"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).isSolid(); - } - return 0; - break; - case do_hash2("iswaterblocking"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).isWaterBlocking(); - } - return 0; - break; - case do_hash2("issbblock"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).isSolidBlockingBlock(); - } - return 0; - break; - case do_hash2("istop"): - if (blockdataInitialized) { - return blockSource->getHeightmapPos(tmp) == tmp; - } - return 0; - break; - case do_hash2("destroyspeed"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getDestroySpeed(); - } - return 0; - break; - case do_hash2("thickness"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getThickness(); - } - return 0; - break; - case do_hash2("translucency"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getTranslucency(); - } - return 0; - break; - case do_hash2("light"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getLight().value; - } - return 0; - break; - case do_hash2("emissive"): - if (blockdataInitialized) { - return blockSource->getBlock(tmp).getLightEmission().value; - } - return 0; - break; - case do_hash2("normalx"): - if (searchBoxInitialized) { - if (size == 0) { - buildSearchCache(); - auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); - auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); - double sumx = 0; - double sumy = 0; - double sumz = 0; - sumx = static_cast(solid * here.x - posSum.x); - sumy = static_cast(solid * here.y - posSum.y); - sumz = static_cast(solid * here.z - posSum.z); - double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); - return sumx / length; - } - } - return 0; - break; - case do_hash2("normaly"): - if (searchBoxInitialized) { - if (size == 0) { - buildSearchCache(); - auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); - auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); - double sumx = 0; - double sumy = 0; - double sumz = 0; - sumx = static_cast(solid * here.x - posSum.x); - sumy = static_cast(solid * here.y - posSum.y); - sumz = static_cast(solid * here.z - posSum.z); - double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); - return sumy / length; - } - } - return 0; - break; - case do_hash2("normalz"): - if (searchBoxInitialized) { - if (size == 0) { - buildSearchCache(); - auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); - auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); - double sumx = 0; - double sumy = 0; - double sumz = 0; - sumx = static_cast(solid * here.x - posSum.x); - sumy = static_cast(solid * here.y - posSum.y); - sumz = static_cast(solid * here.z - posSum.z); - double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); - return sumz / length; - } - } - return 0; - break; - case do_hash2("angle"): - if (searchBoxInitialized) { - if (size == 0) { - buildSearchCache(); - auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); - auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); - double sumx = 0; - double sumy = 0; - double sumz = 0; - sumx = static_cast(solid * here.x - posSum.x); - sumy = static_cast(solid * here.y - posSum.y); - sumz = static_cast(solid * here.z - posSum.z); - double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); - return acos(sumy / length) / M_PI * 180.0; - } - } - return 0; - break; - case do_hash2("issurface"): - if (blockdataInitialized) { - if (&blockSource->getBlock(tmp) != BedrockBlocks::mAir) { - int counts = 0; - for (auto& calPos : tmp.getNeighbors()) { - counts += &blockSource->getBlock(calPos) == BedrockBlocks::mAir; + } else { + if (tmp.y <= hsa.aabb.max.y) { + return static_cast(hsa.type); } - return counts > 0; } } - return 0; - break; - case do_hash2("issurfacesmooth"): - if (searchBoxInitialized) { - buildSearchCache(); - return 1.0 - static_cast(getSolidMap(tmp - normalSearchDis, tmp + normalSearchDis)) / - static_cast((normalSearchDis * 2 + 1) * normalSearchDis * 2 + 1); - } - return 0; - break; + } + return 0; + } + return 0; + break; + case do_hash2("biome"): + if (blockdataInitialized) { + return blockSource->getConstBiome(tmp).getId(); + } + return 0; + break; + case do_hash2("hasplayer"): + if (blockdataInitialized) { + auto& dimension = blockSource->getDimensionConst(); + if (size == 1) { + return nullptr + != dimension.fetchAnyInteractablePlayer( + here.toVec3(), + static_cast(params[0]) + ); + } else if (size == 4) { + return nullptr + != dimension.fetchAnyInteractablePlayer( + here.toVec3() + Vec3(params[1], params[2], params[3]), + static_cast(params[0]) + ); + } + } + return 0; + break; + case do_hash2("noplayer"): + if (blockdataInitialized) { + auto& dimension = blockSource->getDimensionConst(); + Vec3 tmpVec; + if (size == 1) { + tmpVec = here.toVec3(); + } else if (size == 4) { + tmpVec = here.toVec3() + Vec3(params[1], params[2], params[3]); + } + float playerDistance = FLT_MAX; + dimension.forEachPlayer([&](Player& player) { + float dis = (float)player.getPosition().distanceToSqr(tmpVec); + playerDistance = std::min(dis, playerDistance); + return true; + }); + return playerDistance == FLT_MAX + || playerDistance >= pow2(static_cast(params[0])); + } + return 0; + break; + case do_hash2("hasuntickedchunk"): + if (blockdataInitialized) { + if (size == 1) { + return blockSource->hasUntickedNeighborChunk( + ChunkPos(here), + static_cast(params[0]) + ); + } else if (size == 4) { + return blockSource->hasUntickedNeighborChunk( + ChunkPos( + here + + BlockPos( + static_cast(floor(params[1])), + static_cast(floor(params[2])), + static_cast(floor(params[3])) + ) + ), + static_cast(params[0]) + ); + } + } + return 0; + case do_hash2("chunksfullyloaded"): + if (blockdataInitialized) { + if (size == 1) { + return blockSource->areChunksFullyLoaded( + here, + static_cast(params[0]) + ); + } else if (size == 4) { + return blockSource->areChunksFullyLoaded( + (here + + BlockPos( + static_cast(floor(params[1])), + static_cast(floor(params[2])), + static_cast(floor(params[3])) + )), + static_cast(params[0]) + ); + } + } + return 0; + break; + case do_hash2("data"): + if (blockdataInitialized) { + return (const_cast(blockSource->getBlock(tmp))).getTileData(); + } + return 0; + break; + case do_hash2("issolid"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).isSolid(); + } + return 0; + break; + case do_hash2("iswaterblocking"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).isWaterBlocking(); + } + return 0; + break; + case do_hash2("issbblock"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).isSolidBlockingBlock(); + } + return 0; + break; + case do_hash2("istop"): + if (blockdataInitialized) { + return blockSource->getHeightmapPos(tmp) == tmp; + } + return 0; + break; + case do_hash2("destroyspeed"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getDestroySpeed(); + } + return 0; + break; + case do_hash2("thickness"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getThickness(); + } + return 0; + break; + case do_hash2("translucency"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getTranslucency(); + } + return 0; + break; + case do_hash2("light"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getLight().value; + } + return 0; + break; + case do_hash2("emissive"): + if (blockdataInitialized) { + return blockSource->getBlock(tmp).getLightEmission().value; + } + return 0; + break; + case do_hash2("normalx"): + if (searchBoxInitialized) { + if (size == 0) { + buildSearchCache(); + auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); + auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); + double sumx = 0; + double sumy = 0; + double sumz = 0; + sumx = static_cast(solid * here.x - posSum.x); + sumy = static_cast(solid * here.y - posSum.y); + sumz = static_cast(solid * here.z - posSum.z); + double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); + return sumx / length; + } + } + return 0; + break; + case do_hash2("normaly"): + if (searchBoxInitialized) { + if (size == 0) { + buildSearchCache(); + auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); + auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); + double sumx = 0; + double sumy = 0; + double sumz = 0; + sumx = static_cast(solid * here.x - posSum.x); + sumy = static_cast(solid * here.y - posSum.y); + sumz = static_cast(solid * here.z - posSum.z); + double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); + return sumy / length; + } + } + return 0; + break; + case do_hash2("normalz"): + if (searchBoxInitialized) { + if (size == 0) { + buildSearchCache(); + auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); + auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); + double sumx = 0; + double sumy = 0; + double sumz = 0; + sumx = static_cast(solid * here.x - posSum.x); + sumy = static_cast(solid * here.y - posSum.y); + sumz = static_cast(solid * here.z - posSum.z); + double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); + return sumz / length; + } + } + return 0; + break; + case do_hash2("angle"): + if (searchBoxInitialized) { + if (size == 0) { + buildSearchCache(); + auto solid = getSolidMap(here - normalSearchDis, here + normalSearchDis); + auto posSum = getPosMap(here - normalSearchDis, here + normalSearchDis); + double sumx = 0; + double sumy = 0; + double sumz = 0; + sumx = static_cast(solid * here.x - posSum.x); + sumy = static_cast(solid * here.y - posSum.y); + sumz = static_cast(solid * here.z - posSum.z); + double length = sqrt(sumx * sumx + sumy * sumy + sumz * sumz); + return acos(sumy / length) / M_PI * 180.0; + } + } + return 0; + break; + case do_hash2("issurface"): + if (blockdataInitialized) { + if (&blockSource->getBlock(tmp) != BedrockBlocks::mAir) { + int counts = 0; + for (auto& calPos : tmp.getNeighbors()) { + counts += &blockSource->getBlock(calPos) == BedrockBlocks::mAir; + } + return counts > 0; + } + } + return 0; + break; + case do_hash2("issurfacesmooth"): + if (searchBoxInitialized) { + buildSearchCache(); + return 1.0 + - static_cast( + getSolidMap(tmp - normalSearchDis, tmp + normalSearchDis) + ) + / static_cast( + (normalSearchDis * 2 + 1) * normalSearchDis * 2 + 1 + ); + } + return 0; + break; - case do_hash2("simplex"): - if (size >= 3) { - FastNoiseLite noise = FastNoiseLite(); - noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Simplex); - tryGetParameter(size, params, 4, noise.SetSeed, int64_t); - tryGetParameter(size, params, 5, noise.SetFractalType, FastNoiseLite::FractalType); - tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); - tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); - tryGetParameter(size, params, 8, noise.SetFractalGain, double); - tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); - tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); - return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; - } - return 0; - break; + case do_hash2("simplex"): + if (size >= 3) { + FastNoiseLite noise = FastNoiseLite(); + noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Simplex); + tryGetParameter(size, params, 4, noise.SetSeed, int64_t); + tryGetParameter( + size, + params, + 5, + noise.SetFractalType, + FastNoiseLite::FractalType + ); + tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); + tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); + tryGetParameter(size, params, 8, noise.SetFractalGain, double); + tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); + tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); + return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; + } + return 0; + break; - case do_hash2("perlin"): - if (size >= 3) { - FastNoiseLite noise = FastNoiseLite(); - noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin); - tryGetParameter(size, params, 4, noise.SetSeed, int64_t); - tryGetParameter(size, params, 5, noise.SetFractalType, FastNoiseLite::FractalType); - tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); - tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); - tryGetParameter(size, params, 8, noise.SetFractalGain, double); - tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); - tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); - return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; - } - return 0; - break; + case do_hash2("perlin"): + if (size >= 3) { + FastNoiseLite noise = FastNoiseLite(); + noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin); + tryGetParameter(size, params, 4, noise.SetSeed, int64_t); + tryGetParameter( + size, + params, + 5, + noise.SetFractalType, + FastNoiseLite::FractalType + ); + tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); + tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); + tryGetParameter(size, params, 8, noise.SetFractalGain, double); + tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); + tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); + return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; + } + return 0; + break; - case do_hash2("cubic"): - if (size >= 3) { - FastNoiseLite noise = FastNoiseLite(); - noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic); - tryGetParameter(size, params, 4, noise.SetSeed, int64_t); - tryGetParameter(size, params, 5, noise.SetFractalType, FastNoiseLite::FractalType); - tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); - tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); - tryGetParameter(size, params, 8, noise.SetFractalGain, double); - tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); - tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); - return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; - } - return 0; - break; + case do_hash2("cubic"): + if (size >= 3) { + FastNoiseLite noise = FastNoiseLite(); + noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic); + tryGetParameter(size, params, 4, noise.SetSeed, int64_t); + tryGetParameter( + size, + params, + 5, + noise.SetFractalType, + FastNoiseLite::FractalType + ); + tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); + tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); + tryGetParameter(size, params, 8, noise.SetFractalGain, double); + tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); + tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); + return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; + } + return 0; + break; - case do_hash2("value"): - if (size >= 3) { - FastNoiseLite noise = FastNoiseLite(); - noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Value); - tryGetParameter(size, params, 4, noise.SetSeed, int64_t); - tryGetParameter(size, params, 5, noise.SetFractalType, FastNoiseLite::FractalType); - tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); - tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); - tryGetParameter(size, params, 8, noise.SetFractalGain, double); - tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); - tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); - return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; - } - return 0; - break; + case do_hash2("value"): + if (size >= 3) { + FastNoiseLite noise = FastNoiseLite(); + noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Value); + tryGetParameter(size, params, 4, noise.SetSeed, int64_t); + tryGetParameter( + size, + params, + 5, + noise.SetFractalType, + FastNoiseLite::FractalType + ); + tryGetParameter(size, params, 6, noise.SetFractalOctaves, int64_t); + tryGetParameter(size, params, 7, noise.SetFractalLacunarity, double); + tryGetParameter(size, params, 8, noise.SetFractalGain, double); + tryGetParameter(size, params, 9, noise.SetFractalWeightedStrength, double); + tryGetParameter(size, params, 10, noise.SetFractalPingPongStrength, double); + return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; + } + return 0; + break; - case do_hash2("voronoi"): - if (size >= 3) { - FastNoiseLite noise = FastNoiseLite(); - noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular); - tryGetParameter(size, params, 4, noise.SetSeed, int64_t); - tryGetParameter(size, params, 5, noise.SetCellularReturnType, FastNoiseLite::CellularReturnType); - tryGetParameter(size, params, 6, noise.SetCellularDistanceFunction, - FastNoiseLite::CellularDistanceFunction); - tryGetParameter(size, params, 7, noise.SetCellularJitter, double); - tryGetParameter(size, params, 8, noise.SetFractalType, FastNoiseLite::FractalType); - tryGetParameter(size, params, 9, noise.SetFractalOctaves, int64_t); - tryGetParameter(size, params, 10, noise.SetFractalLacunarity, double); - tryGetParameter(size, params, 11, noise.SetFractalGain, double); - tryGetParameter(size, params, 12, noise.SetFractalWeightedStrength, double); - tryGetParameter(size, params, 13, noise.SetFractalPingPongStrength, double); - return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; - } - break; + case do_hash2("voronoi"): + if (size >= 3) { + FastNoiseLite noise = FastNoiseLite(); + noise.SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular); + tryGetParameter(size, params, 4, noise.SetSeed, int64_t); + tryGetParameter( + size, + params, + 5, + noise.SetCellularReturnType, + FastNoiseLite::CellularReturnType + ); + tryGetParameter( + size, + params, + 6, + noise.SetCellularDistanceFunction, + FastNoiseLite::CellularDistanceFunction + ); + tryGetParameter(size, params, 7, noise.SetCellularJitter, double); + tryGetParameter( + size, + params, + 8, + noise.SetFractalType, + FastNoiseLite::FractalType + ); + tryGetParameter(size, params, 9, noise.SetFractalOctaves, int64_t); + tryGetParameter(size, params, 10, noise.SetFractalLacunarity, double); + tryGetParameter(size, params, 11, noise.SetFractalGain, double); + tryGetParameter(size, params, 12, noise.SetFractalWeightedStrength, double); + tryGetParameter(size, params, 13, noise.SetFractalPingPongStrength, double); + return (noise.GetNoise(params[0], params[1], params[2]) + 1.0) * 0.5; + } + break; - default: - if (blockdataInitialized) { - std::string sname(name); - if (frontIs(sname, "is_")) { - if (sname.find(":") == std::string::npos) { - sname = "minecraft:" + sname.substr(3); - } else { - sname = sname.substr(3); - } - return sname == blockSource->getBlock(tmp).getTypeName(); - } else if (frontIs(sname, "has_")) { - sname = sname.substr(4); - return blockSource->getBlock(tmp).getTypeName().find(sname) != std::string::npos; - } - return 0; + default: + if (blockdataInitialized) { + std::string sname(name); + if (frontIs(sname, "is_")) { + if (sname.find(":") == std::string::npos) { + sname = "minecraft:" + sname.substr(3); + } else { + sname = sname.substr(3); } + return sname == blockSource->getBlock(tmp).getTypeName(); + } else if (frontIs(sname, "has_")) { + sname = sname.substr(4); + return blockSource->getBlock(tmp).getTypeName().find(sname) + != std::string::npos; + } + return 0; } - return 0; } + return 0; +} -} // namespace worldedit +} // namespace we diff --git a/old/core/eval/Eval.h b/old/core/eval/Eval.h index 269be72..1521fa7 100644 --- a/old/core/eval/Eval.h +++ b/old/core/eval/Eval.h @@ -1,136 +1,137 @@ #pragma once -// -// Created by OEOTYAN on 2022/5/15. -// #include "Globals.h" #include // #include -#include +#include "CppEval.h" +#include "FastNoiseLite.h" #include +#include #include #include -#include "CppEval.h" -#include "FastNoiseLite.h" -namespace worldedit { - - template - constexpr T binpow(T const& a, uint64_t const& b) { - if (b == 0) - return static_cast(1); - T res = binpow(a, b / 2); - if (b % 2) - return res * res * a; - else - return res * res; +namespace we { + +template +constexpr T binpow(T const& a, uint64_t const& b) { + if (b == 0) return static_cast(1); + T res = binpow(a, b / 2); + if (b % 2) return res * res * a; + else return res * res; +} + +template +constexpr T pow2(T const& a) { + return binpow(a, 2); +} + +template +constexpr T pow3(T const& a) { + return binpow(a, 3); +} + +template +constexpr T pow4(T const& a) { + return binpow(a, 4); +} + +template +constexpr T pow5(T const& a) { + return binpow(a, 5); +} + +template +constexpr T pow6(T const& a) { + return binpow(a, 6); +} + +template +constexpr T pow7(T const& a) { + return binpow(a, 7); +} + +template +constexpr T pow8(T const& a) { + return binpow(a, 8); +} + +template +inline T clamp(T const& a, T const& min, T const& max) { + return std::min(max, std::max(a, min)); +} + +template +inline T saturate(T const& a) { + return std::min(static_cast(1), std::max(a, static_cast(0))); +} + +template +inline T sign(T const& a) { + if (a == 0) { + return 0; } - - template - constexpr T pow2(T const& a) { - return binpow(a, 2); + return std::copysign(1, a); +} + +template +inline T signedSqrt(T const& a) { + return sign(a) * std::sqrt(std::abs(a)); +} + +double posfmod(double x, double y); + +int getHighestTerrainBlock( + class BlockSource* blockSource, + int x, + int z, + int minY, + int maxY, + std::string filter +); + +class LongLong3 { +public: + long long x = 0; + long long y = 0; + long long z = 0; + + constexpr LongLong3& operator+=(LongLong3 const& b) { + x += b.x; + y += b.y; + z += b.z; + return *this; } - template - constexpr T pow3(T const& a) { - return binpow(a, 3); + constexpr LongLong3& operator-=(LongLong3 const& b) { + x -= b.x; + y -= b.y; + z -= b.z; + return *this; } - - template - constexpr T pow4(T const& a) { - return binpow(a, 4); - } - - template - constexpr T pow5(T const& a) { - return binpow(a, 5); +}; +class EvalFunctions { + int normalSearchDis = 4; + BlockPos here; + BlockPos size; + BlockSource* blockSource; + BoundingBox normalSearchBox; + std::vector posMap; + std::vector solidMap; + bool searchBoxInitialized = false; + bool searchCacheBuilded = false; + bool blockdataInitialized = false; + +public: + void setPos(BlockPos const& pos) { here = pos; } + void setbs(BlockSource* bs) { + blockSource = bs; + blockdataInitialized = true; } - - template - constexpr T pow6(T const& a) { - return binpow(a, 6); - } - - template - constexpr T pow7(T const& a) { - return binpow(a, 7); - } - - template - constexpr T pow8(T const& a) { - return binpow(a, 8); - } - - template - inline T clamp(T const& a, T const& min, T const& max) { - return std::min(max, std::max(a, min)); - } - - template - inline T saturate(T const& a) { - return std::min(static_cast(1), std::max(a, static_cast(0))); - } - - template - inline T sign(T const& a) { - if (a == 0) { - return 0; - } - return std::copysign(1, a); - } - - template - inline T signedSqrt(T const& a) { - return sign(a) * std::sqrt(std::abs(a)); - } - - double posfmod(double x, double y); - - int getHighestTerrainBlock(class BlockSource* blockSource, int x, int z, int minY, int maxY, std::string filter); - - class LongLong3 { - public: - long long x = 0; - long long y = 0; - long long z = 0; - - constexpr LongLong3& operator+=(LongLong3 const& b) { - x += b.x; - y += b.y; - z += b.z; - return *this; - } - - constexpr LongLong3& operator-=(LongLong3 const& b) { - x -= b.x; - y -= b.y; - z -= b.z; - return *this; - } - }; - class EvalFunctions { - int normalSearchDis = 4; - BlockPos here; - BlockPos size; - BlockSource* blockSource; - BoundingBox normalSearchBox; - std::vector posMap; - std::vector solidMap; - bool searchBoxInitialized = false; - bool searchCacheBuilded = false; - bool blockdataInitialized = false; - - public: - void setPos(const BlockPos& pos) { here = pos; } - void setbs(BlockSource* bs) { - blockSource = bs; - blockdataInitialized = true; - } - void setbox(BoundingBox box); - void buildSearchCache(); - long long getIndex(const BlockPos& pos); - long long getSolidMap(const BlockPos& pos1, const BlockPos& pos2); - LongLong3 getPosMap(const BlockPos& pos1, const BlockPos& pos2); - double operator()(std::string_view name, const std::vector& params); - }; -} // namespace worldedit \ No newline at end of file + void setbox(BoundingBox box); + void buildSearchCache(); + long long getIndex(BlockPos const& pos); + long long getSolidMap(BlockPos const& pos1, BlockPos const& pos2); + LongLong3 getPosMap(BlockPos const& pos1, BlockPos const& pos2); + double operator()(std::string_view name, const std::vector& params); +}; +} // namespace we \ No newline at end of file diff --git a/old/core/eval/blur.cpp b/old/core/eval/blur.cpp index 7cf5e15..5579500 100644 --- a/old/core/eval/blur.cpp +++ b/old/core/eval/blur.cpp @@ -1,83 +1,82 @@ -// -// Created by OEOTYAN on 2022/05/30. -// #include "blur.hpp" -#include "mc/Level.hpp" #include "I18nAPI.h" +#include "mc/Level.hpp" -namespace worldedit { +namespace we { - std::vector gaussianKernel(int size, double sigma) { - static const double small_gaussian_tab[][7] = { - {1}, - {0.25, 0.5, 0.25}, - {0.0625, 0.25, 0.375, 0.25, 0.0625}, - {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125}, - }; - std::vector res; - int ksize = size * 2 + 1; - res.resize(size * 2 + 1); - if (size < 4) { - for (int i = 0; i < ksize; ++i) { - res[i] = small_gaussian_tab[size][i]; - } - return res; - } - if (sigma < 0) { - sigma = 0.3 * (0.5 * (size - 1) - 1) + 0.8; - } - double scale2 = -0.5 / (sigma * sigma); - double sum = 0; - for (int i = 0; i < ksize; ++i) { - double x = i - size; - res[i] = exp(x * x * scale2); - sum += res[i]; - } +std::vector gaussianKernel(int size, double sigma) { + static const double small_gaussian_tab[][7] = { + {1}, + {0.25, 0.5, 0.25}, + {0.0625, 0.25, 0.375, 0.25, 0.0625}, + {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125}, + }; + std::vector res; + int ksize = size * 2 + 1; + res.resize(size * 2 + 1); + if (size < 4) { for (int i = 0; i < ksize; ++i) { - res[i] /= sum; + res[i] = small_gaussian_tab[size][i]; } return res; } - std::vector blur2D(std::vector const& heightMap, int ksize, int sizex, int sizez) { - std::vector res; - try { - res.resize(heightMap.size()); - } catch (std::bad_alloc) { - Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); - return std::vector(0); - } - auto kernel = gaussianKernel(ksize); - for (int x = 0; x < sizex; ++x) - for (int z = 0; z < sizez; ++z) { - double sum = 0; - double sumk = 0; - for (int k = -ksize; k <= ksize; k++) - if (x + k >= 0 && x + k < sizex && heightMap[(x + k) * sizez + z] > -1e100) { - sum += heightMap[(x + k) * sizez + z] * kernel[k + ksize]; - sumk += kernel[k + ksize]; - } - if (sumk <= 0) { - res[x * sizez + z] = heightMap[x * sizez + z]; - } else { - res[x * sizez + z] = sum / sumk; + if (sigma < 0) { + sigma = 0.3 * (0.5 * (size - 1) - 1) + 0.8; + } + double scale2 = -0.5 / (sigma * sigma); + double sum = 0; + for (int i = 0; i < ksize; ++i) { + double x = i - size; + res[i] = exp(x * x * scale2); + sum += res[i]; + } + for (int i = 0; i < ksize; ++i) { + res[i] /= sum; + } + return res; +} +std::vector +blur2D(std::vector const& heightMap, int ksize, int sizex, int sizez) { + std::vector res; + try { + res.resize(heightMap.size()); + } catch (std::bad_alloc) { + Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); + return std::vector(0); + } + auto kernel = gaussianKernel(ksize); + for (int x = 0; x < sizex; ++x) + for (int z = 0; z < sizez; ++z) { + double sum = 0; + double sumk = 0; + for (int k = -ksize; k <= ksize; k++) + if (x + k >= 0 && x + k < sizex + && heightMap[(x + k) * sizez + z] > -1e100) { + sum += heightMap[(x + k) * sizez + z] * kernel[k + ksize]; + sumk += kernel[k + ksize]; } + if (sumk <= 0) { + res[x * sizez + z] = heightMap[x * sizez + z]; + } else { + res[x * sizez + z] = sum / sumk; } - std::vector tmp(res); - for (int x = 0; x < sizex; ++x) - for (int z = 0; z < sizez; ++z) { - double sum = 0; - double sumk = 0; - for (int k = -ksize; k <= ksize; k++) - if (z + k >= 0 && z + k < sizez && tmp[x * sizez + (z + k)] > -1e100) { - sum += tmp[x * sizez + (z + k)] * kernel[k + ksize]; - sumk += kernel[k + ksize]; - } - if (sumk <= 0) { - res[x * sizez + z] = tmp[x * sizez + z]; - } else { - res[x * sizez + z] = sum / sumk; + } + std::vector tmp(res); + for (int x = 0; x < sizex; ++x) + for (int z = 0; z < sizez; ++z) { + double sum = 0; + double sumk = 0; + for (int k = -ksize; k <= ksize; k++) + if (z + k >= 0 && z + k < sizez && tmp[x * sizez + (z + k)] > -1e100) { + sum += tmp[x * sizez + (z + k)] * kernel[k + ksize]; + sumk += kernel[k + ksize]; } + if (sumk <= 0) { + res[x * sizez + z] = tmp[x * sizez + z]; + } else { + res[x * sizez + z] = sum / sumk; } - return res; - } -} // namespace worldedit \ No newline at end of file + } + return res; +} +} // namespace we \ No newline at end of file diff --git a/old/core/eval/blur.hpp b/old/core/eval/blur.hpp index 2b911ae..6d13729 100644 --- a/old/core/eval/blur.hpp +++ b/old/core/eval/blur.hpp @@ -1,11 +1,9 @@ -// -// Created by OEOTYAN on 2022/05/30. -// #pragma once #include -namespace worldedit { - std::vector gaussianKernel(int size, double sigma = -1); - std::vector blur2D(std::vector const& heightMap, int ksize, int sizex, int sizez); -} // namespace worldedit +namespace we { +std::vector gaussianKernel(int size, double sigma = -1); +std::vector +blur2D(std::vector const& heightMap, int ksize, int sizex, int sizez); +} // namespace we diff --git a/old/core/filesys/download.cpp b/old/core/filesys/download.cpp index 6e5432a..6320cff 100644 --- a/old/core/filesys/download.cpp +++ b/old/core/filesys/download.cpp @@ -1,36 +1,34 @@ -// -// Created by OEOTYAN on 2022/06/20. -// #include "download.h" +#include +#include +#include +#include #include #include -#include -#include -#include -#include #pragma comment(lib, "urlmon.lib") #pragma comment(lib, "wininet.lib") #pragma comment(lib, "ws2_32.lib") #pragma warning(disable : 4267) -namespace worldedit { - int download(std::string_view url, std::string_view outfilename) {} +namespace we { +int download(std::string_view url, std::string_view outfilename) {} - bool downloadImage(std::string const& url) { - size_t len = url.length(); - int nmlen = MultiByteToWideChar(CP_ACP, 0, url.c_str(), len + 1, NULL, (size_t)0); +bool downloadImage(std::string const& url) { + size_t len = url.length(); + int nmlen = MultiByteToWideChar(CP_ACP, 0, url.c_str(), len + 1, NULL, (size_t)0); - wchar_t* buffer = new wchar_t[nmlen]; - MultiByteToWideChar(CP_ACP, 0, url.c_str(), len + 1, buffer, (size_t)nmlen); + wchar_t* buffer = new wchar_t[nmlen]; + MultiByteToWideChar(CP_ACP, 0, url.c_str(), len + 1, buffer, (size_t)nmlen); - DeleteUrlCacheEntryW(buffer); + DeleteUrlCacheEntryW(buffer); - HRESULT hr = URLDownloadToFileW(NULL, buffer, _T("plugins/WorldEdit/imgtemp/0image"), 0, NULL); - if (hr == S_OK) { - return true; - } else { - return false; - } + HRESULT hr = + URLDownloadToFileW(NULL, buffer, _T("plugins/WorldEdit/imgtemp/0image"), 0, NULL); + if (hr == S_OK) { + return true; + } else { + return false; } +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/filesys/download.h b/old/core/filesys/download.h index 8a5035d..f111f9b 100644 --- a/old/core/filesys/download.h +++ b/old/core/filesys/download.h @@ -1,10 +1,7 @@ -// -// Created by OEOTYAN on 2022/06/20. -// #pragma once #include "Globals.h" -namespace worldedit { - int download(std::string_view url, std::string_view outfilename); - bool downloadImage(std::string const& url); -} // namespace worldedit +namespace we { +int download(std::string_view url, std::string_view outfilename); +bool downloadImage(std::string const& url); +} // namespace we diff --git a/old/core/filesys/file.cpp b/old/core/filesys/file.cpp index b3274b7..fc1baac 100644 --- a/old/core/filesys/file.cpp +++ b/old/core/filesys/file.cpp @@ -1,57 +1,57 @@ -// -// Created by OEOTYAN on 2022/06/20. -// #include "file.h" -#include +#include #include +#include #include -#include -namespace worldedit { - std::vector getFiles(std::string path) { - std::vector res; - res.clear(); - auto length = path.length(); - if (path.back() != '\\' && path.back() != '/') { - length += 1; - } - for (auto& file : std::filesystem::recursive_directory_iterator(path)) { - const auto& str = UTF82String(file.path().u8string()).substr(length); - // std::cout << str << std::endl; - res.push_back(str); - } - return res; +namespace we { +std::vector getFiles(std::string path) { + std::vector res; + res.clear(); + auto length = path.length(); + if (path.back() != '\\' && path.back() != '/') { + length += 1; } - std::vector getWEFiles(std::string path) { - return getFiles(WE_DIR + path); + for (auto& file : std::filesystem::recursive_directory_iterator(path)) { + const auto& str = UTF82String(file.path().u8string()).substr(length); + // std::cout << str << std::endl; + res.push_back(str); } - std::vector getFiles(std::string path, std::function filter) { - std::vector res; - res.clear(); - auto length = path.length(); - if (path.back() != '\\' && path.back() != '/') { - length += 1; - } - for (auto& file : std::filesystem::recursive_directory_iterator(path)) { - const auto& str = UTF82String(file.path().u8string()).substr(length); - if (filter(str)) { - res.push_back(str); - } - } - return res; - } - std::vector getWEFiles(std::string path, std::function filter) { - return getFiles(WE_DIR + path, filter); + return res; +} +std::vector getWEFiles(std::string path) { return getFiles(WE_DIR + path); } +std::vector +getFiles(std::string path, std::function filter) { + std::vector res; + res.clear(); + auto length = path.length(); + if (path.back() != '\\' && path.back() != '/') { + length += 1; } - phmap::flat_hash_set>>& getFileWatchSet() { - static phmap::flat_hash_set>> sets; - return sets; + for (auto& file : std::filesystem::recursive_directory_iterator(path)) { + const auto& str = UTF82String(file.path().u8string()).substr(length); + if (filter(str)) { + res.push_back(str); + } } + return res; +} +std::vector +getWEFiles(std::string path, std::function filter) { + return getFiles(WE_DIR + path, filter); +} +phmap::flat_hash_set>>& +getFileWatchSet() { + static phmap::flat_hash_set>> + sets; + return sets; +} void addFileWatch(std::string const& path, std::function func) { - getFileWatchSet().insert(std::unique_ptr>( - new filewatch::FileWatch(str2wstr(path), func))); - } -} // namespace worldedit \ No newline at end of file + getFileWatchSet().insert(std::unique_ptr>( + new filewatch::FileWatch(str2wstr(path), func) + )); +} +} // namespace we \ No newline at end of file diff --git a/old/core/filesys/file.h b/old/core/filesys/file.h index a4de8de..727944f 100644 --- a/old/core/filesys/file.h +++ b/old/core/filesys/file.h @@ -1,17 +1,16 @@ -// -// Created by OEOTYAN on 2022/06/20. -// #pragma once +#include "FileWatch.hpp" #include "Globals.h" #include -#include "FileWatch.hpp" -namespace worldedit { - std::vector getFiles(std::string path); - std::vector getWEFiles(std::string path); - std::vector getFiles(std::string path, std::function filter); - std::vector getWEFiles(std::string path, std::function filter); - phmap::flat_hash_set>>& getFileWatchSet(); - void addFileWatch(std::string const& path, - std::function); -} // namespace worldedit +namespace we { +std::vector getFiles(std::string path); +std::vector getWEFiles(std::string path); +std::vector +getFiles(std::string path, std::function filter); +std::vector +getWEFiles(std::string path, std::function filter); +phmap::flat_hash_set>>& +getFileWatchSet(); +void addFileWatch(std::string const& path, std::function); +} // namespace we diff --git a/old/core/image/Image.cpp b/old/core/image/Image.cpp index d2765a2..deb0d85 100644 --- a/old/core/image/Image.cpp +++ b/old/core/image/Image.cpp @@ -1,107 +1,125 @@ -// -// Created by OEOTYAN on 2022/06/11. -// #include "Image.h" -#include "eval/Eval.h" #include "WorldEdit.h" +#include "eval/Eval.h" #include "mc/Level.hpp" #define STBI_FAILURE_USERMSG #include "stb_image.h" -namespace worldedit { - void Sampler::setUV(double& u) const { - switch (edgeType) { - case EdgeType::CLAMP: - u = std::min(1.0, std::max(0.0, u)); - break; - case EdgeType::REPEAT: - u = u - floor(u); - break; - case EdgeType::FLIP: - u = abs(1 - posfmod(u + 1, 2)); - break; - default: - u = 0; - break; - } +namespace we { +void Sampler::setUV(double& u) const { + switch (edgeType) { + case EdgeType::CLAMP: + u = std::min(1.0, std::max(0.0, u)); + break; + case EdgeType::REPEAT: + u = u - floor(u); + break; + case EdgeType::FLIP: + u = abs(1 - posfmod(u + 1, 2)); + break; + default: + u = 0; + break; } +} - Texture2D::Texture2D(unsigned w, unsigned h) : width(w), height(h), size((unsigned long long)(w)*h) { - rawColor.resize(size); - }; +Texture2D::Texture2D(unsigned w, unsigned h) +: width(w), + height(h), + size((unsigned long long)(w)*h) { + rawColor.resize(size); +}; - mce::Color Texture2D::load(const Sampler& sampler, double u, double v, double offsetu, double offsetv) const { - u += offsetu / width; - v += offsetv / height; - sampler.setUV(u); - sampler.setUV(v); - if (u < 0 || v < 0) { - return mce::Color(0, 0, 0, 0); - } - u *= width; - v *= height; - unsigned iu = std::min(width - 1, std::max(0u, static_cast(floor(u)))); - unsigned iv = std::min(height - 1, std::max(0u, static_cast(floor(v)))); - return rawColor[iu + iv * width]; +mce::Color Texture2D::load( + const Sampler& sampler, + double u, + double v, + double offsetu, + double offsetv +) const { + u += offsetu / width; + v += offsetv / height; + sampler.setUV(u); + sampler.setUV(v); + if (u < 0 || v < 0) { + return mce::Color(0, 0, 0, 0); } - mce::Color Texture2D::sample(const Sampler& sampler, double u, double v, double lod) const { - switch (sampler.samplerType) { - case SamplerType::Bicubic: - case SamplerType::Bilinear: { - auto color0 = load(sampler, u, v); - auto color1 = load(sampler, u, v, 1); - auto color2 = load(sampler, u, v, 0, 1); - auto color3 = load(sampler, u, v, 1, 1); + u *= width; + v *= height; + unsigned iu = std::min(width - 1, std::max(0u, static_cast(floor(u)))); + unsigned iv = std::min(height - 1, std::max(0u, static_cast(floor(v)))); + return rawColor[iu + iv * width]; +} +mce::Color +Texture2D::sample(const Sampler& sampler, double u, double v, double lod) const { + switch (sampler.samplerType) { + case SamplerType::Bicubic: + case SamplerType::Bilinear: { + auto color0 = load(sampler, u, v); + auto color1 = load(sampler, u, v, 1); + auto color2 = load(sampler, u, v, 0, 1); + auto color3 = load(sampler, u, v, 1, 1); - mce::Color res(0, 0, 0, 0); - u *= width; - v *= height; - u += 0.5; - v += 0.5; - u -= floor(u); - v -= floor(v); + mce::Color res(0, 0, 0, 0); + u *= width; + v *= height; + u += 0.5; + v += 0.5; + u -= floor(u); + v -= floor(v); - double pm0 = (1 - u) * (1 - v); - double pm1 = v * (1 - u); - double pm2 = u * (1 - v); - double pm3 = u * v; + double pm0 = (1 - u) * (1 - v); + double pm1 = v * (1 - u); + double pm2 = u * (1 - v); + double pm3 = u * v; - res.r = static_cast(pm0 * color0.r + pm1 * color1.r + pm2 * color2.r + pm3 * color3.r); - res.g = static_cast(pm0 * color0.g + pm1 * color1.g + pm2 * color2.g + pm3 * color3.g); - res.b = static_cast(pm0 * color0.b + pm1 * color1.b + pm2 * color2.b + pm3 * color3.b); - res.a = static_cast(pm0 * color0.a + pm1 * color1.a + pm2 * color2.a + pm3 * color3.a); - return res; - } - default: - return load(sampler, u, v); - } - } - Texture2D loadImage(std::string const& filename) { - int width, height, channel; - unsigned char* data = stbi_load(filename.c_str(), &width, &height, &channel, 4); - if (data == nullptr) { - // logger().error("Image load error: {}", stbi_failure_reason()); - Level::broadcastText("§c" + tr("stb.image." + std::string(stbi_failure_reason())), TextType::RAW); - return Texture2D(0, 0); - } - Texture2D res(width, height); - for (size_t k = 0; k < res.size; k++) { - auto k4 = 4 * k; - res.rawColor[k] = mce::Color(data[k4], data[k4 + 1], data[k4 + 2], data[k4 + 3]); - } - stbi_image_free(data); + res.r = static_cast( + pm0 * color0.r + pm1 * color1.r + pm2 * color2.r + pm3 * color3.r + ); + res.g = static_cast( + pm0 * color0.g + pm1 * color1.g + pm2 * color2.g + pm3 * color3.g + ); + res.b = static_cast( + pm0 * color0.b + pm1 * color1.b + pm2 * color2.b + pm3 * color3.b + ); + res.a = static_cast( + pm0 * color0.a + pm1 * color1.a + pm2 * color2.a + pm3 * color3.a + ); return res; } + default: + return load(sampler, u, v); + } +} +Texture2D loadImage(std::string const& filename) { + int width, height, channel; + unsigned char* data = stbi_load(filename.c_str(), &width, &height, &channel, 4); + if (data == nullptr) { + // logger().error("Image load error: {}", stbi_failure_reason()); + Level::broadcastText( + "§c" + tr("stb.image." + std::string(stbi_failure_reason())), + TextType::RAW + ); + return Texture2D(0, 0); + } + Texture2D res(width, height); + for (size_t k = 0; k < res.size; k++) { + auto k4 = 4 * k; + res.rawColor[k] = mce::Color(data[k4], data[k4 + 1], data[k4 + 2], data[k4 + 3]); + } + stbi_image_free(data); + return res; +} - double colorToHeight(const mce::Color& color) { - if (color > 0) { - if (color.r == color.g && color.g == color.b) { - return color.r; - } else { - auto colorLinear = color.sRGBToLinear(); - return colorLinear.r * 0.299 + colorLinear.g * 0.587 + colorLinear.b * 0.114; - } +double colorToHeight(const mce::Color& color) { + if (color > 0) { + if (color.r == color.g && color.g == color.b) { + return color.r; + } else { + auto colorLinear = color.sRGBToLinear(); + return colorLinear.r * 0.299 + colorLinear.g * 0.587 + colorLinear.b * 0.114; } - return 0; } + return 0; +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/image/Image.h b/old/core/image/Image.h index a09532d..0ee77dd 100644 --- a/old/core/image/Image.h +++ b/old/core/image/Image.h @@ -1,47 +1,50 @@ -// -// Created by OEOTYAN on 2022/06/11. -// #pragma once #include "Globals.h" // #include "lodepng.h" -namespace worldedit { - enum class SamplerType { - Point = 0, - Bilinear = 1, - Bicubic = 2, - }; - enum class EdgeType { - ZERO = 0, - CLAMP = 1, - REPEAT = 2, - FLIP = 3, - }; - - class Sampler { - public: - SamplerType samplerType = SamplerType::Point; - EdgeType edgeType = EdgeType::REPEAT; - - Sampler() = default; - Sampler(SamplerType s, EdgeType e) : samplerType(s), edgeType(e){}; - void setUV(double&) const; - }; - - class Texture2D { - public: - std::vector rawColor; - - unsigned width = 0, height = 0; - unsigned long long size = 0; - - Texture2D(unsigned w, unsigned h); - mce::Color sample(const Sampler& sampler, double u, double v, double lod = 0.0) const; - mce::Color load(const Sampler& sampler, double u, double v, double offsetu = 0.0, double offsetv = 0.0) const; - }; - - Texture2D loadImage(std::string const& filename); - - double colorToHeight(const mce::Color& color); -} // namespace worldedit +namespace we { +enum class SamplerType { + Point = 0, + Bilinear = 1, + Bicubic = 2, +}; +enum class EdgeType { + ZERO = 0, + CLAMP = 1, + REPEAT = 2, + FLIP = 3, +}; + +class Sampler { +public: + SamplerType samplerType = SamplerType::Point; + EdgeType edgeType = EdgeType::REPEAT; + + Sampler() = default; + Sampler(SamplerType s, EdgeType e) : samplerType(s), edgeType(e){}; + void setUV(double&) const; +}; + +class Texture2D { +public: + std::vector rawColor; + + unsigned width = 0, height = 0; + unsigned long long size = 0; + + Texture2D(unsigned w, unsigned h); + mce::Color sample(const Sampler& sampler, double u, double v, double lod = 0.0) const; + mce::Color load( + const Sampler& sampler, + double u, + double v, + double offsetu = 0.0, + double offsetv = 0.0 + ) const; +}; + +Texture2D loadImage(std::string const& filename); + +double colorToHeight(const mce::Color& color); +} // namespace we diff --git a/old/core/particle/Graphics.cpp b/old/core/particle/Graphics.cpp index 827bee0..66bf931 100644 --- a/old/core/particle/Graphics.cpp +++ b/old/core/particle/Graphics.cpp @@ -1,150 +1,156 @@ -// -// Created by OEOTYAN on 2022/5/15. -// #pragma once -#include "Globals.h" #include "Graphics.h" +#include "Globals.h" #include "eval/Bresenham.hpp" // #include "mc/Level.hpp" #define MAX_LENGTH (64.0f) -namespace worldedit { - class ::ParticleCUI& globalPT() { - static ParticleCUI pt = ParticleCUI(); - return pt; - } - std::string facingToString(FACING facing) { - switch (facing) { - case FACING::POS_X: - return "+x"; - case FACING::NEG_X: - return "-x"; - case FACING::POS_Y: - return "+y"; - case FACING::POS_Z: - return "+z"; - case FACING::NEG_Y: - return "-y"; - case FACING::NEG_Z: - return "-z"; - default: - return "unknown"; - } +namespace we { +class ::ParticleCUI& globalPT() { + static ParticleCUI pt = ParticleCUI(); + return pt; +} +std::string facingToString(FACING facing) { + switch (facing) { + case FACING::POS_X: + return "+x"; + case FACING::NEG_X: + return "-x"; + case FACING::POS_Y: + return "+y"; + case FACING::POS_Z: + return "+z"; + case FACING::NEG_Y: + return "-y"; + case FACING::NEG_Z: + return "-z"; + default: + return "unknown"; } +} - std::string facingToDirString(FACING facing) { - switch (facing) { - case FACING::POS_X: - return "west"; - case FACING::NEG_X: - return "east"; - case FACING::POS_Y: - return "up"; - case FACING::POS_Z: - return "south"; - case FACING::NEG_Y: - return "down"; - case FACING::NEG_Z: - return "north"; - default: - return "unknown"; - } +std::string facingToDirString(FACING facing) { + switch (facing) { + case FACING::POS_X: + return "west"; + case FACING::NEG_X: + return "east"; + case FACING::POS_Y: + return "up"; + case FACING::POS_Z: + return "south"; + case FACING::NEG_Y: + return "down"; + case FACING::NEG_Z: + return "north"; + default: + return "unknown"; } - FACING dirStringToFacing(std::string_view dir) { - if (dir == "west") { - return FACING::POS_X; - } else if (dir == "east") { - return FACING::NEG_X; - } else if (dir == "down") { - return FACING::NEG_Y; - } else if (dir == "south") { - return FACING::POS_Z; - } else if (dir == "north") { - return FACING::NEG_Z; - } - return FACING::POS_Y; - } - FACING dirToFacing(const Vec3& dir) { - Vec3 mDir = dir.normalize(); - if (mDir.x > 0.71) { - return FACING::POS_X; - } else if (mDir.x < -0.71) { - return FACING::NEG_X; - } else if (mDir.y < -0.71) { - return FACING::NEG_Y; - } else if (mDir.z > 0.71) { - return FACING::POS_Z; - } else if (mDir.z < -0.71) { - return FACING::NEG_Z; - } - return FACING::POS_Y; +} +FACING dirStringToFacing(std::string_view dir) { + if (dir == "west") { + return FACING::POS_X; + } else if (dir == "east") { + return FACING::NEG_X; + } else if (dir == "down") { + return FACING::NEG_Y; + } else if (dir == "south") { + return FACING::POS_Z; + } else if (dir == "north") { + return FACING::NEG_Z; } - bool facingIsPos(FACING facing) { - return facing == FACING::POS_X || facing == FACING::POS_Y || facing == FACING::POS_Z; + return FACING::POS_Y; +} +FACING dirToFacing(const Vec3& dir) { + Vec3 mDir = dir.normalize(); + if (mDir.x > 0.71) { + return FACING::POS_X; + } else if (mDir.x < -0.71) { + return FACING::NEG_X; + } else if (mDir.y < -0.71) { + return FACING::NEG_Y; + } else if (mDir.z > 0.71) { + return FACING::POS_Z; + } else if (mDir.z < -0.71) { + return FACING::NEG_Z; } + return FACING::POS_Y; +} +bool facingIsPos(FACING facing) { + return facing == FACING::POS_X || facing == FACING::POS_Y || facing == FACING::POS_Z; +} - bool facingIsNeg(FACING facing) { - return facing == FACING::NEG_X || facing == FACING::NEG_Y || facing == FACING::NEG_Z; - } +bool facingIsNeg(FACING facing) { + return facing == FACING::NEG_X || facing == FACING::NEG_Y || facing == FACING::NEG_Z; +} - bool facingIsX(FACING facing) { - return facing == FACING::POS_X || facing == FACING::NEG_X; - } +bool facingIsX(FACING facing) { + return facing == FACING::POS_X || facing == FACING::NEG_X; +} - bool facingIsY(FACING facing) { - return facing == FACING::POS_Y || facing == FACING::NEG_Y; - } +bool facingIsY(FACING facing) { + return facing == FACING::POS_Y || facing == FACING::NEG_Y; +} - bool facingIsZ(FACING facing) { - return facing == FACING::POS_Z || facing == FACING::NEG_Z; - } - BlockPos facingToPos(FACING facing, int length = 1) { - switch (facing) { - case FACING::POS_X: - return BlockPos(length, 0, 0); - case FACING::NEG_X: - return BlockPos(-length, 0, 0); - case FACING::NEG_Z: - return BlockPos(0, 0, -length); - case FACING::POS_Z: - return BlockPos(0, 0, length); - case FACING::NEG_Y: - return BlockPos(0, -length, 0); - case FACING::POS_Y: - return BlockPos(0, length, 0); - default: - return BlockPos(0, 0, 0); - } +bool facingIsZ(FACING facing) { + return facing == FACING::POS_Z || facing == FACING::NEG_Z; +} +BlockPos facingToPos(FACING facing, int length = 1) { + switch (facing) { + case FACING::POS_X: + return BlockPos(length, 0, 0); + case FACING::NEG_X: + return BlockPos(-length, 0, 0); + case FACING::NEG_Z: + return BlockPos(0, 0, -length); + case FACING::POS_Z: + return BlockPos(0, 0, length); + case FACING::NEG_Y: + return BlockPos(0, -length, 0); + case FACING::POS_Y: + return BlockPos(0, length, 0); + default: + return BlockPos(0, 0, 0); } +} - FACING invFacing(FACING facing) { - switch (facing) { - case FACING::NEG_Y: - return FACING::POS_Y; - case FACING::POS_Y: - return FACING::NEG_Y; - case FACING::NEG_Z: - return FACING::POS_Z; - case FACING::POS_Z: - return FACING::NEG_Z; - case FACING::NEG_X: - return FACING::POS_X; - case FACING::POS_X: - return FACING::NEG_X; - default: - return FACING::POS_X; - } +FACING invFacing(FACING facing) { + switch (facing) { + case FACING::NEG_Y: + return FACING::POS_Y; + case FACING::POS_Y: + return FACING::NEG_Y; + case FACING::NEG_Z: + return FACING::POS_Z; + case FACING::POS_Z: + return FACING::NEG_Z; + case FACING::NEG_X: + return FACING::POS_X; + case FACING::POS_X: + return FACING::NEG_X; + default: + return FACING::POS_X; } +} - void drawCurve(KochanekBartelsInterpolation const& curve, mce::ColorPalette color, int dimType) { - auto length = (float)(curve.arcLength()); - length = std::min(length * 2.5f, MAX_LENGTH * 0.5f); - int len = (int)ceil(length); - auto particle = getParticleColorType(color); - for (int i = 0; i <= len; ++i) { - auto point = curve.getPosition(i / (double)len); - globalPT().drawPoint(point, dimType, ParticleCUI::PointSize::PX4, mce::ColorPalette::YELLOW); - } +void drawCurve( + KochanekBartelsInterpolation const& curve, + mce::ColorPalette color, + int dimType +) { + auto length = (float)(curve.arcLength()); + length = std::min(length * 2.5f, MAX_LENGTH * 0.5f); + int len = (int)ceil(length); + auto particle = getParticleColorType(color); + for (int i = 0; i <= len; ++i) { + auto point = curve.getPosition(i / (double)len); + globalPT().drawPoint( + point, + dimType, + ParticleCUI::PointSize::PX4, + mce::ColorPalette::YELLOW + ); } -} // namespace worldedit +} +} // namespace we diff --git a/old/core/particle/Graphics.h b/old/core/particle/Graphics.h index 4f7a891..6dabec4 100644 --- a/old/core/particle/Graphics.h +++ b/old/core/particle/Graphics.h @@ -1,45 +1,46 @@ -// -// Created by OEOTYAN on 2022/5/15. -// #pragma once #include "Globals.h" #include "ParticleAPI.h" -namespace worldedit { +namespace we { - enum class FACING { - NEG_Y = 0, - POS_Y = 1, - NEG_Z = 2, - POS_Z = 3, - NEG_X = 4, - POS_X = 5, - }; +enum class FACING { + NEG_Y = 0, + POS_Y = 1, + NEG_Z = 2, + POS_Z = 3, + NEG_X = 4, + POS_X = 5, +}; - bool facingIsPos(FACING facing); +bool facingIsPos(FACING facing); - bool facingIsNeg(FACING facing); +bool facingIsNeg(FACING facing); - bool facingIsX(FACING facing); +bool facingIsX(FACING facing); - bool facingIsY(FACING facing); +bool facingIsY(FACING facing); - bool facingIsZ(FACING facing); +bool facingIsZ(FACING facing); - FACING invFacing(FACING facing); +FACING invFacing(FACING facing); - std::string facingToString(FACING facing); +std::string facingToString(FACING facing); - BlockPos facingToPos(FACING facing, int length); +BlockPos facingToPos(FACING facing, int length); - FACING dirStringToFacing(std::string_view dir); +FACING dirStringToFacing(std::string_view dir); - FACING dirToFacing(const Vec3& dir); +FACING dirToFacing(const Vec3& dir); - std::string facingToDirString(FACING facing); +std::string facingToDirString(FACING facing); - void drawCurve(class KochanekBartelsInterpolation const& curve, enum mce::ColorPalette color, int dimType); +void drawCurve( + class KochanekBartelsInterpolation const& curve, + enum mce::ColorPalette color, + int dimType +); - class ::ParticleCUI& globalPT(); -} // namespace worldedit +class ::ParticleCUI& globalPT(); +} // namespace we diff --git a/old/core/region/ConvexRegion.cpp b/old/core/region/ConvexRegion.cpp deleted file mode 100644 index 1b5d376..0000000 --- a/old/core/region/ConvexRegion.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "ConvexRegion.h" -#include "Globals.h" -#include "mc/Level.hpp" -#include "mc/Dimension.hpp" -namespace worldedit { - void ConvexRegion::updateBoundingBox() { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - boundingBox.min = *vertices.begin(); - boundingBox.max = *vertices.begin(); - - for (auto& vertice : vertices) { - boundingBox.min.x = std::min(boundingBox.min.x, vertice.x); - boundingBox.min.y = std::max(std::min(boundingBox.min.y, vertice.y), static_cast(range.min)); - boundingBox.min.z = std::min(boundingBox.min.z, vertice.z); - boundingBox.max.x = std::max(boundingBox.max.x, vertice.x); - boundingBox.max.y = std::min(std::max(boundingBox.max.y, vertice.y), static_cast(range.max) - 1); - boundingBox.max.z = std::max(boundingBox.max.z, vertice.z); - } - for (auto& value : vertexBacklog) { - boundingBox.min.x = std::min(boundingBox.min.x, value.x); - boundingBox.min.y = std::max(std::min(boundingBox.min.y, value.y), static_cast(range.min)); - boundingBox.min.z = std::min(boundingBox.min.z, value.z); - boundingBox.max.x = std::max(boundingBox.max.x, value.x); - boundingBox.max.y = std::min(std::max(boundingBox.max.y, value.y), static_cast(range.max) - 1); - boundingBox.max.z = std::max(boundingBox.max.z, value.z); - } - } - - void ConvexRegion::updateEdges() { - edges.clear(); - for (auto triangle : triangles) { - for (int i = 0; i < 3; ++i) { - Edge edge = triangle.getEdge(i); - if (!edges.contains(edge)) { - edges.insert(edge); - } - } - } - } - - ConvexRegion::ConvexRegion(const BoundingBox& region, const int& dim) : Region(region, dim) { - vertices.clear(); - poss.clear(); - triangles.clear(); - vertexBacklog.clear(); - edges.clear(); - hasLast = false; - centerAccum = BlockPos(0, 0, 0); - regionType = CONVEX; - } - - bool ConvexRegion::containsRaw(const Vec3& pt) { - if (lastTriangle.above(pt) && hasLast) { - return false; - } - - for (Triangle triangle : triangles) { - if (lastTriangle == triangle) { - continue; - } - - if (triangle.above(pt)) { - hasLast = true; - lastTriangle = triangle; - return false; - } - } - - return true; - } - - bool ConvexRegion::addVertex(const BlockPos& vertex) { - hasLast = false; - if (vertices.contains(vertex)) { - return false; - } - Vec3 vertexD = vertex.toVec3(); - if (vertices.size() == 3) { - if (vertexBacklog.contains(vertex)) { - return false; - } - if (containsRaw(vertexD)) { - vertexBacklog.insert(vertex); - updateBoundingBox(); - return true; - } - } - vertices.insert(vertex); - updateBoundingBox(); - centerAccum = centerAccum + vertex; - - switch (vertices.size()) { - case 0: - case 1: - case 2: { - return true; - }; - case 3: { - std::vector v; - v.assign(vertices.begin(), vertices.end()); - triangles.emplace_back(Triangle(v[0].toVec3(), v[1].toVec3(), v[2].toVec3())); - triangles.emplace_back(Triangle(v[0].toVec3(), v[2].toVec3(), v[1].toVec3())); - updateEdges(); - return true; - }; - default: - break; - } - phmap::flat_hash_set borderEdges; - for (auto iter = triangles.begin(); iter != triangles.end();) { - if ((*iter).above(vertexD)) { - for (int i = 0; i < 3; ++i) { - Edge edge = (*iter).getEdge(i); - if (!borderEdges.contains(edge)) { - borderEdges.insert(edge); - } else { - borderEdges.erase(edge); - } - } - iter = triangles.erase(iter); - } else - ++iter; - } - for (Edge edge : borderEdges) { - triangles.emplace_back(edge.createTriangle(vertexD)); - } - - if (!vertexBacklog.empty()) { - vertices.erase(vertex); - phmap::flat_hash_set vertexBacklog2(vertexBacklog); - vertexBacklog.clear(); - for (BlockPos vertex2 : vertexBacklog2) { - addVertex(vertex2); - } - vertices.insert(vertex); - } - updateEdges(); - return true; - } - - bool ConvexRegion::setMainPos(const BlockPos& pos, const int& dim) { - dimensionID = dim; - selecting = 1; - hasLast = false; - vertices.clear(); - triangles.clear(); - vertexBacklog.clear(); - edges.clear(); - poss.clear(); - centerAccum = BlockPos(0, 0, 0); - bool res = addVertex(pos); - if (res) { - poss.push_back(pos); - } - return res; - } - - bool ConvexRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - return false; - } - bool res = addVertex(pos); - if (res) { - poss.push_back(pos); - } - return res; - } - - std::pair ConvexRegion::shift(const BlockPos& change) { - boundingBox.min = boundingBox.min + change; - boundingBox.max = boundingBox.max + change; - phmap::flat_hash_set tmpVertices = vertices; - vertices.clear(); - for (auto vertice : tmpVertices) { - vertices.insert(vertice + change); - } - for (auto& pos : poss) { - pos += change; - } - phmap::flat_hash_set tmpVertexBacklog = vertexBacklog; - vertexBacklog.clear(); - for (auto vertex : tmpVertexBacklog) { - vertexBacklog.insert(vertex + change); - } - std::vector tmpTriangles = triangles; - triangles.clear(); - for (auto triangle : tmpTriangles) { - triangles.emplace_back(Triangle(triangle.vertices[0] + change.toVec3(), - triangle.vertices[1] + change.toVec3(), - triangle.vertices[2] + change.toVec3())); - } - phmap::flat_hash_set tmpEdges = edges; - edges.clear(); - for (auto edge : tmpEdges) { - edges.insert(Edge(edge.start + change.toVec3(), edge.end + change.toVec3())); - } - centerAccum = centerAccum + change * (int)vertices.size(); - hasLast = false; - - return {"worldedit.shift.shifted", true}; - } - - bool ConvexRegion::contains(const BlockPos& pos) { - if (triangles.empty()) { - return false; - } - - if (!pos.containedWithin(boundingBox.min, boundingBox.max)) { - return false; - } - - return containsRaw(pos.toVec3()); - } - - void ConvexRegion::forEachLine(const std::function& todo) { - if (poss.size() > 1) { - for (int i = 0; i < poss.size() - 1; ++i) { - todo(poss[i], poss[i + 1]); - } - } - } - - uint64_t ConvexRegion::size() const { - double volume = 0; - for (auto triangle : triangles) { - volume += triangle.getVertex(0).cross(triangle.getVertex(1)).dot(triangle.getVertex(2)); - } - return (uint64_t)std::abs(volume / 6.0); - }; - - void ConvexRegion::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - rendertick = 40; - auto size = vertices.size(); - for (auto& vertice : vertices) { - globalPT().drawCuboid(vertice, dimensionID, mce::ColorPalette::GREEN); - } - for (auto& pos : poss) { - if (!vertices.contains(pos)) { - globalPT().drawCuboid(pos, dimensionID, mce::ColorPalette::WHITE); - } - } - for (auto& edge : edges) { - globalPT().drawOrientedLine(edge.start + 0.5f, edge.end + 0.5f, dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - } - } - rendertick--; - }; - - bool Edge::operator==(const Edge& other) const { - return (start == other.start && end == other.end) || (end == other.start && start == other.end); - } - - Triangle Edge::createTriangle(const Vec3& vertex) { - return Triangle(start, end, vertex); - } - - Triangle::Triangle(const Vec3& v0, const Vec3& v1, const Vec3& v2) { - vertices[0] = v0; - vertices[1] = v1; - vertices[2] = v2; - normal = ((v1 - v0).cross(v2 - v0)).normalize(); - maxDotProduct = (float)std::max(std::max(normal.dot(v0), normal.dot(v1)), normal.dot(v2)); - } - bool Triangle::operator==(const Triangle& v) const { - return (v.maxDotProduct == maxDotProduct) && (v.normal == normal) && (v.vertices[0] == vertices[0]) && - (v.vertices[1] == vertices[1]) && (v.vertices[2] == vertices[2]); - } - Edge Triangle::getEdge(const int& index) { - if (index == 2) - return Edge(vertices[index], vertices[0]); - return Edge(vertices[index], vertices[index + 1]); - } -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/ConvexRegion.h b/old/core/region/ConvexRegion.h deleted file mode 100644 index 3570254..0000000 --- a/old/core/region/ConvexRegion.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// -#pragma once - -#include "Globals.h" -#include "Region.h" -namespace worldedit { - class Triangle; - class Edge { - public: - Vec3 start; - Vec3 end; - - explicit Edge(const Vec3& _start, const Vec3& _end) : start(_start), end(_end){}; - bool operator==(const Edge& other) const; - Triangle createTriangle(const Vec3&); - }; - class _hash { - public: - size_t operator()(const Edge& rc) const { return std::hash()(rc.start) ^ std::hash()(rc.end); } - }; - class Triangle { - public: - Vec3 vertices[3]; - Vec3 normal; - float maxDotProduct; - - Triangle() = default; - Triangle(const Vec3& v0, const Vec3& v1, const Vec3& v2); - Vec3 getVertex(const int& index) const { return vertices[index]; }; - Edge getEdge(const int& index); - bool below(const Vec3& pt) { return normal.dot(pt) < maxDotProduct; } - bool above(const Vec3& pt) { return normal.dot(pt) > maxDotProduct; } - bool operator==(const Triangle& v) const; - }; - - class Region; - - class ConvexRegion final : public Region { - private: - bool addVertex(const BlockPos& vertex); - - bool containsRaw(const Vec3& pt); - - void updateEdges(); - - phmap::flat_hash_set vertices; - - std::vector triangles; - - phmap::flat_hash_set edges; - - phmap::flat_hash_set vertexBacklog; - - BlockPos centerAccum; - - Triangle lastTriangle; - - bool hasLast = false; - - public: - std::vector poss; - - std::string getName() override { return "convex"; } - - void updateBoundingBox() override; - - explicit ConvexRegion(const BoundingBox& region, const int& dim); - - uint64_t size() const override; - - void renderRegion() override; - - std::pair shift(const BlockPos& change) override; - - Vec3 getCenter() const override { - return centerAccum.toVec3() * (1.0f / vertices.size()) + Vec3(0.5, 0.5, 0.5); - }; - - void forEachLine(const std::function& todo) override; - - bool setMainPos(const BlockPos& pos, const int& dim) override; - - bool setVicePos(const BlockPos& pos, const int& dim) override; - - bool contains(const BlockPos& pos) override; - }; -} // namespace worldedit diff --git a/old/core/region/CuboidRegion.cpp b/old/core/region/CuboidRegion.cpp deleted file mode 100644 index b570202..0000000 --- a/old/core/region/CuboidRegion.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "CuboidRegion.h" -#include "mc/Level.hpp" -#include "mc/Dimension.hpp" -namespace worldedit { - void CuboidRegion::updateBoundingBox() { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - boundingBox.min.x = std::min(mainPos.x, vicePos.x); - boundingBox.min.y = std::max(std::min(mainPos.y, vicePos.y), static_cast(range.min)); - boundingBox.min.z = std::min(mainPos.z, vicePos.z); - boundingBox.max.x = std::max(mainPos.x, vicePos.x); - boundingBox.max.y = std::min(std::max(mainPos.y, vicePos.y), static_cast(range.max) - 1); - boundingBox.max.z = std::max(mainPos.z, vicePos.z); - boundingBox.max.x = std::max(mainPos.x, vicePos.x); - vicePos.y = std::max(vicePos.y, static_cast(range.min)); - vicePos.y = std::min(vicePos.y, static_cast(range.max) - 1); - mainPos.y = std::max(mainPos.y, static_cast(range.min)); - mainPos.y = std::min(mainPos.y, static_cast(range.max) - 1); - } - - bool CuboidRegion::setMainPos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - dimensionID = dim; - vicePos = pos; - selecting = true; - } - mainPos = pos; - updateBoundingBox(); - return true; - } - - bool CuboidRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - dimensionID = dim; - mainPos = pos; - selecting = true; - } - vicePos = pos; - updateBoundingBox(); - return true; - } - - std::pair CuboidRegion::expand(const std::vector& changes) { - for (auto change : changes) { - if (change.x > 0) { - if (std::max(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } else { - if (std::min(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } - - if (change.y > 0) { - if (std::max(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } else { - if (std::min(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } - - if (change.z > 0) { - if (std::max(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } else { - if (std::min(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } - } - - updateBoundingBox(); - - return {"worldedit.expand.expanded", true}; - } - - std::pair CuboidRegion::contract(const std::vector& changes) { - for (auto change : changes) { - if (change.x < 0) { - if (std::max(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } else { - if (std::min(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } - - if (change.y < 0) { - if (std::max(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } else { - if (std::min(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } - - if (change.z < 0) { - if (std::max(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } else { - if (std::min(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } - } - - updateBoundingBox(); - return {"worldedit.contract.contracted", true}; - } - - std::pair CuboidRegion::shift(const BlockPos& change) { - mainPos = mainPos + change; - vicePos = vicePos + change; - updateBoundingBox(); - - return {"worldedit.shift.shifted", true}; - } - - void CuboidRegion::forEachLine(const std::function& todo) { - todo(mainPos, vicePos); - } - - CuboidRegion::CuboidRegion() : Region{BoundingBox(), -1} { - regionType = CUBOID; - needResetVice = false; - } - CuboidRegion::CuboidRegion(const BoundingBox& region, const int& dim) : Region(region, dim) { - regionType = CUBOID; - mainPos = region.min; - vicePos = region.max; - needResetVice = false; - if (dim != -1 && region != BoundingBox()) { - selecting = true; - } - } -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/CuboidRegion.h b/old/core/region/CuboidRegion.h deleted file mode 100644 index 968e0c8..0000000 --- a/old/core/region/CuboidRegion.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// -#pragma once - -#include "Globals.h" -#include "Region.h" -namespace worldedit { - class CuboidRegion final : public Region { - public: - BlockPos mainPos = BlockPos::MIN; - BlockPos vicePos = BlockPos::MIN; - void updateBoundingBox() override; - - std::string getName() override { return "cuboid"; } - - explicit CuboidRegion(const BoundingBox& region, const int& dim); - explicit CuboidRegion(); - - std::pair expand(const std::vector& changes) override; - - std::pair contract(const std::vector& changes) override; - - std::pair shift(const BlockPos& change) override; - - bool setMainPos(const BlockPos& pos, const int& dim) override; - - bool setVicePos(const BlockPos& pos, const int& dim) override; - - void forEachLine(const std::function& todo) override; - }; -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/CylinderRegion.cpp b/old/core/region/CylinderRegion.cpp index 02b1e29..696a496 100644 --- a/old/core/region/CylinderRegion.cpp +++ b/old/core/region/CylinderRegion.cpp @@ -1,189 +1,224 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "CylinderRegion.h" -#include "mc/Level.hpp" -#include "mc/Dimension.hpp" #include "ParticleAPI.h" -namespace worldedit { - CylinderRegion::CylinderRegion(const BoundingBox& region, const int& dim) : Region(region, dim) { - selecting = false; - hasY = false; - regionType = CYLINDER; - } - - void CylinderRegion::forEachBlockUVInRegion(const std::function& todo) { - forEachBlockInRegion([&](const BlockPos& pos) { - int counts = 0; - for (auto& calPos : pos.getNeighbors()) { - counts += contains(calPos); - } - if (counts < 6) { - todo(pos, (atan2(pos.z - center.z, pos.x - center.x) + M_PI) / (M_PI * 2), - (pos.y - minY) / static_cast(maxY - minY)); - } - }); - } +#include "mc/Dimension.hpp" +#include "mc/Level.hpp" +namespace we { +CylinderRegion::CylinderRegion(const BoundingBox& region, int dim) : Region(region, dim) { + selecting = false; + hasY = false; + regionType = CYLINDER; +} - void CylinderRegion::updateBoundingBox() { - if (hasY) { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - auto newRadius = (int)(radius); - boundingBox.min.x = center.x - newRadius; - boundingBox.min.y = std::max(minY, static_cast(range.min)); - boundingBox.min.z = center.z - newRadius; - boundingBox.max.x = center.x + newRadius; - boundingBox.max.y = std::min(maxY, static_cast(range.max) - 1); - boundingBox.max.z = center.z + newRadius; +void CylinderRegion::forEachBlockUVInRegion( + const std::function& todo +) { + forEachBlockInRegion([&](BlockPos const& pos) { + int counts = 0; + for (auto& calPos : pos.getNeighbors()) { + counts += contains(calPos); } - } - - bool CylinderRegion::setY(int y) { - if (!hasY) { - minY = y; - maxY = y; - hasY = true; - return true; - } else if (y < minY) { - minY = y; - return true; - } else if (y > maxY) { - maxY = y; - return true; + if (counts < 6) { + todo( + pos, + (atan2(pos.z - center.z, pos.x - center.x) + M_PI) / (M_PI * 2), + (pos.y - minY) / static_cast(maxY - minY) + ); } - return false; + }); +} + +void CylinderRegion::updateBoundingBox() { + if (hasY) { + auto range = reinterpret_cast( + Global->getDimension(dimensionID).mHandle.lock().get() + ) + ->getHeightRange(); + rendertick = 0; + auto newRadius = (int)(radius); + boundingBox.min.x = center.x - newRadius; + boundingBox.min.y = std::max(minY, static_cast(range.min)); + boundingBox.min.z = center.z - newRadius; + boundingBox.max.x = center.x + newRadius; + boundingBox.max.y = std::min(maxY, static_cast(range.max) - 1); + boundingBox.max.z = center.z + newRadius; } +} - bool CylinderRegion::setMainPos(const BlockPos& pos, const int& dim) { - selecting = true; - hasY = false; - selectedCenter = false; - selectedRadius = false; - dimensionID = dim; - center = pos; - radius = 0.5; - setY(pos.y); - selectedCenter = true; - selectedRadius = false; - updateBoundingBox(); +bool CylinderRegion::setY(int y) { + if (!hasY) { + minY = y; + maxY = y; + hasY = true; + return true; + } else if (y < minY) { + minY = y; + return true; + } else if (y > maxY) { + maxY = y; return true; } + return false; +} - bool CylinderRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID || !selectedCenter) { - return false; - } - double disx = pos.x - center.x; - double disz = pos.z - center.z; - double dis = sqrt(disx * disx + disz * disz); - if (dis >= radius) { - radius = static_cast(dis + 0.5); - } - selectedRadius = true; - setY(pos.y); - updateBoundingBox(); - return true; +bool CylinderRegion::setMainPos(BlockPos const& pos, int dim) { + selecting = true; + hasY = false; + selectedCenter = false; + selectedRadius = false; + dimensionID = dim; + center = pos; + radius = 0.5; + setY(pos.y); + selectedCenter = true; + selectedRadius = false; + updateBoundingBox(); + return true; +} + +bool CylinderRegion::setVicePos(BlockPos const& pos, int dim) { + if (!selecting || dim != dimensionID || !selectedCenter) { + return false; } + double disx = pos.x - center.x; + double disz = pos.z - center.z; + double dis = sqrt(disx * disx + disz * disz); + if (dis >= radius) { + radius = static_cast(dis + 0.5); + } + selectedRadius = true; + setY(pos.y); + updateBoundingBox(); + return true; +} - bool CylinderRegion::contains(const BlockPos& pos) { - if (pos.y < minY || pos.y > maxY) { - return false; - } - double disx = pos.x - center.x; - double disz = pos.z - center.z; - return disx * disx + disz * disz <= radius * radius; +bool CylinderRegion::contains(BlockPos const& pos) { + if (pos.y < minY || pos.y > maxY) { + return false; } + double disx = pos.x - center.x; + double disz = pos.z - center.z; + return disx * disx + disz * disz <= radius * radius; +} - int CylinderRegion::checkChanges(const std::vector& changes) { - int x = 0, z = 0; - for (auto change : changes) { - x += abs(change.x); - z += abs(change.z); - } - if (x == z) { - return x / 2; - } - return -1; +int CylinderRegion::checkChanges(const std::vector& changes) { + int x = 0, z = 0; + for (auto change : changes) { + x += abs(change.x); + z += abs(change.z); + } + if (x == z) { + return x / 2; } + return -1; +} - std::pair CylinderRegion::expand(const std::vector& changes) { - int check = checkChanges(changes); - if (check == -1) { - return {"orldedit.selection.expand.cylinder.error", false}; +bool CylinderRegion::expand(const std::vector& changes) { + int check = checkChanges(changes); + if (check == -1) { + return {"orldedit.selection.expand.cylinder.error", false}; + } else { + radius += check; + } + for (BlockPos change : changes) { + if (change.y > 0) { + maxY += change.y; } else { - radius += check; - } - for (BlockPos change : changes) { - if (change.y > 0) { - maxY += change.y; - } else { - minY += change.y; - } + minY += change.y; } - updateBoundingBox(); - return {"worldedit.expand.expanded", true}; } + updateBoundingBox(); + return {"worldedit.expand.expanded", true}; +} - std::pair CylinderRegion::contract(const std::vector& changes) { - int check = checkChanges(changes); - if (check == -1) { - return {"orldedit.selection.contract.cylinder.error", false}; +bool CylinderRegion::contract(const std::vector& changes) { + int check = checkChanges(changes); + if (check == -1) { + return {"orldedit.selection.contract.cylinder.error", false}; + } else { + radius -= check; + radius = std::max(radius, 0.5f); + } + for (BlockPos change : changes) { + int height = maxY - minY; + if (change.y > 0) { + minY += std::min(change.y, height); } else { - radius -= check; - radius = std::max(radius, 0.5f); + maxY += std::max(change.y, -height); } - for (BlockPos change : changes) { - int height = maxY - minY; - if (change.y > 0) { - minY += std::min(change.y, height); - } else { - maxY += std::max(change.y, -height); - } - } - updateBoundingBox(); - return {"worldedit.contract.contracted", true}; } + updateBoundingBox(); + return {"worldedit.contract.contracted", true}; +} - std::pair CylinderRegion::shift(const BlockPos& change) { - center = center + change; - maxY += change.y; - minY += change.y; - updateBoundingBox(); - return {"worldedit.shift.shifted", true}; - } +bool CylinderRegion::shift(BlockPos const& change) { + center = center + change; + maxY += change.y; + minY += change.y; + updateBoundingBox(); + return {"worldedit.shift.shifted", true}; +} - void CylinderRegion::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - rendertick = 40; - BlockPos centery = center; - centery.y = minY; - globalPT().drawCuboid(AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), dimensionID, - mce::ColorPalette::GREEN); - if (radius > 1.0f) { - centery.x = center.x - (int)radius; - globalPT().drawCuboid(AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), - dimensionID, mce::ColorPalette::YELLOW); - centery.x = center.x + (int)radius; - globalPT().drawCuboid(AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), - dimensionID, mce::ColorPalette::YELLOW); - centery.x = center.x; - centery.z = center.z - (int)radius; - globalPT().drawCuboid(AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), - dimensionID, mce::ColorPalette::YELLOW); - centery.z = center.z + (int)radius; - globalPT().drawCuboid(AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), - dimensionID, mce::ColorPalette::YELLOW); - globalPT().drawCircle(BlockPos(center.x, maxY, center.z), ParticleCUI::Direction::POS_Y, radius, - dimensionID, ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - if (minY != maxY) { - globalPT().drawCircle(BlockPos(center.x, minY, center.z), ParticleCUI::Direction::POS_Y, radius, - dimensionID, ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - } +void CylinderRegion::renderRegion() { + if (selecting && dimensionID >= 0 && rendertick <= 0) { + rendertick = 40; + BlockPos centery = center; + centery.y = minY; + globalPT().drawCuboid( + AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), + dimensionID, + mce::ColorPalette::GREEN + ); + if (radius > 1.0f) { + centery.x = center.x - (int)radius; + globalPT().drawCuboid( + AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), + dimensionID, + mce::ColorPalette::YELLOW + ); + centery.x = center.x + (int)radius; + globalPT().drawCuboid( + AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), + dimensionID, + mce::ColorPalette::YELLOW + ); + centery.x = center.x; + centery.z = center.z - (int)radius; + globalPT().drawCuboid( + AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), + dimensionID, + mce::ColorPalette::YELLOW + ); + centery.z = center.z + (int)radius; + globalPT().drawCuboid( + AABB(centery.toVec3(), centery.toVec3() + Vec3(1, 1 + maxY - minY, 1)), + dimensionID, + mce::ColorPalette::YELLOW + ); + globalPT().drawCircle( + BlockPos(center.x, maxY, center.z), + ParticleCUI::Direction::POS_Y, + radius, + dimensionID, + ParticleCUI::PointSize::PX4, + 1, + 64, + mce::ColorPalette::YELLOW + ); + if (minY != maxY) { + globalPT().drawCircle( + BlockPos(center.x, minY, center.z), + ParticleCUI::Direction::POS_Y, + radius, + dimensionID, + ParticleCUI::PointSize::PX4, + 1, + 64, + mce::ColorPalette::YELLOW + ); } } - rendertick--; - }; + } + rendertick--; +}; -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/region/CylinderRegion.h b/old/core/region/CylinderRegion.h index ecdd493..13ead45 100644 --- a/old/core/region/CylinderRegion.h +++ b/old/core/region/CylinderRegion.h @@ -1,48 +1,46 @@ -// -// Created by OEOTYAN on 2022/06/04. -// #pragma once -#include "Globals.h" -#include "Region.h" -namespace worldedit { - class CylinderRegion final : public Region { - private: - BlockPos center = BlockPos::MIN; - float radius = 0.5; - int minY = 0, maxY = 0; - bool hasY = false, selectedCenter = false, selectedRadius = false; - int checkChanges(const std::vector& changes); +#include "Region.h" - public: - std::string getName() override { return "cylinder"; } +namespace we { +class CylinderRegion : public Region { +private: + BlockPos center = BlockPos::MIN; + float radius = 0.5; + int minY = 0, maxY = 0; + bool hasY = false, selectedCenter = false, selectedRadius = false; + int checkChanges(const std::vector& changes); - explicit CylinderRegion(const BoundingBox& region, const int& dim); +public: + CylinderRegion(const BoundingBox& region, int dim); - void updateBoundingBox() override; + void updateBoundingBox() override; - bool setY(int y); + bool setY(int y); - uint64_t size() const override { - return (uint64_t)std::round(M_PI * (double)radius * (double)radius * (maxY - minY + 1)); - }; + uint64_t size() const override { + return (uint64_t + )std::round(M_PI * (double)radius * (double)radius * (maxY - minY + 1)); + }; - std::pair expand(const std::vector& changes) override; + bool expand(std::span) override; - std::pair contract(const std::vector& changes) override; + bool contract(std::span) override; - std::pair shift(const BlockPos& change) override; + bool shift(std::span) override; - void forEachBlockUVInRegion(const std::function& todo) override; + void forEachBlockUVInRegion( + const std::function& todo + ) const override; - void renderRegion() override; + void renderRegion() override; - float getRadius() const { return radius; }; + float getRadius() const { return radius; }; - bool setMainPos(const BlockPos& pos, const int& dim) override; + bool setMainPos(BlockPos const& pos, int dim) override; - bool setVicePos(const BlockPos& pos, const int& dim) override; + bool setVicePos(BlockPos const& pos, int dim) override; - bool contains(const BlockPos& pos) override; - }; -} // namespace worldedit + bool contains(BlockPos const& pos) override; +}; +} // namespace we diff --git a/old/core/region/ExpandRegion.cpp b/old/core/region/ExpandRegion.cpp deleted file mode 100644 index 7546472..0000000 --- a/old/core/region/ExpandRegion.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "ExpandRegion.h" -#include "mc/Level.hpp" -#include "mc/Dimension.hpp" -namespace worldedit { - void ExpandRegion::updateBoundingBox() { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - boundingBox.min.x = std::min(mainPos.x, vicePos.x); - boundingBox.min.y = std::max(std::min(mainPos.y, vicePos.y), static_cast(range.min)); - boundingBox.min.z = std::min(mainPos.z, vicePos.z); - boundingBox.max.x = std::max(mainPos.x, vicePos.x); - boundingBox.max.y = std::min(std::max(mainPos.y, vicePos.y), static_cast(range.max) - 1); - boundingBox.max.z = std::max(mainPos.z, vicePos.z); - vicePos.y = std::max(vicePos.y, static_cast(range.min)); - vicePos.y = std::min(vicePos.y, static_cast(range.max) - 1); - mainPos.y = std::max(mainPos.y, static_cast(range.min)); - mainPos.y = std::min(mainPos.y, static_cast(range.max) - 1); - } - - bool ExpandRegion::setMainPos(const BlockPos& pos, const int& dim) { - selecting = true; - dimensionID = dim; - mainPos = pos; - vicePos = pos; - updateBoundingBox(); - return true; - } - - bool ExpandRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - return false; - } - if (!pos.containedWithin(boundingBox.min, boundingBox.max)) { - mainPos.x = std::min(mainPos.x, pos.x); - mainPos.y = std::min(mainPos.y, pos.y); - mainPos.z = std::min(mainPos.z, pos.z); - vicePos.x = std::max(pos.x, vicePos.x); - vicePos.y = std::max(pos.y, vicePos.y); - vicePos.z = std::max(pos.z, vicePos.z); - updateBoundingBox(); - return true; - } - return false; - } - - std::pair ExpandRegion::expand(const std::vector& changes) { - for (auto change : changes) { - if (change.x > 0) { - if (std::max(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } else { - if (std::min(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } - - if (change.y > 0) { - if (std::max(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } else { - if (std::min(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } - - if (change.z > 0) { - if (std::max(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } else { - if (std::min(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } - } - - updateBoundingBox(); - - return {"worldedit.expand.expanded", true}; - } - - std::pair ExpandRegion::contract(const std::vector& changes) { - for (auto change : changes) { - if (change.x < 0) { - if (std::max(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } else { - if (std::min(mainPos.x, vicePos.x) == mainPos.x) { - mainPos = mainPos + BlockPos(change.x, 0, 0); - } else { - vicePos = vicePos + BlockPos(change.x, 0, 0); - } - } - - if (change.y < 0) { - if (std::max(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } else { - if (std::min(mainPos.y, vicePos.y) == mainPos.y) { - mainPos = mainPos + BlockPos(0, change.y, 0); - } else { - vicePos = vicePos + BlockPos(0, change.y, 0); - } - } - - if (change.z < 0) { - if (std::max(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } else { - if (std::min(mainPos.z, vicePos.z) == mainPos.z) { - mainPos = mainPos + BlockPos(0, 0, change.z); - } else { - vicePos = vicePos + BlockPos(0, 0, change.z); - } - } - } - - updateBoundingBox(); - return {"worldedit.contract.contracted", true}; - } - - std::pair ExpandRegion::shift(const BlockPos& change) { - mainPos = mainPos + change; - vicePos = vicePos + change; - updateBoundingBox(); - - return {"worldedit.shift.shifted", true}; - } - - ExpandRegion::ExpandRegion(const BoundingBox& region, const int& dim) - : Region(region, dim), mainPos(region.min), vicePos(region.max) { - regionType = EXPAND; - if (dim != -1 && region != BoundingBox()) { - selecting = true; - } - } -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/ExpandRegion.h b/old/core/region/ExpandRegion.h deleted file mode 100644 index 19916a8..0000000 --- a/old/core/region/ExpandRegion.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// -#pragma once - -#include "Globals.h" -#include "Region.h" -namespace worldedit { - class ExpandRegion final : public Region { - public: - BlockPos mainPos = BlockPos::MIN; - BlockPos vicePos = BlockPos::MIN; - void updateBoundingBox() override; - - std::string getName() override { return "extend"; } - - explicit ExpandRegion(const BoundingBox& region, const int& dim); - - std::pair expand(const std::vector& changes) override; - - std::pair contract(const std::vector& changes) override; - - std::pair shift(const BlockPos& change) override; - - bool setMainPos(const BlockPos& pos, const int& dim) override; - - bool setVicePos(const BlockPos& pos, const int& dim) override; - }; -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/LoftRegion.cpp b/old/core/region/LoftRegion.cpp index a47888e..c346e85 100644 --- a/old/core/region/LoftRegion.cpp +++ b/old/core/region/LoftRegion.cpp @@ -1,285 +1,288 @@ -// -// Created by OEOTYAN on 2022/06/18. -// #include "LoftRegion.h" -namespace worldedit { - LoftRegion::LoftRegion(const BoundingBox& region, const int& dim) : Region(BoundingBox(), dim) { - loftPoints.clear(); - interpolations.clear(); - cache1.clear(); - cache2.clear(); - regionType = LOFT; - } +namespace we { +LoftRegion::LoftRegion(const BoundingBox& region, int dim) : Region(BoundingBox(), dim) { + loftPoints.clear(); + interpolations.clear(); + cache1.clear(); + cache2.clear(); + regionType = LOFT; +} + +void LoftRegion::updateBoundingBox() { + posCached = false; + boundingBox = BoundingBox(); + interpolations.clear(); + cache1.clear(); + cache2.clear(); + if (maxPointCount == 1) { + std::vector nodes2; + nodes2.clear(); + for (auto& point : loftPoints) { + nodes2.push_back(Node(point[0])); + } + cache1.push_back(KochanekBartelsInterpolation(nodes2, circle)); + } else { + for (auto& points : loftPoints) { + std::vector nodes; + nodes.clear(); + for (auto& point : points) { + nodes.push_back(Node(point)); + } + interpolations.push_back(KochanekBartelsInterpolation(nodes)); + } - void LoftRegion::updateBoundingBox() { - posCached = false; - boundingBox = BoundingBox(); - interpolations.clear(); - cache1.clear(); - cache2.clear(); - if (maxPointCount == 1) { + for (int i = 0; i < maxPointCount * 2 - 1; ++i) { std::vector nodes2; nodes2.clear(); - for (auto& point : loftPoints) { - nodes2.push_back(Node(point[0])); + double t = i / (double)((maxPointCount - 1) * 2); + for (auto& curve : interpolations) { + nodes2.push_back(Node(curve.getPosition(t))); } cache1.push_back(KochanekBartelsInterpolation(nodes2, circle)); - } else { - for (auto& points : loftPoints) { - std::vector nodes; - nodes.clear(); - for (auto& point : points) { - nodes.push_back(Node(point)); - } - interpolations.push_back(KochanekBartelsInterpolation(nodes)); - } - - for (int i = 0; i < maxPointCount * 2 - 1; ++i) { - std::vector nodes2; - nodes2.clear(); - double t = i / (double)((maxPointCount - 1) * 2); - for (auto& curve : interpolations) { - nodes2.push_back(Node(curve.getPosition(t))); - } - cache1.push_back(KochanekBartelsInterpolation(nodes2, circle)); - } - auto rSize = loftPoints.size() + circle - 1; - for (int i = 1; i <= rSize; ++i) { - std::vector nodes2; - nodes2.clear(); - for (int j = 0; j < maxPointCount; ++j) { - double t = (i * 2 - 1) / (rSize * 2.0); - nodes2.push_back(Node(cache1[j * 2].getPosition(t))); - } - cache2.push_back(KochanekBartelsInterpolation(nodes2)); + } + auto rSize = loftPoints.size() + circle - 1; + for (int i = 1; i <= rSize; ++i) { + std::vector nodes2; + nodes2.clear(); + for (int j = 0; j < maxPointCount; ++j) { + double t = (i * 2 - 1) / (rSize * 2.0); + nodes2.push_back(Node(cache1[j * 2].getPosition(t))); } + cache2.push_back(KochanekBartelsInterpolation(nodes2)); } - rendertick = 0; } + rendertick = 0; +} - bool LoftRegion::contains(const BlockPos& pos) { - if (posCached) { - return posCache.contains(pos); - } - return false; - }; +bool LoftRegion::contains(BlockPos const& pos) { + if (posCached) { + return posCache.contains(pos); + } + return false; +}; - bool LoftRegion::removePoint(int dim, const BlockPos& pos) { - if (!selecting) { - return false; - } - if (dim != dimensionID) { - return false; - } - if (loftPoints.size() == 1 && loftPoints[0].size() == 1) { - selecting = false; - return true; - } - if (pos == BlockPos::MIN) { - auto& points = loftPoints.back(); - if (points.size() == 1) { - loftPoints.pop_back(); - } else { - points.pop_back(); - } +bool LoftRegion::removePoint(int dim, BlockPos const& pos) { + if (!selecting) { + return false; + } + if (dim != dimensionID) { + return false; + } + if (loftPoints.size() == 1 && loftPoints[0].size() == 1) { + selecting = false; + return true; + } + if (pos == BlockPos::MIN) { + auto& points = loftPoints.back(); + if (points.size() == 1) { + loftPoints.pop_back(); } else { - double minDis = DBL_MAX; - size_t pi = 0, pj = 0; - for (size_t endi = loftPoints.size(), i = 0; i < endi; ++i) { - for (size_t endj = loftPoints[i].size(), j = 0; j < endj; ++j) { - auto length = (loftPoints[i][j] - pos).length(); - if (length <= minDis) { - minDis = length; - pi = i; - pj = j; - } + points.pop_back(); + } + } else { + double minDis = DBL_MAX; + size_t pi = 0, pj = 0; + for (size_t endi = loftPoints.size(), i = 0; i < endi; ++i) { + for (size_t endj = loftPoints[i].size(), j = 0; j < endj; ++j) { + auto length = (loftPoints[i][j] - pos).length(); + if (length <= minDis) { + minDis = length; + pi = i; + pj = j; } } - if (loftPoints[pi].size() == 1) { - loftPoints.erase(loftPoints.begin() + pi); - } else { - loftPoints[pi].erase(loftPoints[pi].begin() + pj); - } } - updateBoundingBox(); - return true; + if (loftPoints[pi].size() == 1) { + loftPoints.erase(loftPoints.begin() + pi); + } else { + loftPoints[pi].erase(loftPoints[pi].begin() + pj); + } } + updateBoundingBox(); + return true; +} - void LoftRegion::buildCache() { - if (posCached) { - return; - } - if (!selecting) { - return; - } - if (interpolations.size() == 0) { - return; - } - posCached = true; - posCache.clear(); - double maxCurveLength = 0; +void LoftRegion::buildCache() { + if (posCached) { + return; + } + if (!selecting) { + return; + } + if (interpolations.size() == 0) { + return; + } + posCached = true; + posCache.clear(); + double maxCurveLength = 0; + for (auto& curve : interpolations) { + maxCurveLength = std::max(maxCurveLength, curve.arcLength()); + } + double step = (1.0 / maxCurveLength) / quality; + BoundingBox box(loftPoints[0][0], loftPoints[0][0]); + for (double t = 0; t <= 1.0; t += step) { + std::vector nodes; + nodes.clear(); for (auto& curve : interpolations) { - maxCurveLength = std::max(maxCurveLength, curve.arcLength()); + nodes.push_back(Node(curve.getPosition(t))); } - double step = (1.0 / maxCurveLength) / quality; - BoundingBox box(loftPoints[0][0], loftPoints[0][0]); - for (double t = 0; t <= 1.0; t += step) { - std::vector nodes; - nodes.clear(); - for (auto& curve : interpolations) { - nodes.push_back(Node(curve.getPosition(t))); - } - auto tmpCurve = KochanekBartelsInterpolation(nodes, circle); - auto step2 = (1.0 / tmpCurve.arcLength()) / quality; - for (double t2 = 0; t2 <= 1.0; t2 += step2) { - auto tmpPos = tmpCurve.getPosition(t2).toBlockPos(); - posCache[tmpPos] = std::make_pair(1 - t2, 1 - t); - box = box.merge(tmpPos); - } + auto tmpCurve = KochanekBartelsInterpolation(nodes, circle); + auto step2 = (1.0 / tmpCurve.arcLength()) / quality; + for (double t2 = 0; t2 <= 1.0; t2 += step2) { + auto tmpPos = tmpCurve.getPosition(t2).toBlockPos(); + posCache[tmpPos] = std::make_pair(1 - t2, 1 - t); + box = box.merge(tmpPos); } - boundingBox = box; } + boundingBox = box; +} - BoundingBox LoftRegion::getBoundBox() { - buildCache(); - return boundingBox; - } +BoundingBox LoftRegion::getBoundBox() { + buildCache(); + return boundingBox; +} - void LoftRegion::forEachBlockInRegion(const std::function& todo) { - buildCache(); - for (auto& pos : posCache) { - todo(pos.first); - } +void LoftRegion::forEachBlockInRegion(const std::function& todo) { + buildCache(); + for (auto& pos : posCache) { + todo(pos.first); } +} - void LoftRegion::forEachBlockUVInRegion(const std::function& todo) { - buildCache(); - for (auto& pos : posCache) { - todo(pos.first, pos.second.first, pos.second.second); - } +void LoftRegion::forEachBlockUVInRegion( + const std::function& todo +) { + buildCache(); + for (auto& pos : posCache) { + todo(pos.first, pos.second.first, pos.second.second); } +} - void LoftRegion::forEachBlockInLines(int num, bool isX, const std::function& todo) { - if (!selecting) { - return; - } - if (num < 2) { - return; - } - buildCache(); - if (isX) { - if (loftPoints.size() == 1) { - for (auto& pos : posCache) { - todo(pos.first); - } - return; - } else { - phmap::flat_hash_set posCache2; - for (int i = 0; i < num; ++i) { - std::vector nodes2; - nodes2.clear(); - double t = i / (double)(num - 1); - for (auto& curve : interpolations) { - nodes2.push_back(Node(curve.getPosition(t))); - } - - auto tmpCurve = KochanekBartelsInterpolation(nodes2, circle); - auto step2 = (1.0 / tmpCurve.arcLength()) / quality; - for (double t2 = 0; t2 <= 1.0; t2 += step2) { - auto tmpPos = tmpCurve.getPosition(t2).toBlockPos(); - posCache2.insert(tmpPos); - } - } - for (auto& pos : posCache2) { - todo(pos); - } - return; +void LoftRegion::forEachBlockInLines( + int num, + bool isX, + const std::function& todo +) { + if (!selecting) { + return; + } + if (num < 2) { + return; + } + buildCache(); + if (isX) { + if (loftPoints.size() == 1) { + for (auto& pos : posCache) { + todo(pos.first); } + return; } else { phmap::flat_hash_set posCache2; - for (int i = 0; i < num; ++i) { std::vector nodes2; nodes2.clear(); - double t = i / (double)(num - 1 + circle); - for (size_t endj = cache1.size(), j = 0; j < endj; j += 2) { - auto& curve = cache1[j]; + double t = i / (double)(num - 1); + for (auto& curve : interpolations) { nodes2.push_back(Node(curve.getPosition(t))); } - auto tmpCurve = KochanekBartelsInterpolation(nodes2); - auto step2 = (1.0 / tmpCurve.arcLength()) / quality; + + auto tmpCurve = KochanekBartelsInterpolation(nodes2, circle); + auto step2 = (1.0 / tmpCurve.arcLength()) / quality; for (double t2 = 0; t2 <= 1.0; t2 += step2) { auto tmpPos = tmpCurve.getPosition(t2).toBlockPos(); posCache2.insert(tmpPos); } } - for (auto& pos : posCache2) { todo(pos); } return; } - } + } else { + phmap::flat_hash_set posCache2; - void LoftRegion::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - rendertick = 40; - for (auto& point : loftPoints) { - globalPT().drawCuboid(point[0], dimensionID, mce::ColorPalette::SLATE); - for (size_t endi = point.size(), i = 1; i < endi; ++i) { - globalPT().drawCuboid(point[i], dimensionID, mce::ColorPalette::GREEN); - } - } - for (auto& curve : interpolations) { - drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); - } - for (auto& curve : cache1) { - drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); + for (int i = 0; i < num; ++i) { + std::vector nodes2; + nodes2.clear(); + double t = i / (double)(num - 1 + circle); + for (size_t endj = cache1.size(), j = 0; j < endj; j += 2) { + auto& curve = cache1[j]; + nodes2.push_back(Node(curve.getPosition(t))); } - for (auto& curve : cache2) { - drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); + auto tmpCurve = KochanekBartelsInterpolation(nodes2); + auto step2 = (1.0 / tmpCurve.arcLength()) / quality; + for (double t2 = 0; t2 <= 1.0; t2 += step2) { + auto tmpPos = tmpCurve.getPosition(t2).toBlockPos(); + posCache2.insert(tmpPos); } } - rendertick--; + + for (auto& pos : posCache2) { + todo(pos); + } + return; } +} - bool LoftRegion::setMainPos(const BlockPos& pos, const int& dim) { - if (!selecting) { - dimensionID = dim; - selecting = true; - loftPoints.clear(); - maxPointCount = 1; +void LoftRegion::renderRegion() { + if (selecting && dimensionID >= 0 && rendertick <= 0) { + rendertick = 40; + for (auto& point : loftPoints) { + globalPT().drawCuboid(point[0], dimensionID, mce::ColorPalette::SLATE); + for (size_t endi = point.size(), i = 1; i < endi; ++i) { + globalPT().drawCuboid(point[i], dimensionID, mce::ColorPalette::GREEN); + } + } + for (auto& curve : interpolations) { + drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); } - if (dim != dimensionID) { - return false; + for (auto& curve : cache1) { + drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); } - std::vector point; - point.clear(); - point.push_back(pos); - loftPoints.push_back(point); + for (auto& curve : cache2) { + drawCurve(curve, mce::ColorPalette::YELLOW, dimensionID); + } + } + rendertick--; +} - updateBoundingBox(); - return true; +bool LoftRegion::setMainPos(BlockPos const& pos, int dim) { + if (!selecting) { + dimensionID = dim; + selecting = true; + loftPoints.clear(); + maxPointCount = 1; } - bool LoftRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - return false; - } - (loftPoints.back()).push_back(pos); - maxPointCount = std::max(maxPointCount, (int)(loftPoints.back().size())); + if (dim != dimensionID) { + return false; + } + std::vector point; + point.clear(); + point.push_back(pos); + loftPoints.push_back(point); - updateBoundingBox(); - return true; + updateBoundingBox(); + return true; +} +bool LoftRegion::setVicePos(BlockPos const& pos, int dim) { + if (!selecting || dim != dimensionID) { + return false; } - std::pair LoftRegion::shift(const BlockPos& change) { - for (auto& points : loftPoints) { - for (auto& point : points) { - point += change; - } + (loftPoints.back()).push_back(pos); + maxPointCount = std::max(maxPointCount, (int)(loftPoints.back().size())); + + updateBoundingBox(); + return true; +} +bool LoftRegion::shift(BlockPos const& change) { + for (auto& points : loftPoints) { + for (auto& point : points) { + point += change; } - updateBoundingBox(); - return {"worldedit.shift.shifted", true}; } + updateBoundingBox(); + return {"worldedit.shift.shifted", true}; +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/region/LoftRegion.h b/old/core/region/LoftRegion.h index e00b3e9..47c3b75 100644 --- a/old/core/region/LoftRegion.h +++ b/old/core/region/LoftRegion.h @@ -1,63 +1,65 @@ -// -// Created by OEOTYAN on 2022/06/18. -// #pragma once -#include "Globals.h" #include "Region.h" -#include "eval/Bresenham.hpp" +#include "math/Bresenham.h" -namespace worldedit { +namespace we { - class LoftRegion final : public Region { - public: - std::vector> loftPoints; - int maxPointCount = 1; - std::vector interpolations; - std::vector cache1; - std::vector cache2; - phmap::flat_hash_map> posCache; - bool circle = false; - static const int quality = 16; - bool posCached = false; +class LoftRegion : public Region { +public: + std::vector> loftPoints; + int maxPointCount = 1; + std::vector interpolations; + std::vector cache1; + std::vector cache2; + phmap::flat_hash_map> posCache; + bool circle = false; + static const int quality = 16; + bool posCached = false; - std::string getName() override { return "loft"; } + void updateBoundingBox() override; - void updateBoundingBox() override; + LoftRegion(const BoundingBox& region, int dim); - explicit LoftRegion(const BoundingBox& region, const int& dim); + BoundingBox getBoundBox() override; - BoundingBox getBoundBox() override; + bool shift(BlockPos const& change) override; - std::pair shift(const BlockPos& change) override; - - void setCircle(bool value) { - circle = value; - updateBoundingBox(); - }; + void setCircle(bool value) { + circle = value; + updateBoundingBox(); + }; - void buildCache(); + void buildCache(); - uint64_t size() const override { - auto bSize = boundingBox.max - boundingBox.min + 1; - return std::max(std::max((uint64_t)bSize.x * bSize.z, (uint64_t)bSize.x * bSize.y), - (uint64_t)bSize.y * bSize.z); - } + uint64_t size() const override { + auto bSize = boundingBox.max - boundingBox.min + 1; + return std::max( + std::max((uint64_t)bSize.x * bSize.z, (uint64_t)bSize.x * bSize.y), + (uint64_t)bSize.y * bSize.z + ); + } - bool removePoint(int dim, const BlockPos& pos = BlockPos::MIN) override; + bool removePoint(int dim, BlockPos const& pos = BlockPos::MIN) override; - void forEachBlockInRegion(const std::function& todo) override; + void forEachBlockInRegion(const std::function& todo) override; - void forEachBlockUVInRegion(const std::function& todo) override; + void forEachBlockUVInRegion( + const std::function& todo + ) override; - void forEachBlockInLines(int num, bool isX, const std::function& todo); + void forEachBlockInLines( + int num, + bool isX, + const std::function& todo + ); - void renderRegion() override; + void renderRegion() override; - bool setMainPos(const BlockPos& pos, const int& dim) override; + bool setMainPos(BlockPos const& pos, int dim) override; - bool setVicePos(const BlockPos& pos, const int& dim) override; + bool setVicePos(BlockPos const& pos, int dim) override; - bool contains(const BlockPos& pos); - }; -} // namespace worldedit + bool contains(BlockPos const& pos); +}; +} // namespace we diff --git a/old/core/region/PolyRegion.cpp b/old/core/region/PolyRegion.cpp index efdff97..d9c8be8 100644 --- a/old/core/region/PolyRegion.cpp +++ b/old/core/region/PolyRegion.cpp @@ -1,227 +1,250 @@ -// -// Created by OEOTYAN on 2021/2/8. -// #include "PolyRegion.h" -#include "mc/Level.hpp" #include "mc/Dimension.hpp" -namespace worldedit { - void PolyRegion::updateBoundingBox() { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - minY = std::max(minY, static_cast(range.min)); - maxY = std::min(maxY, static_cast(range.max) - 1); - boundingBox.min.y = minY; - boundingBox.max.y = maxY; - boundingBox.min.x = points[0].x; - boundingBox.min.z = points[0].z; - boundingBox.max.x = points[0].x; - boundingBox.max.z = points[0].z; - for (auto& point : points) { - boundingBox.min.x = std::min(boundingBox.min.x, point.x); - boundingBox.min.z = std::min(boundingBox.min.z, point.z); - boundingBox.max.x = std::max(boundingBox.max.x, point.x); - boundingBox.max.z = std::max(boundingBox.max.z, point.z); - } +#include "mc/Level.hpp" +namespace we { +void PolyRegion::updateBoundingBox() { + auto range = reinterpret_cast( + Global->getDimension(dimensionID).mHandle.lock().get() + ) + ->getHeightRange(); + rendertick = 0; + minY = std::max(minY, static_cast(range.min)); + maxY = std::min(maxY, static_cast(range.max) - 1); + boundingBox.min.y = minY; + boundingBox.max.y = maxY; + boundingBox.min.x = points[0].x; + boundingBox.min.z = points[0].z; + boundingBox.max.x = points[0].x; + boundingBox.max.z = points[0].z; + for (auto& point : points) { + boundingBox.min.x = std::min(boundingBox.min.x, point.x); + boundingBox.min.z = std::min(boundingBox.min.z, point.z); + boundingBox.max.x = std::max(boundingBox.max.x, point.x); + boundingBox.max.z = std::max(boundingBox.max.z, point.z); } +} - void PolyRegion::forEachBlockUVInRegion(const std::function& todo) { - auto faceNum = points.size() - 1; - for (int i = 0; i < faceNum; ++i) { - auto pos0 = points[i]; - auto pos1 = points[i + 1]; - int x0 = pos0.x; - int z0 = pos0.z; - int x1 = pos1.x; - int z1 = pos1.z; - int dx = abs(x1 - x0); - int dz = abs(z1 - z0); - int sx = x0 < x1 ? 1 : -1; - int sz = z0 < z1 ? 1 : -1; +void PolyRegion::forEachBlockUVInRegion( + const std::function& todo +) { + auto faceNum = points.size() - 1; + for (int i = 0; i < faceNum; ++i) { + auto pos0 = points[i]; + auto pos1 = points[i + 1]; + int x0 = pos0.x; + int z0 = pos0.z; + int x1 = pos1.x; + int z1 = pos1.z; + int dx = abs(x1 - x0); + int dz = abs(z1 - z0); + int sx = x0 < x1 ? 1 : -1; + int sz = z0 < z1 ? 1 : -1; - int dMax = std::max(dx, dz); - if (dMax == dx) { - for (int domstep = 0; domstep <= dx; domstep++) { - int tipx = x0 + domstep * sx; - int tipz = (int)round(z0 + domstep / ((double)dx) * ((double)dz) * sz); - for (int y = minY; y <= maxY; ++y) { - todo(BlockPos(tipx, y, tipz), (i + (static_cast(domstep) / dx)) / faceNum, - static_cast(y - minY) / (maxY - minY)); - } + int dMax = std::max(dx, dz); + if (dMax == dx) { + for (int domstep = 0; domstep <= dx; domstep++) { + int tipx = x0 + domstep * sx; + int tipz = (int)round(z0 + domstep / ((double)dx) * ((double)dz) * sz); + for (int y = minY; y <= maxY; ++y) { + todo( + BlockPos(tipx, y, tipz), + (i + (static_cast(domstep) / dx)) / faceNum, + static_cast(y - minY) / (maxY - minY) + ); } - } else { - for (int domstep = 0; domstep <= dz; domstep++) { - int tipx = (int)round(x0 + domstep / ((double)dz) * ((double)dx) * sx); - int tipz = z0 + domstep * sz; - for (int y = minY; y <= maxY; ++y) { - todo(BlockPos(tipx, y, tipz), (i + (static_cast(domstep) / dz)) / faceNum, - static_cast(y - minY) / (maxY - minY)); - } + } + } else { + for (int domstep = 0; domstep <= dz; domstep++) { + int tipx = (int)round(x0 + domstep / ((double)dz) * ((double)dx) * sx); + int tipz = z0 + domstep * sz; + for (int y = minY; y <= maxY; ++y) { + todo( + BlockPos(tipx, y, tipz), + (i + (static_cast(domstep) / dz)) / faceNum, + static_cast(y - minY) / (maxY - minY) + ); } } } } +} - PolyRegion::PolyRegion(const BoundingBox& region, const int& dim) : Region(region, dim) { - points.clear(); - regionType = POLY; +PolyRegion::PolyRegion(const BoundingBox& region, int dim) : Region(region, dim) { + points.clear(); + regionType = POLY; +} +bool PolyRegion::setMainPos(BlockPos const& pos, int dim) { + mainPos = pos; + dimensionID = dim; + selecting = 1; + minY = pos.y; + maxY = pos.y; + points.clear(); + points.push_back({pos.x, 0, pos.z}); + updateBoundingBox(); + return true; +} +bool PolyRegion::setVicePos(BlockPos const& pos, int dim) { + if (!selecting || dim != dimensionID) { + return false; } - bool PolyRegion::setMainPos(const BlockPos& pos, const int& dim) { - mainPos = pos; - dimensionID = dim; - selecting = 1; - minY = pos.y; - maxY = pos.y; - points.clear(); - points.push_back({pos.x, 0, pos.z}); - updateBoundingBox(); - return true; - } - bool PolyRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - return false; - } - for (auto iter = points.cbegin(); iter != points.cend(); iter++) { - if (*iter == BlockPos(pos.x, 0, pos.z)) { - minY = std::min(minY, pos.y); - maxY = std::max(maxY, pos.y); - updateBoundingBox(); - return true; - } + for (auto iter = points.cbegin(); iter != points.cend(); iter++) { + if (*iter == BlockPos(pos.x, 0, pos.z)) { + minY = std::min(minY, pos.y); + maxY = std::max(maxY, pos.y); + updateBoundingBox(); + return true; } - minY = std::min(minY, pos.y); - maxY = std::max(maxY, pos.y); - points.push_back({pos.x, 0, pos.z}); - updateBoundingBox(); - return true; } - std::pair PolyRegion::expand(const std::vector& changes) { - for (BlockPos change : changes) { - if (change.x != 0 || change.z != 0) { - return {"worldedit.selection.expand.poly.error", false}; - } + minY = std::min(minY, pos.y); + maxY = std::max(maxY, pos.y); + points.push_back({pos.x, 0, pos.z}); + updateBoundingBox(); + return true; +} +bool PolyRegion::expand(const std::vector& changes) { + for (BlockPos change : changes) { + if (change.x != 0 || change.z != 0) { + return {"worldedit.selection.expand.poly.error", false}; } - for (BlockPos change : changes) { - int changeY = change.y; - if (changeY > 0) { - maxY += changeY; - } else { - minY += changeY; - } + } + for (BlockPos change : changes) { + int changeY = change.y; + if (changeY > 0) { + maxY += changeY; + } else { + minY += changeY; } - updateBoundingBox(); - - return {"worldedit.expand.expanded", true}; } + updateBoundingBox(); - std::pair PolyRegion::contract(const std::vector& changes) { - for (BlockPos change : changes) { - if (change.x != 0 || change.z != 0) { - return {"worldedit.selection.contract.poly.error", false}; - } + return {"worldedit.expand.expanded", true}; +} + +bool PolyRegion::contract(const std::vector& changes) { + for (BlockPos change : changes) { + if (change.x != 0 || change.z != 0) { + return {"worldedit.selection.contract.poly.error", false}; } - for (BlockPos change : changes) { - int changeY = change.y; - if (changeY > 0) { - minY += changeY; - } else { - maxY += changeY; - } + } + for (BlockPos change : changes) { + int changeY = change.y; + if (changeY > 0) { + minY += changeY; + } else { + maxY += changeY; } - updateBoundingBox(); - return {"worldedit.contract.contracted", true}; } + updateBoundingBox(); + return {"worldedit.contract.contracted", true}; +} - std::pair PolyRegion::shift(const BlockPos& change) { - minY += change.y; - maxY += change.y; - mainPos = mainPos + change; - for (auto& point : points) { - point.x += change.x; - point.z += change.z; - } - updateBoundingBox(); - return {"worldedit.shift.shifted", true}; +bool PolyRegion::shift(BlockPos const& change) { + minY += change.y; + maxY += change.y; + mainPos = mainPos + change; + for (auto& point : points) { + point.x += change.x; + point.z += change.z; } + updateBoundingBox(); + return {"worldedit.shift.shifted", true}; +} - uint64_t PolyRegion::size() const { - uint64_t area = 0; - auto j = points.size() - 1; - for (int i = 0; i <= j; ++i) { - int x = points[j].x + points[i].x; - int z = points[j].z - points[i].z; - area += x * z; - j = i; - } +uint64_t PolyRegion::size() const { + uint64_t area = 0; + auto j = points.size() - 1; + for (int i = 0; i <= j; ++i) { + int x = points[j].x + points[i].x; + int z = points[j].z - points[i].z; + area += x * z; + j = i; + } - return (uint64_t)std::floor(std::abs((double)area * 0.5)) * (maxY - minY + 1); - }; + return (uint64_t)std::floor(std::abs((double)area * 0.5)) * (maxY - minY + 1); +}; - void PolyRegion::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - rendertick = 40; - auto size = points.size(); - for (int i = 0; i < size; ++i) { - globalPT().drawCuboid( - AABB(Vec3(points[i].x, minY, points[i].z), Vec3(points[i].x, maxY, points[i].z) + Vec3::ONE), - dimensionID, mce::ColorPalette::YELLOW); - } - for (int y : {minY, maxY}) { - for (int i = 0; i < size - 1; ++i) { - globalPT().drawOrientedLine(BlockPos(points[i].x, y, points[i].z), - BlockPos(points[i + 1].x, y, points[i + 1].z), dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - } - globalPT().drawOrientedLine(BlockPos(points[0].x, y, points[0].z), - BlockPos(points[size - 1].x, y, points[size - 1].z), dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); +void PolyRegion::renderRegion() { + if (selecting && dimensionID >= 0 && rendertick <= 0) { + rendertick = 40; + auto size = points.size(); + for (int i = 0; i < size; ++i) { + globalPT().drawCuboid( + AABB( + Vec3(points[i].x, minY, points[i].z), + Vec3(points[i].x, maxY, points[i].z) + Vec3::ONE + ), + dimensionID, + mce::ColorPalette::YELLOW + ); + } + for (int y : {minY, maxY}) { + for (int i = 0; i < size - 1; ++i) { + globalPT().drawOrientedLine( + BlockPos(points[i].x, y, points[i].z), + BlockPos(points[i + 1].x, y, points[i + 1].z), + dimensionID, + ParticleCUI::PointSize::PX4, + 1, + 64, + mce::ColorPalette::YELLOW + ); } + globalPT().drawOrientedLine( + BlockPos(points[0].x, y, points[0].z), + BlockPos(points[size - 1].x, y, points[size - 1].z), + dimensionID, + ParticleCUI::PointSize::PX4, + 1, + 64, + mce::ColorPalette::YELLOW + ); } - rendertick--; - }; + } + rendertick--; +}; - bool PolyRegion::contains(const BlockPos& pos) { - if (points.size() < 3 || pos.y < minY || pos.y > maxY) { - return false; - } - bool inside = false; - int x1; - int z1; - int x2; - int z2; - long long crossproduct; - BlockPos point = points.back(); +bool PolyRegion::contains(BlockPos const& pos) { + if (points.size() < 3 || pos.y < minY || pos.y > maxY) { + return false; + } + bool inside = false; + int x1; + int z1; + int x2; + int z2; + long long crossproduct; + BlockPos point = points.back(); - for (auto iter = points.cbegin(); iter != points.cend(); iter++) { - auto value = *iter; - if (value == BlockPos(pos.x, 0, pos.z)) - return true; - if (value.x > point.x) { - x1 = point.x; - x2 = value.x; - z1 = point.z; - z2 = value.z; - } else { - x1 = value.x; - x2 = point.x; - z1 = value.z; - z2 = point.z; - } - if (x1 <= pos.x && pos.x <= x2) { - crossproduct = ((long long)pos.z - (long long)z1) * (long long)(x2 - x1) - - ((long long)z2 - (long long)z1) * (long long)(pos.x - x1); - if (crossproduct == 0) { - if ((z1 <= pos.z) == (pos.z <= z2)) { - return true; - } - } else if (crossproduct < 0 && (x1 != pos.x)) { - inside = !inside; + for (auto iter = points.cbegin(); iter != points.cend(); iter++) { + auto value = *iter; + if (value == BlockPos(pos.x, 0, pos.z)) return true; + if (value.x > point.x) { + x1 = point.x; + x2 = value.x; + z1 = point.z; + z2 = value.z; + } else { + x1 = value.x; + x2 = point.x; + z1 = value.z; + z2 = point.z; + } + if (x1 <= pos.x && pos.x <= x2) { + crossproduct = ((long long)pos.z - (long long)z1) * (long long)(x2 - x1) + - ((long long)z2 - (long long)z1) * (long long)(pos.x - x1); + if (crossproduct == 0) { + if ((z1 <= pos.z) == (pos.z <= z2)) { + return true; } + } else if (crossproduct < 0 && (x1 != pos.x)) { + inside = !inside; } - point.x = value.x; - point.z = value.z; } - return inside; + point.x = value.x; + point.z = value.z; } -} // namespace worldedit \ No newline at end of file + return inside; +} +} // namespace we \ No newline at end of file diff --git a/old/core/region/PolyRegion.h b/old/core/region/PolyRegion.h index a6c5bca..a018b48 100644 --- a/old/core/region/PolyRegion.h +++ b/old/core/region/PolyRegion.h @@ -1,50 +1,49 @@ -// -// Created by OEOTYAN on 2021/2/8. -// #pragma once -#include "Globals.h" #include "Region.h" -namespace worldedit { - class PolyRegion final : public Region { - public: - std::vector points; - int minY = -2100000000; - int maxY = -2100000000; - BlockPos mainPos{-2100000000, -2100000000, -2100000000}; +namespace we { +class PolyRegion : public Region { +public: + std::vector points; + int minY = -2100000000; + int maxY = -2100000000; + BlockPos mainPos{-2100000000, -2100000000, -2100000000}; - std::string getName() override { return "poly"; } + void updateBoundingBox() override; - void updateBoundingBox() override; + PolyRegion(const BoundingBox& region, int dim); - explicit PolyRegion(const BoundingBox& region, const int& dim); + bool expand(std::span) override; - std::pair expand(const std::vector& changes) override; + bool contract(std::span) override; - std::pair contract(const std::vector& changes) override; + bool shift(std::span) override; - std::pair shift(const BlockPos& change) override; + uint64_t size() const override; - uint64_t size() const override; + void renderRegion() override; - void renderRegion() override; + void forEachBlockUVInRegion( + const std::function& todo + ) override; - void forEachBlockUVInRegion(const std::function& todo) override; - - Vec3 getCenter() const override { - BlockPos tmp(0, 0, 0); - for (auto& point : points) { - tmp = tmp + point; - } - auto size = points.size(); - return Vec3(static_cast(tmp.x) / size + 0.5, static_cast(maxY + minY) * 0.5 + 0.5, - static_cast(tmp.z) / size + 0.5); - }; + Vec3 getCenter() const override { + BlockPos tmp(0, 0, 0); + for (auto& point : points) { + tmp = tmp + point; + } + auto size = points.size(); + return Vec3( + static_cast(tmp.x) / size + 0.5, + static_cast(maxY + minY) * 0.5 + 0.5, + static_cast(tmp.z) / size + 0.5 + ); + }; - bool setMainPos(const BlockPos& pos, const int& dim) override; + bool setMainPos(BlockPos const& pos, int dim) override; - bool setVicePos(const BlockPos& pos, const int& dim) override; + bool setVicePos(BlockPos const& pos, int dim) override; - bool contains(const BlockPos& pos) override; - }; -} // namespace worldedit + bool contains(BlockPos const& pos) override; +}; +} // namespace we diff --git a/old/core/region/Region.cpp b/old/core/region/Region.cpp deleted file mode 100644 index 468c3de..0000000 --- a/old/core/region/Region.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "Regions.h" -#include "mc/Level.hpp" -#include "mc/BlockSource.hpp" -#include "mc/Block.hpp" -#include -#include -#include "eval/Eval.h" -#include "WorldEdit.h" -namespace worldedit { - void Region::forEachBlockInRegion(const std::function& todo) { - for (int y = boundingBox.min.y; y <= boundingBox.max.y; ++y) - for (int x = boundingBox.min.x; x <= boundingBox.max.x; ++x) - for (int z = boundingBox.min.z; z <= boundingBox.max.z; ++z) { - if (contains({x, y, z})) { - todo({x, y, z}); - } - } - } - void Region::forEachBlockUVInRegion(const std::function& todo) { - auto size = boundingBox.max - boundingBox.min + 1; - - if (size.x == 1) { - for (int y = boundingBox.min.y; y <= boundingBox.max.y; ++y) - for (int z = boundingBox.min.z; z <= boundingBox.max.z; ++z) { - BlockPos pos(boundingBox.max.x, y, z); - if (contains(pos)) { - auto localPos = pos - boundingBox.min; - todo(pos, (localPos.z + 0.5) / size.z, (localPos.y + 0.5) / size.y); - } - } - } else if (size.z == 1) { - for (int y = boundingBox.min.y; y <= boundingBox.max.y; ++y) - for (int x = boundingBox.min.x; x <= boundingBox.max.x; ++x) { - BlockPos pos(x, y, boundingBox.max.z); - if (contains(pos)) { - auto localPos = pos - boundingBox.min; - todo(pos, (localPos.x + 0.5) / size.x, (localPos.y + 0.5) / size.y); - } - } - } else { - for (int z = boundingBox.min.z; z <= boundingBox.max.z; ++z) - for (int x = boundingBox.min.x; x <= boundingBox.max.x; ++x) { - BlockPos pos(x, boundingBox.max.y, z); - if (contains(pos)) { - auto localPos = pos - boundingBox.min; - todo(pos, (localPos.x + 0.5) / size.x, (localPos.z + 0.5) / size.z); - } - } - } - } - void Region::forTopBlockInRegion(const std::function& todo) { - auto blockSource = Level::getBlockSource(dimensionID); - for (int x = boundingBox.min.x; x <= boundingBox.max.x; ++x) - for (int z = boundingBox.min.z; z <= boundingBox.max.z; ++z) { - auto topy = blockSource->getHeightmap(x, z); - if (topy < boundingBox.max.y) { - for (int y = std::max(static_cast(topy), boundingBox.min.y + 1); y <= boundingBox.max.y; ++y) { - if (&blockSource->getBlock({x, y, z}) == BedrockBlocks::mAir && - &blockSource->getBlock({x, y - 1, z}) != BedrockBlocks::mAir && contains({x, y, z})) { - todo({x, y, z}); - break; - } - } - } else { - for (int y = boundingBox.max.y; y >= boundingBox.min.y + 1; y--) { - if (&blockSource->getBlock({x, y, z}) == BedrockBlocks::mAir && - &blockSource->getBlock({x, y - 1, z}) != BedrockBlocks::mAir && contains({x, y, z})) { - todo({x, y, z}); - break; - } - } - } - } - } - - int Region::getHeighest(int x, int z) { - for (int y = boundingBox.max.y; y >= boundingBox.min.y; y--) { - if (contains({x, y, z})) { - return y; - } - } - return boundingBox.min.y - 1; - } - - std::vector Region::getHeightMap(std::string mask) { - int sizex = boundingBox.max.x - boundingBox.min.x + 1; - int sizez = boundingBox.max.z - boundingBox.min.z + 1; - std::vector res(sizex * sizez, -1e200); - - auto blockSource = Level::getBlockSource(dimensionID); - for (int x = boundingBox.min.x; x <= boundingBox.max.x; ++x) - for (int z = boundingBox.min.z; z <= boundingBox.max.z; ++z) { - auto topy = getHighestTerrainBlock(blockSource, x, z, boundingBox.min.y, getHeighest(x, z), mask); - if (topy >= boundingBox.min.y) { - int cx = x - boundingBox.min.x; - int cz = z - boundingBox.min.z; - res[cx * sizez + cz] = topy + 0.5; - } - } - return res; - } - - void Region::applyHeightMap(const std::vector& data, std::string xuid, std::string mask) { - auto& playerData = getPlayersData(xuid); - auto* player = Global->getPlayer(xuid); - int sizex = boundingBox.max.x - boundingBox.min.x + 1; - int sizez = boundingBox.max.z - boundingBox.min.z + 1; - auto blockSource = Level::getBlockSource(dimensionID); - EvalFunctions f; - f.setbs(blockSource); - f.setbox(boundingBox); - phmap::flat_hash_map variables; - playerData.setVarByPlayer(variables); - auto playerPos = player->getPosition(); - Vec3 center = boundingBox.getCenter().toVec3(); - for (int posx = boundingBox.min.x; posx <= boundingBox.max.x; posx++) - for (int posz = boundingBox.min.z; posz <= boundingBox.max.z; posz++) { - auto topy = getHighestTerrainBlock(blockSource, posx, posz, boundingBox.min.y, - getHeighest(posx, posz) + 1, mask); - BlockPos pos = {posx, topy, posz}; - if (!contains(pos)) { - continue; - } - int x = pos.x - boundingBox.min.x; - int z = pos.z - boundingBox.min.z; - int index = x * sizez + z; - - if (data[index] < -1e150) { - return; - } - - int curHeight = pos.y; - int newHeight = std::min(boundingBox.max.y, static_cast(floor(data[index]))); - int xr = pos.x; - int zr = pos.z; - double scale = static_cast(curHeight - boundingBox.min.y) / - static_cast(newHeight - boundingBox.min.y); - - if (newHeight > curHeight) { - auto* top = &blockSource->getBlock({xr, curHeight, zr}); - - pos = {xr, newHeight, zr}; - - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple(blockSource, f, variables, pos, top); - - for (int y = newHeight - 1 - boundingBox.min.y; y >= 0; y--) { - int copyFrom = static_cast(floor(y * scale)); - pos = {xr, boundingBox.min.y + y, zr}; - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple( - blockSource, f, variables, pos, - &blockSource->getBlock({xr, boundingBox.min.y + copyFrom, zr})); - } - } else if (curHeight > newHeight) { - for (int y = 0; y < newHeight - boundingBox.min.y; ++y) { - int copyFrom = static_cast(floor(y * scale)); - pos = {xr, boundingBox.min.y + y, zr}; - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple( - blockSource, f, variables, pos, - &blockSource->getBlock({xr, boundingBox.min.y + copyFrom, zr})); - } - - pos = {xr, newHeight, zr}; - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple(blockSource, f, variables, pos, - &blockSource->getBlock({xr, curHeight, zr})); - - for (int y = newHeight + 1; y <= curHeight; ++y) { - pos = {xr, y, zr}; - setFunction(variables, f, boundingBox, playerPos, pos, center); - playerData.setBlockSimple(blockSource, f, variables, pos); - } - } - }; - } - - void Region::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - globalPT().drawCuboid(getBoundBox(), dimensionID, mce::ColorPalette::YELLOW); - rendertick = 40; - } - rendertick--; - }; - - Region::Region(const BoundingBox& b, int dim) : boundingBox(b), dimensionID(dim) {} - - std::unique_ptr Region::createRegion(RegionType type, const BoundingBox& box, int dim) { - switch (type) { - case CUBOID: - return std::make_unique(CuboidRegion(box, dim)); - case EXPAND: - return std::make_unique(ExpandRegion(box, dim)); - case SPHERE: - return std::make_unique(SphereRegion(box, dim)); - case POLY: - return std::make_unique(PolyRegion(box, dim)); - case CONVEX: - return std::make_unique(ConvexRegion(box, dim)); - case CYLINDER: - return std::make_unique(CylinderRegion(box, dim)); - case LOFT: - return std::make_unique(LoftRegion(box, dim)); - default: - return std::make_unique(CuboidRegion(box, dim)); - } - } -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/Region.h b/old/core/region/Region.h deleted file mode 100644 index 7783c7b..0000000 --- a/old/core/region/Region.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#pragma once -#include "Globals.h" -#include "particle/Graphics.h" - -namespace worldedit { - inline AABB toRealAABB(const BoundingBox& bound) { - return {{bound.min.x, bound.min.y, bound.min.z}, {bound.max.x + 1, bound.max.y + 1, bound.max.z + 1}}; - } - - enum RegionType { - CUBOID = 0, - EXPAND = 1, - SPHERE = 2, - POLY = 3, - CONVEX = 4, - CYLINDER = 5, - LOFT = 6, - }; - - class Region { - protected: - int rendertick = 0; - int dimensionID = -1; - BoundingBox boundingBox; - - public: - RegionType regionType = CUBOID; - bool selecting = false; - bool needResetVice = true; - explicit Region(const BoundingBox& b, int dim); - - virtual std::string getName() { return "null"; } - virtual BoundingBox getBoundBox() { return boundingBox; } - RegionType getRegionType() const { return regionType; } - int getDimensionID() const { return dimensionID; } - - virtual ~Region() = default; - - virtual void updateBoundingBox() = 0; - - virtual uint64_t size() const { - return (uint64_t)(boundingBox.max.x - boundingBox.min.x + 1) * (boundingBox.max.y - boundingBox.min.y + 1) * - (boundingBox.max.z - boundingBox.min.z + 1); - }; - - virtual std::pair expand(const std::vector& changes) { - return {"worldedit.selection.expand.error", false}; - }; - - virtual std::pair contract(const std::vector& changes) { - return {"worldedit.selection.contract.error", false}; - }; - virtual std::pair shift(const BlockPos& change) { - return {"worldedit.selection.shift.error", false}; - }; - - virtual Vec3 getCenter() const { return toRealAABB(boundingBox).getCenter(); }; - - virtual bool setMainPos(const BlockPos& pos, const int& dim) { return false; }; - - virtual bool setVicePos(const BlockPos& pos, const int& dim) { return false; }; - - virtual bool contains(const BlockPos& pos) { return pos.containedWithin(boundingBox.min, boundingBox.max); }; - - virtual void forEachBlockInRegion(const std::function& todo); - - virtual void forEachBlockUVInRegion(const std::function& todo); - - virtual void forTopBlockInRegion(const std::function& todo); - - virtual void forEachLine(const std::function& todo){}; - - virtual std::vector getHeightMap(std::string mask = ""); - - virtual bool removePoint(int dim, const BlockPos& pos = BlockPos::MIN) { return false; }; - - virtual void applyHeightMap(const std::vector& data, std::string xuid, std::string mask = ""); - - virtual void renderRegion(); - - int getHeighest(int x, int z); - - inline bool hasSelected() { return selecting; } - - static std::unique_ptr createRegion(RegionType type, - const BoundingBox& box = BoundingBox(), - int dim = -1); - }; -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/Regions.h b/old/core/region/Regions.h index a7ef23b..0316fd4 100644 --- a/old/core/region/Regions.h +++ b/old/core/region/Regions.h @@ -1,14 +1,11 @@ -// -// Created by OEOTYAN on 2021/2/8. -// #pragma once -#include "Region.h" +#include "ConvexRegion.h" #include "CuboidRegion.h" -#include "ExpandRegion.h" -#include "SphereRegion.h" #include "CylinderRegion.h" +#include "ExpandRegion.h" +#include "LoftRegion.h" #include "PolyRegion.h" -#include "ConvexRegion.h" -#include "LoftRegion.h" \ No newline at end of file +#include "Region.h" +#include "SphereRegion.h" diff --git a/old/core/region/SphereRegion.cpp b/old/core/region/SphereRegion.cpp deleted file mode 100644 index 8ff5be8..0000000 --- a/old/core/region/SphereRegion.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "SphereRegion.h" -#include "mc/Level.hpp" -#include "eval/Eval.h" -#include "mc/Dimension.hpp" -namespace worldedit { - void SphereRegion::updateBoundingBox() { - auto range = reinterpret_cast(Global->getDimension(dimensionID).mHandle.lock().get()) - ->getHeightRange(); - rendertick = 0; - auto newRadius = (int)(ceil(radius)); - boundingBox.min.x = center.x - newRadius; - boundingBox.min.y = std::max(center.y - newRadius, static_cast(range.min)); - boundingBox.min.z = center.z - newRadius; - boundingBox.max.x = center.x + newRadius; - boundingBox.max.y = std::min(center.y + newRadius, static_cast(range.max) - 1); - boundingBox.max.z = center.z + newRadius; - } - - void SphereRegion::forEachBlockUVInRegion(const std::function& todo) { - forEachBlockInRegion([&](const BlockPos& pos) { - int counts = 0; - for (auto& calPos : pos.getNeighbors()) { - counts += contains(calPos); - } - if (counts < 6) { - double y = (pos.y - center.y) / radius; - if (abs(y) > 0.8) { - todo(pos, (atan2(pos.z - center.z, pos.x - center.x) + M_PI) / (M_PI * 2), - acos(clamp(-sign(y) * - sqrt(std::max(0.0, pow2(radius) - pow2(static_cast(pos.z) - center.z) - - pow2(static_cast(pos.x) - center.x))) / - radius, - -1.0, 1.0)) * - M_1_PI); - } else { - todo(pos, (atan2(pos.z - center.z, pos.x - center.x) + M_PI) / (M_PI * 2), acos(-y) * M_1_PI); - } - } - }); - } - - bool SphereRegion::setMainPos(const BlockPos& pos, const int& dim) { - selecting = true; - dimensionID = dim; - center = pos; - radius = 0.5; - updateBoundingBox(); - return true; - } - - bool SphereRegion::setVicePos(const BlockPos& pos, const int& dim) { - if (!selecting || dim != dimensionID) { - return false; - } - auto dis = pos.distanceTo(center); - if (dis > radius) { - radius = dis + 0.5f; - updateBoundingBox(); - return true; - } - return false; - } - - int SphereRegion::checkChanges(const std::vector& changes) { - int x = 0, y = 0, z = 0; - for (auto change : changes) { - x += abs(change.x); - y += abs(change.y); - z += abs(change.z); - } - if (x == y && y == z) { - return x / 2; - } - return -1; - } - - std::pair SphereRegion::expand(const std::vector& changes) { - int check = checkChanges(changes); - if (check == -1) { - return {"worldedit.selection.expand.sphere.error", false}; - } else { - radius += check; - updateBoundingBox(); - } - - return {"worldedit.expand.expanded", true}; - } - - std::pair SphereRegion::contract(const std::vector& changes) { - int check = checkChanges(changes); - if (check == -1) { - return {"worldedit.selection.contract.sphere.error", false}; - } else { - radius -= check; - radius = std::max(radius, 0.5); - } - updateBoundingBox(); - return {"worldedit.contract.contracted", true}; - } - - std::pair SphereRegion::shift(const BlockPos& change) { - center = center + change; - updateBoundingBox(); - return {"worldedit.shift.shifted", true}; - } - - bool SphereRegion::contains(const BlockPos& pos) { - return pos.distanceTo(center) <= radius; - } - - SphereRegion::SphereRegion(const BoundingBox& region, const int& dim) : Region(region, dim) { - selecting = false; - regionType = SPHERE; - } - void SphereRegion::renderRegion() { - if (selecting && dimensionID >= 0 && rendertick <= 0) { - rendertick = 40; - globalPT().drawCuboid(AABB(center.toVec3(), center.toVec3() + Vec3::ONE), dimensionID, - mce::ColorPalette::GREEN); - if (radius > 1.0f) { - globalPT().drawCircle(center, ParticleCUI::Direction::POS_Y, radius, dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - globalPT().drawCircle(center, ParticleCUI::Direction::POS_Z, radius, dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - globalPT().drawCircle(center, ParticleCUI::Direction::POS_X, radius, dimensionID, - ParticleCUI::PointSize::PX4, 1, 64, mce::ColorPalette::YELLOW); - } - } - rendertick--; - }; -} // namespace worldedit \ No newline at end of file diff --git a/old/core/region/SphereRegion.h b/old/core/region/SphereRegion.h deleted file mode 100644 index 14b8e82..0000000 --- a/old/core/region/SphereRegion.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Created by OEOTYAN on 2021/2/8. -// - -#include "Globals.h" -#include "Region.h" - -namespace worldedit { - class SphereRegion final : public Region { - private: - BlockPos center = BlockPos::MIN; - double radius = 0.5; - int checkChanges(const std::vector& changes); - - public: - void updateBoundingBox() override; - - std::string getName() override { return "sphere"; } - - explicit SphereRegion(const BoundingBox& region, const int& dim); - - std::pair expand(const std::vector& changes) override; - - std::pair contract(const std::vector& changes) override; - - std::pair shift(const BlockPos& change) override; - - Vec3 getCenter() const override { return center.toVec3() + 0.5f; }; - - uint64_t size() const override { return (uint64_t)std::round(4.0 / 3.0 * M_PI * radius * radius * radius); }; - - void forEachBlockUVInRegion(const std::function& todo) override; - - void renderRegion() override; - - double getRadius() const { return radius; }; - - bool setMainPos(const BlockPos& pos, const int& dim) override; - - bool setVicePos(const BlockPos& pos, const int& dim) override; - - bool contains(const BlockPos& pos) override; - }; -} // namespace worldedit \ No newline at end of file diff --git a/old/core/store/BlockListPattern.cpp b/old/core/store/BlockListPattern.cpp index 2cf81d8..bb9e1d8 100644 --- a/old/core/store/BlockListPattern.cpp +++ b/old/core/store/BlockListPattern.cpp @@ -1,337 +1,379 @@ -// -// Created by OEOTYAN on 2023/02/02. -// +#include "BlockListPattern.h" #include "BlockNBTSet.hpp" +#include "WorldEdit.h" #include "mc/BlockPalette.hpp" -#include +#include "mc/ItemStack.hpp" #include "mc/Level.hpp" +#include "mc/Player.hpp" +#include "mc/StaticVanillaBlocks.hpp" +#include "utils/RNG.h" #include "utils/StringHelper.h" -#include #include +#include #include -#include "WorldEdit.h" -#include "mc/ItemStack.hpp" -#include "mc/BlockPalette.hpp" -#include "mc/StaticVanillaBlocks.hpp" -#include "mc/Player.hpp" -#include "utils/RNG.h" -#include "BlockListPattern.h" +#include -namespace worldedit { - double Percents::getPercents(const phmap::flat_hash_map<::std::string, double>& variables, EvalFunctions& funcs) { - if (std::holds_alternative(val)) { - return std::get(val); - } - return cpp_eval::eval(std::get(val), variables, funcs); +namespace we { +double Percents::getPercents( + const phmap::flat_hash_map<::std::string, double>& variables, + EvalFunctions& funcs +) { + if (std::holds_alternative(val)) { + return std::get(val); } - Block const* RawBlock::getBlock(const phmap::flat_hash_map<::std::string, double>& variables, EvalFunctions& funcs) { - switch (block.index()) { - default: - return BedrockBlocks::mAir; - case 0: - return std::get(block); - case 1: - return Block::create(static_cast( - round(cpp_eval::eval(std::get(block), variables, funcs)))); - case 2: - std::string blockName; - auto& blockIds = std::get(block); - if (std::holds_alternative(blockIds.first)) { - blockName = getBlockName(static_cast( - round(cpp_eval::eval(std::get(blockIds.first), variables, funcs)))); - } else { - blockName = std::get(blockIds.first).val; - } + return cpp_eval::eval(std::get(val), variables, funcs); +} +Block const* RawBlock::getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + EvalFunctions& funcs +) { + switch (block.index()) { + default: + return BedrockBlocks::mAir; + case 0: + return std::get(block); + case 1: + return Block::create(static_cast( + round(cpp_eval::eval(std::get(block), variables, funcs)) + )); + case 2: + std::string blockName; + auto& blockIds = std::get(block); + if (std::holds_alternative(blockIds.first)) { + blockName = getBlockName(static_cast(round(cpp_eval::eval( + std::get(blockIds.first), + variables, + funcs + )))); + } else { + blockName = std::get(blockIds.first).val; + } - int mData = 0; - if (blockIds.second.has_value()) { - auto& dataVal = blockIds.second.value(); - mData = std::holds_alternative(dataVal) - ? std::get(dataVal) - : (static_cast( - round(cpp_eval::eval(std::get(dataVal), variables, funcs)))); - } - return Block::create(blockName, mData); + int mData = 0; + if (blockIds.second.has_value()) { + auto& dataVal = blockIds.second.value(); + mData = std::holds_alternative(dataVal) + ? std::get(dataVal) + : (static_cast(round(cpp_eval::eval( + std::get(dataVal), + variables, + funcs + )))); } + return Block::create(blockName, mData); } +} - RawBlock* BlockListPattern::getRawBlock(const phmap::flat_hash_map<::std::string, double>& variables, - EvalFunctions& funcs) { - std::vector weights; - double total = 0; - weights.resize(blockNum); - for (int i = 0; i < blockNum; ++i) { - weights[i] = std::max(percents[i].getPercents(variables, funcs), 0.0); - total += weights[i]; - } - if (total < 1e-32) { - return nullptr; - } - double random = RNG::rand() * total; - double sum = 0; - for (int i = 0; i < blockNum - 1; ++i) { - sum += weights[i]; - if (random <= sum) { - return &rawBlocks[i]; - } +RawBlock* BlockListPattern::getRawBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + EvalFunctions& funcs +) { + std::vector weights; + double total = 0; + weights.resize(blockNum); + for (int i = 0; i < blockNum; ++i) { + weights[i] = std::max(percents[i].getPercents(variables, funcs), 0.0); + total += weights[i]; + } + if (total < 1e-32) { + return nullptr; + } + double random = RNG::rand() * total; + double sum = 0; + for (int i = 0; i < blockNum - 1; ++i) { + sum += weights[i]; + if (random <= sum) { + return &rawBlocks[i]; } - return &rawBlocks[blockNum - 1]; } + return &rawBlocks[blockNum - 1]; +} - RawBlock::RawBlock() { - exBlock = const_cast(BedrockBlocks::mAir); - block = std::pair{BlockNameType(""), std::nullopt}; - } +RawBlock::RawBlock() { + exBlock = const_cast(BedrockBlocks::mAir); + block = std::pair{BlockNameType(""), std::nullopt}; +} - Block const* BlockListPattern::getBlock(const phmap::flat_hash_map<::std::string, double>& variables, - EvalFunctions& funcs) { - auto* rawBlock = getRawBlock(variables, funcs); - if (rawBlock == nullptr) { - return nullptr; - } - return rawBlock->getBlock(variables, funcs); +Block const* BlockListPattern::getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + EvalFunctions& funcs +) { + auto* rawBlock = getRawBlock(variables, funcs); + if (rawBlock == nullptr) { + return nullptr; } + return rawBlock->getBlock(variables, funcs); +} - bool BlockListPattern::setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) { - auto* rawBlock = getRawBlock(variables, funcs); - if (rawBlock == nullptr) { - return false; - } - auto* block = rawBlock->getBlock(variables, funcs); - bool res = playerData->setBlockSimple(blockSource, funcs, variables, pos, block, rawBlock->exBlock); +bool BlockListPattern::setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos +) { + auto* rawBlock = getRawBlock(variables, funcs); + if (rawBlock == nullptr) { + return false; + } + auto* block = rawBlock->getBlock(variables, funcs); + bool res = playerData->setBlockSimple( + blockSource, + funcs, + variables, + pos, + block, + rawBlock->exBlock + ); - if (block->hasBlockEntity() && rawBlock->blockEntity != nullptr) { - auto be = blockSource->getBlockEntity(pos); - if (be != nullptr) { - return be->setNbt(rawBlock->blockEntity.get()); - } else { - LevelChunk* chunk = blockSource->getChunkAt(pos); - auto b = BlockActor::create(rawBlock->blockEntity.get()); - if (b != nullptr) { - b->moveTo(pos); - chunk->_placeBlockEntity(b); - } + if (block->hasBlockEntity() && rawBlock->blockEntity != nullptr) { + auto be = blockSource->getBlockEntity(pos); + if (be != nullptr) { + return be->setNbt(rawBlock->blockEntity.get()); + } else { + LevelChunk* chunk = blockSource->getChunkAt(pos); + auto b = BlockActor::create(rawBlock->blockEntity.get()); + if (b != nullptr) { + b->moveTo(pos); + chunk->_placeBlockEntity(b); } } - return res; } + return res; +} - BlockListPattern::BlockListPattern(std::string_view str_v, std::string_view xuid) : Pattern(xuid) { - type = Pattern::PatternType::BLOCKLIST; +BlockListPattern::BlockListPattern(std::string_view str_v, std::string_view xuid) +: Pattern(xuid) { + type = Pattern::PatternType::BLOCKLIST; - std::string str = asString(str_v); + std::string str = asString(str_v); - auto strSize = str.size(); - playerData = &getPlayersData(xuid); - if (str == "#hand") { - type = Pattern::PatternType::HAND; - blockNum = 1; - percents.resize(blockNum); - rawBlocks.resize(blockNum); - Player* player = Global->getPlayer(asString(xuid)); - if (player != nullptr) { - auto mBlock = player->getHandSlot()->getBlock(); - if (mBlock != nullptr) { - rawBlocks[0].block = mBlock; - } + auto strSize = str.size(); + playerData = &getPlayersData(xuid); + if (str == "#hand") { + type = Pattern::PatternType::HAND; + blockNum = 1; + percents.resize(blockNum); + rawBlocks.resize(blockNum); + Player* player = Global->getPlayer(asString(xuid)); + if (player != nullptr) { + auto mBlock = player->getHandSlot()->getBlock(); + if (mBlock != nullptr) { + rawBlocks[0].block = mBlock; } - return; } - std::vector raw; - raw.clear(); - string form = ""; - size_t i = 0; - while (i < strSize) { - if (str[i] == '-' || isdigit(str[i])) { - auto head = i; + return; + } + std::vector raw; + raw.clear(); + string form = ""; + size_t i = 0; + while (i < strSize) { + if (str[i] == '-' || isdigit(str[i])) { + auto head = i; + ++i; + while (i < strSize && (str[i] == '.' || isdigit(str[i]))) { ++i; - while (i < strSize && (str[i] == '.' || isdigit(str[i]))) { - ++i; - } - form += string("num") + str[i]; - raw.push_back(str.substr(head, i - head)); - } else if (str[i] == '\'') { + } + form += string("num") + str[i]; + raw.push_back(str.substr(head, i - head)); + } else if (str[i] == '\'') { + ++i; + auto head = i; + while (i < strSize && (str[i] != '\'')) { ++i; - auto head = i; + } + raw.push_back(str.substr(head, i - head)); + ++i; + form += string("funciton") + str[i]; + } else if (isalpha(str[i])) { + if (str[i] == 'r' && str[i + 1] == 't' && str[i + 2] == '\'') { + i += 3; + auto head = i; while (i < strSize && (str[i] != '\'')) { ++i; } raw.push_back(str.substr(head, i - head)); ++i; - form += string("funciton") + str[i]; - } else if (isalpha(str[i])) { - if (str[i] == 'r' && str[i + 1] == 't' && str[i + 2] == '\'') { - i += 3; - auto head = i; - while (i < strSize && (str[i] != '\'')) { - ++i; - } - raw.push_back(str.substr(head, i - head)); + form += string("rtfunciton") + str[i]; + } else { + auto head = i; + ++i; + while (i < strSize + && (isalpha(str[i]) || str[i] == '_' || isdigit(str[i]) + || (str[i] == ':' && i + 1 < strSize && isalpha(str[i + 1]))) + ) { ++i; - form += string("rtfunciton") + str[i]; - } else { - auto head = i; + } + int kb = 0; + if (str[i] == '[') { + kb = 1; ++i; - while (i < strSize && (isalpha(str[i]) || str[i] == '_' || isdigit(str[i]) || - (str[i] == ':' && i + 1 < strSize && isalpha(str[i + 1])))) { - ++i; - } - int kb = 0; - if (str[i] == '[') { - kb = 1; - ++i; - while (kb > 0) { - if (str[i] == '[') { - ++kb; - } else if (str[i] == ']') { - --kb; - } - ++i; + while (kb > 0) { + if (str[i] == '[') { + ++kb; + } else if (str[i] == ']') { + --kb; } + ++i; } - form += string("block") + str[i]; - raw.push_back(str.substr(head, i - head)); - } - } else if (str[i] == '{') { - auto head = i; - int bracket = -1; - ++i; - while (i < strSize && bracket < 0) { - if (str[i] == '{') { - bracket--; - } else if (str[i] == '}') { - bracket++; - } - ++i; } - form += string("SNBT") + str[i]; + form += string("block") + str[i]; raw.push_back(str.substr(head, i - head)); } + } else if (str[i] == '{') { + auto head = i; + int bracket = -1; ++i; - } - auto blockList = SplitStrWithPattern(form, ","); - blockNum = blockList.size(); - // for (auto& x : blockList) { - // std::cout << x << std::endl; - // } - percents.resize(blockNum); - rawBlocks.resize(blockNum); - int rawPtr = 0; - for (int iter = 0; iter < blockNum; iter++) { - auto& blockIter = blockList[iter]; - auto& rawBlockIter = rawBlocks[iter]; - if (blockIter.find("%") != std::string::npos) { - if (blockIter.find("num%") != std::string::npos) { - percents[iter].val = std::stod(raw[rawPtr]); - } else { - percents[iter].val = raw[rawPtr]; + while (i < strSize && bracket < 0) { + if (str[i] == '{') { + bracket--; + } else if (str[i] == '}') { + bracket++; } - ++rawPtr; + ++i; + } + form += string("SNBT") + str[i]; + raw.push_back(str.substr(head, i - head)); + } + ++i; + } + auto blockList = SplitStrWithPattern(form, ","); + blockNum = blockList.size(); + // for (auto& x : blockList) { + // std::cout << x << std::endl; + // } + percents.resize(blockNum); + rawBlocks.resize(blockNum); + int rawPtr = 0; + for (int iter = 0; iter < blockNum; iter++) { + auto& blockIter = blockList[iter]; + auto& rawBlockIter = rawBlocks[iter]; + if (blockIter.find("%") != std::string::npos) { + if (blockIter.find("num%") != std::string::npos) { + percents[iter].val = std::stod(raw[rawPtr]); } else { - blockIter = "%" + blockIter; + percents[iter].val = raw[rawPtr]; } - if (blockIter.find("%num") != std::string::npos) { - std::get(rawBlockIter.block).first = - BlockNameType(getBlockName(std::stoi(raw[rawPtr]))); - ++rawPtr; - } else if (blockIter.find("%block") != std::string::npos) { - std::string tmpName = raw[rawPtr]; - if (tmpName[0] == 'r' && tmpName[1] == 't' && isdigit(tmpName[2])) { - rawBlockIter.block = Block::create(static_cast(std::stoi(tmpName.substr(2)))); - ++rawPtr; - continue; - } - if (tmpName.find("minecraft:") == std::string::npos) { - tmpName = "minecraft:" + tmpName; - } - std::get(rawBlockIter.block).first = BlockNameType(tmpName); - ++rawPtr; - } else if (blockIter.find("%rtfunciton") != std::string::npos) { - rawBlockIter.block = raw[rawPtr]; + ++rawPtr; + } else { + blockIter = "%" + blockIter; + } + if (blockIter.find("%num") != std::string::npos) { + std::get(rawBlockIter.block).first = + BlockNameType(getBlockName(std::stoi(raw[rawPtr]))); + ++rawPtr; + } else if (blockIter.find("%block") != std::string::npos) { + std::string tmpName = raw[rawPtr]; + if (tmpName[0] == 'r' && tmpName[1] == 't' && isdigit(tmpName[2])) { + rawBlockIter.block = + Block::create(static_cast(std::stoi(tmpName.substr(2))) + ); ++rawPtr; continue; - } else if (blockIter.find("%funciton") != std::string::npos) { - std::get(rawBlockIter.block).first = raw[rawPtr]; - ++rawPtr; - } else if (blockIter.find("%SNBT") != std::string::npos) { - std::string tmpSNBT = raw[rawPtr]; - if (tmpSNBT[0] == '{' && tmpSNBT[1] == '{') { - size_t i2 = 1; - std::vector tmpSNBTs; - tmpSNBTs.clear(); - while (i2 < tmpSNBT.size() - 1) { - int bracket2 = -1; - if (tmpSNBT[i2] == '{') { - auto head2 = i2; - i2++; - while (i2 < tmpSNBT.size() && bracket2 < 0) { - if (tmpSNBT[i2] == '{') { - bracket2--; - } else if (tmpSNBT[i2] == '}') { - bracket2++; - } - i2++; + } + if (tmpName.find("minecraft:") == std::string::npos) { + tmpName = "minecraft:" + tmpName; + } + std::get(rawBlockIter.block).first = + BlockNameType(tmpName); + ++rawPtr; + } else if (blockIter.find("%rtfunciton") != std::string::npos) { + rawBlockIter.block = raw[rawPtr]; + ++rawPtr; + continue; + } else if (blockIter.find("%funciton") != std::string::npos) { + std::get(rawBlockIter.block).first = raw[rawPtr]; + ++rawPtr; + } else if (blockIter.find("%SNBT") != std::string::npos) { + std::string tmpSNBT = raw[rawPtr]; + if (tmpSNBT[0] == '{' && tmpSNBT[1] == '{') { + size_t i2 = 1; + std::vector tmpSNBTs; + tmpSNBTs.clear(); + while (i2 < tmpSNBT.size() - 1) { + int bracket2 = -1; + if (tmpSNBT[i2] == '{') { + auto head2 = i2; + i2++; + while (i2 < tmpSNBT.size() && bracket2 < 0) { + if (tmpSNBT[i2] == '{') { + bracket2--; + } else if (tmpSNBT[i2] == '}') { + bracket2++; } - tmpSNBTs.push_back(tmpSNBT.substr(head2, i2 - head2)); + i2++; } - i2++; + tmpSNBTs.push_back(tmpSNBT.substr(head2, i2 - head2)); } - for (auto& ssss : tmpSNBTs) { - logger().info("{}", ssss); - } - rawBlockIter.block = Block::create(CompoundTag::fromSNBT(tmpSNBTs[0]).get()); - if (tmpSNBTs.size() > 1) { - rawBlockIter.exBlock = Block::create(CompoundTag::fromSNBT(tmpSNBTs[1]).get()); - } - if (tmpSNBTs.size() > 2) { - rawBlockIter.blockEntity = CompoundTag::fromSNBT(tmpSNBTs[2]); - } - } else { - rawBlockIter.block = Block::create(CompoundTag::fromSNBT(tmpSNBT).get()); + i2++; } - ++rawPtr; - continue; - } - if (blockIter.find(":num") != std::string::npos) { - std::get(rawBlockIter.block).second = std::stoi(raw[rawPtr]); - ++rawPtr; - } else if (blockIter.find(":funciton") != std::string::npos) { - std::get(rawBlockIter.block).second = raw[rawPtr]; - ++rawPtr; + for (auto& ssss : tmpSNBTs) { + logger().info("{}", ssss); + } + rawBlockIter.block = + Block::create(CompoundTag::fromSNBT(tmpSNBTs[0]).get()); + if (tmpSNBTs.size() > 1) { + rawBlockIter.exBlock = + Block::create(CompoundTag::fromSNBT(tmpSNBTs[1]).get()); + } + if (tmpSNBTs.size() > 2) { + rawBlockIter.blockEntity = CompoundTag::fromSNBT(tmpSNBTs[2]); + } + } else { + rawBlockIter.block = Block::create(CompoundTag::fromSNBT(tmpSNBT).get()); } - if (std::holds_alternative(rawBlockIter.block) && - std::holds_alternative(std::get(rawBlockIter.block).first) && - !(std::get(rawBlockIter.block).second.has_value() && - std::holds_alternative( - std::get(rawBlockIter.block).second.value()))) { - auto& blockName = std::get(std::get(rawBlockIter.block).first).val; - if (isBEBlock(blockName)) { - rawBlockIter.block = Block::create( - blockName, std::get(std::get(rawBlockIter.block).second.value_or(0))); - } else if (isJEBlock(blockName)) { - rawBlockIter.block = getJavaBlockMap()[blockName]; - if (blockName.find("waterlogged=true") != std::string::npos) { - rawBlockIter.exBlock = StaticVanillaBlocks::mWater; - } - } else { - rawBlockIter.block = BedrockBlocks::mAir; + ++rawPtr; + continue; + } + if (blockIter.find(":num") != std::string::npos) { + std::get(rawBlockIter.block).second = + std::stoi(raw[rawPtr]); + ++rawPtr; + } else if (blockIter.find(":funciton") != std::string::npos) { + std::get(rawBlockIter.block).second = raw[rawPtr]; + ++rawPtr; + } + if (std::holds_alternative(rawBlockIter.block) + && std::holds_alternative( + std::get(rawBlockIter.block).first + ) + && !( + std::get(rawBlockIter.block).second.has_value() + && std::holds_alternative( + std::get(rawBlockIter.block).second.value() + ) + )) { + auto& blockName = std::get( + std::get(rawBlockIter.block).first + ) + .val; + if (isBEBlock(blockName)) { + rawBlockIter.block = Block::create( + blockName, + std::get(std::get(rawBlockIter.block) + .second.value_or(0)) + ); + } else if (isJEBlock(blockName)) { + rawBlockIter.block = getJavaBlockMap()[blockName]; + if (blockName.find("waterlogged=true") != std::string::npos) { + rawBlockIter.exBlock = StaticVanillaBlocks::mWater; } + } else { + rawBlockIter.block = BedrockBlocks::mAir; } } } +} - bool BlockListPattern::hasBlock(Block const* block) { - for (auto& rawBlock : rawBlocks) { - if (std::holds_alternative(rawBlock.block)) { - if (std::get(rawBlock.block) == block) { - return true; - } +bool BlockListPattern::hasBlock(Block const* block) { + for (auto& rawBlock : rawBlocks) { + if (std::holds_alternative(rawBlock.block)) { + if (std::get(rawBlock.block) == block) { + return true; } } - return false; } -} // namespace worldedit \ No newline at end of file + return false; +} +} // namespace we \ No newline at end of file diff --git a/old/core/store/BlockListPattern.h b/old/core/store/BlockListPattern.h index 669775a..2ec460d 100644 --- a/old/core/store/BlockListPattern.h +++ b/old/core/store/BlockListPattern.h @@ -1,57 +1,67 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #pragma once #include "Pattern.h" -namespace worldedit { - class BlockNameType { - public: - std::string val; - BlockNameType(std::string const& v) : val(v) {} - }; - class Percents { - public: - std::variant val = 1.0; - Percents() = default; - - double getPercents(const phmap::flat_hash_map<::std::string, double>& variables, class EvalFunctions& funcs); - }; - class RawBlock { - public: - using blockid_t = - std::pair, std::optional>>; - std::variant block; - class Block const* exBlock; - std::unique_ptr blockEntity = nullptr; - RawBlock(); - - class Block const* getBlock(const phmap::flat_hash_map<::std::string, double>& variables, class EvalFunctions& funcs); - }; - - class BlockListPattern final : public Pattern { - public: - size_t blockNum = 0; - std::vector percents; - std::vector rawBlocks; - - BlockListPattern(std::string_view str, std::string_view xuid); - - class Block const* getBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs) override; - - bool hasBlock(class Block const* block) override; - - bool setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) override; - - private: - class RawBlock* getRawBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs); - }; - -} // namespace worldedit \ No newline at end of file +namespace we { +class BlockNameType { +public: + std::string val; + BlockNameType(std::string const& v) : val(v) {} +}; +class Percents { +public: + std::variant val = 1.0; + Percents() = default; + + double getPercents( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ); +}; +class RawBlock { +public: + using blockid_t = std::pair< + std::variant, + std::optional>>; + std::variant block; + class Block const* exBlock; + std::unique_ptr blockEntity = nullptr; + RawBlock(); + + class Block const* getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ); +}; + +class BlockListPattern : public Pattern { +public: + size_t blockNum = 0; + std::vector percents; + std::vector rawBlocks; + + BlockListPattern(std::string_view str, std::string_view xuid); + + class Block const* getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ) override; + + bool hasBlock(class Block const* block) override; + + bool setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos + ) override; + +private: + class RawBlock* getRawBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ); +}; + +} // namespace we \ No newline at end of file diff --git a/old/core/store/BlockNBTSet.cpp b/old/core/store/BlockNBTSet.cpp index dd45e33..5d2fc31 100644 --- a/old/core/store/BlockNBTSet.cpp +++ b/old/core/store/BlockNBTSet.cpp @@ -1,126 +1,145 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "BlockNBTSet.hpp" -#include "data/PlayerData.h" #include "WorldEdit.h" +#include "data/PlayerData.h" +#include #include #include -#include -namespace worldedit { +namespace we { - BlockNBTSet::BlockNBTSet(BlockNBTSet const& other) { - if (other.blockEntity) - blockEntity = other.blockEntity->clone(); - blocks = other.blocks; - biomeId = other.biomeId; - } +BlockNBTSet::BlockNBTSet(BlockNBTSet const& other) { + if (other.blockEntity) blockEntity = other.blockEntity->clone(); + blocks = other.blocks; + biomeId = other.biomeId; +} - BlockNBTSet& BlockNBTSet::operator=(BlockNBTSet const& other) { - if (other.blockEntity) - blockEntity = other.blockEntity->clone(); - blocks = other.blocks; - biomeId = other.biomeId; - return *this; - } - BlockNBTSet::BlockNBTSet(BlockInstance& blockInstance) { - auto* bs = blockInstance.getBlockSource(); - auto pos = blockInstance.getPosition(); - blocks = {blockInstance.getBlock(), &bs->getExtraBlock(pos)}; - // auto* biome = bs->tryGetBiome(pos); - // if (biome != nullptr) { - // biomeId = biome->getId(); - // } - if (blockInstance.hasBlockEntity()) { - auto be = blockInstance.getBlockEntity(); - if (be != nullptr) { - blockEntity = be->getNbt(); - } +BlockNBTSet& BlockNBTSet::operator=(BlockNBTSet const& other) { + if (other.blockEntity) blockEntity = other.blockEntity->clone(); + blocks = other.blocks; + biomeId = other.biomeId; + return *this; +} +BlockNBTSet::BlockNBTSet(BlockInstance& blockInstance) { + auto* bs = blockInstance.getBlockSource(); + auto pos = blockInstance.getPosition(); + blocks = {blockInstance.getBlock(), &bs->getExtraBlock(pos)}; + // auto* biome = bs->tryGetBiome(pos); + // if (biome != nullptr) { + // biomeId = biome->getId(); + // } + if (blockInstance.hasBlockEntity()) { + auto be = blockInstance.getBlockEntity(); + if (be != nullptr) { + blockEntity = be->getNbt(); } } +} - bool BlockNBTSet::setBlockWithoutcheckGMask(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - bool setBiome) const { - auto& [block, exblock] = blocks.value(); - bool res; - res = data.setBlockWithoutcheckGMask(blockSource, pos, block, exblock, setBiome ? biomeId : std::nullopt); - if (blockEntity != nullptr && block->hasBlockEntity()) { - auto be = blockSource->getBlockEntity(pos); - if (be != nullptr) { - return be->setNbt(blockEntity.get()); - } else { - LevelChunk* chunk = blockSource->getChunkAt(pos); - if (chunk != nullptr) { - auto b = BlockActor::create(blockEntity.get()); - if (b != nullptr) { - b->moveTo(pos); - chunk->_placeBlockEntity(b); - } +bool BlockNBTSet::setBlockWithoutcheckGMask( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + bool setBiome +) const { + auto& [block, exblock] = blocks.value(); + bool res; + res = data.setBlockWithoutcheckGMask( + blockSource, + pos, + block, + exblock, + setBiome ? biomeId : std::nullopt + ); + if (blockEntity != nullptr && block->hasBlockEntity()) { + auto be = blockSource->getBlockEntity(pos); + if (be != nullptr) { + return be->setNbt(blockEntity.get()); + } else { + LevelChunk* chunk = blockSource->getChunkAt(pos); + if (chunk != nullptr) { + auto b = BlockActor::create(blockEntity.get()); + if (b != nullptr) { + b->moveTo(pos); + chunk->_placeBlockEntity(b); } } } - return res; } + return res; +} - bool BlockNBTSet::setBlock(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - bool setBiome) const { - auto& [block, exblock] = blocks.value(); - bool res; - res = data.setBlockSimple(blockSource, funcs, var, pos, block, exblock, setBiome ? biomeId : std::nullopt); - if (blockEntity != nullptr && block->hasBlockEntity()) { - auto be = blockSource->getBlockEntity(pos); - if (be != nullptr) { - return be->setNbt(blockEntity.get()); - } else { - LevelChunk* chunk = blockSource->getChunkAt(pos); - if (chunk != nullptr) { - auto b = BlockActor::create(blockEntity.get()); - if (b != nullptr) { - b->moveTo(pos); - chunk->_placeBlockEntity(b); - } +bool BlockNBTSet::setBlock( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + bool setBiome +) const { + auto& [block, exblock] = blocks.value(); + bool res; + res = data.setBlockSimple( + blockSource, + funcs, + var, + pos, + block, + exblock, + setBiome ? biomeId : std::nullopt + ); + if (blockEntity != nullptr && block->hasBlockEntity()) { + auto be = blockSource->getBlockEntity(pos); + if (be != nullptr) { + return be->setNbt(blockEntity.get()); + } else { + LevelChunk* chunk = blockSource->getChunkAt(pos); + if (chunk != nullptr) { + auto b = BlockActor::create(blockEntity.get()); + if (b != nullptr) { + b->moveTo(pos); + chunk->_placeBlockEntity(b); } } } - return res; } - bool BlockNBTSet::setBlock(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - Rotation rotation, - Mirror mirror, - bool setBiome) const { - auto& [block, exblock] = blocks.value(); - bool res; - res = data.setBlockSimple( - blockSource, funcs, var, pos, - VanillaBlockStateTransformUtils::transformBlock(*block, rotation, mirror), - VanillaBlockStateTransformUtils::transformBlock(*exblock, rotation, mirror), - setBiome ? biomeId : std::nullopt); - if (blockEntity != nullptr && block->hasBlockEntity()) { - auto be = blockSource->getBlockEntity(pos); - if (be != nullptr) { - return be->setNbt(blockEntity.get()); - } else { - LevelChunk* chunk = blockSource->getChunkAt(pos); - if (chunk != nullptr) { - auto b = BlockActor::create(blockEntity.get()); - if (b != nullptr) { - b->moveTo(pos); - chunk->_placeBlockEntity(b); - } + return res; +} +bool BlockNBTSet::setBlock( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + Rotation rotation, + Mirror mirror, + bool setBiome +) const { + auto& [block, exblock] = blocks.value(); + bool res; + res = data.setBlockSimple( + blockSource, + funcs, + var, + pos, + VanillaBlockStateTransformUtils::transformBlock(*block, rotation, mirror), + VanillaBlockStateTransformUtils::transformBlock(*exblock, rotation, mirror), + setBiome ? biomeId : std::nullopt + ); + if (blockEntity != nullptr && block->hasBlockEntity()) { + auto be = blockSource->getBlockEntity(pos); + if (be != nullptr) { + return be->setNbt(blockEntity.get()); + } else { + LevelChunk* chunk = blockSource->getChunkAt(pos); + if (chunk != nullptr) { + auto b = BlockActor::create(blockEntity.get()); + if (b != nullptr) { + b->moveTo(pos); + chunk->_placeBlockEntity(b); } } } - return res; } -} // namespace worldedit + return res; +} +} // namespace we diff --git a/old/core/store/BlockNBTSet.hpp b/old/core/store/BlockNBTSet.hpp index 5a70dfb..7e32581 100644 --- a/old/core/store/BlockNBTSet.hpp +++ b/old/core/store/BlockNBTSet.hpp @@ -1,53 +1,56 @@ -// -// Created by OEOTYAN on 2022/05/20. -// #pragma once #include "Globals.h" #include // #include +#include "particle/Graphics.h" +#include #include #include +#include #include #include -#include -#include #include #include -#include "particle/Graphics.h" -namespace worldedit { +namespace we { - class BlockNBTSet { - public: - std::unique_ptr blockEntity = nullptr; - std::optional> blocks; - std::optional biomeId; - BlockNBTSet() = default; - BlockNBTSet(BlockNBTSet const&); - BlockNBTSet(BlockNBTSet&&) = default; - BlockNBTSet& operator=(BlockNBTSet const&); - BlockNBTSet& operator=(BlockNBTSet&&) = default; - BlockNBTSet(BlockInstance& blockInstance); - Block const* getBlock() const { return blocks.value().first; } - Block const* getExBlock() const { return blocks.value().second; } - bool setBlockWithoutcheckGMask(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - bool needBiome = false) const; - bool setBlock(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - bool needBiome = false) const; - bool setBlock(const BlockPos& pos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - Rotation rotation, - Mirror mirror, - bool needBiome = false) const; - }; -} // namespace worldedit \ No newline at end of file +class BlockNBTSet { +public: + std::unique_ptr blockEntity = nullptr; + std::optional> blocks; + std::optional biomeId; + BlockNBTSet() = default; + BlockNBTSet(BlockNBTSet const&); + BlockNBTSet(BlockNBTSet&&) = default; + BlockNBTSet& operator=(BlockNBTSet const&); + BlockNBTSet& operator=(BlockNBTSet&&) = default; + BlockNBTSet(BlockInstance& blockInstance); + Block const* getBlock() const { return blocks.value().first; } + Block const* getExBlock() const { return blocks.value().second; } + bool setBlockWithoutcheckGMask( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + bool needBiome = false + ) const; + bool setBlock( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + bool needBiome = false + ) const; + bool setBlock( + BlockPos const& pos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + Rotation rotation, + Mirror mirror, + bool needBiome = false + ) const; +}; +} // namespace we \ No newline at end of file diff --git a/old/core/store/Clipboard.cpp b/old/core/store/Clipboard.cpp index 1730160..62abdae 100644 --- a/old/core/store/Clipboard.cpp +++ b/old/core/store/Clipboard.cpp @@ -1,237 +1,242 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "Clipboard.hpp" #include "I18nAPI.h" #include "WorldEdit.h" #include "eval/Eval.h" -namespace worldedit { +namespace we { - long long Clipboard::getIter(const BlockPos& pos) { - return (pos.y + size.y * pos.z) * size.x + pos.x; +long long Clipboard::getIter(BlockPos const& pos) { + return (pos.y + size.y * pos.z) * size.x + pos.x; +} +Clipboard::Clipboard(BlockPos const& sizes) +: size(sizes + 1), + board(sizes), + rotation(Rotation::None), + mirror(Mirror::None), + rotationAngle({0, 0, 0}) { + used = true; + vsize = size.x * size.y * size.z; + blockslist.clear(); + try { + blockslist.resize(vsize); + } catch (std::bad_alloc) { + Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); + return; } - Clipboard::Clipboard(const BlockPos& sizes) - : size(sizes + 1), board(sizes), rotation(Rotation::None), mirror(Mirror::None), rotationAngle({0, 0, 0}) { - used = true; - vsize = size.x * size.y * size.z; - blockslist.clear(); - try { - blockslist.resize(vsize); - } catch (std::bad_alloc) { - Level::broadcastText(tr("worldedit.memory.out"), TextType::RAW); - return; - } +} +Clipboard::Clipboard(const Clipboard& other) { + if (other.entities) entities = other.entities->clone(); + size = other.size; + playerRelPos = other.playerRelPos; + playerPos = other.playerPos; + board = other.board; + rotation = other.rotation; + mirror = other.mirror; + rotationAngle = other.rotationAngle; + flipY = other.flipY; + used = other.used; + vsize = other.vsize; + blockslist = other.blockslist; +} +long long Clipboard::getIterLoop(BlockPos const& pos) { + return (static_cast(posfmod(pos.y, size.y)) + + size.y * static_cast(posfmod(pos.z, size.z))) + * size.x + + static_cast(posfmod(pos.x, size.x)); +} +void Clipboard::storeBlock(BlockInstance& blockInstance, BlockPos const& pos) { + if (pos.containedWithin(BlockPos(0, 0, 0), board)) { + blockslist[getIter(pos)] = std::move(BlockNBTSet(blockInstance)); } - Clipboard::Clipboard(const Clipboard& other) { - if (other.entities) - entities = other.entities->clone(); - size = other.size; - playerRelPos = other.playerRelPos; - playerPos = other.playerPos; - board = other.board; - rotation = other.rotation; - mirror = other.mirror; - rotationAngle = other.rotationAngle; - flipY = other.flipY; - used = other.used; - vsize = other.vsize; - blockslist = other.blockslist; +} +BoundingBox Clipboard::getBoundingBox() { + BoundingBox res; + res.min = getPos({0, 0, 0}); + res.min = BlockPos::min(res.min, getPos({board.x, 0, 0})); + res.min = BlockPos::min(res.min, getPos({0, board.y, 0})); + res.min = BlockPos::min(res.min, getPos({0, 0, board.z})); + res.min = BlockPos::min(res.min, getPos({board.x, 0, board.z})); + res.min = BlockPos::min(res.min, getPos({board.x, board.y, 0})); + res.min = BlockPos::min(res.min, getPos({0, board.y, board.z})); + res.min = BlockPos::min(res.min, getPos({board.x, board.y, board.z})); + res.max = getPos({0, 0, 0}); + res.max = BlockPos::max(res.max, getPos({board.x, 0, 0})); + res.max = BlockPos::max(res.max, getPos({0, board.y, 0})); + res.max = BlockPos::max(res.max, getPos({0, 0, board.z})); + res.max = BlockPos::max(res.max, getPos({board.x, 0, board.z})); + res.max = BlockPos::max(res.max, getPos({board.x, board.y, 0})); + res.max = BlockPos::max(res.max, getPos({0, board.y, board.z})); + res.max = BlockPos::max(res.max, getPos({board.x, board.y, board.z})); + if (!(abs(posfmod(rotationAngle.x, 90.0f)) < 0.01 + && abs(posfmod(rotationAngle.y, 90.0f)) < 0.01 + && abs(posfmod(rotationAngle.z, 90.0f)) < 0.01)) { + res.min = res.min - 1; + res.max = res.max + 1; } - long long Clipboard::getIterLoop(const BlockPos& pos) { - return (static_cast(posfmod(pos.y, size.y)) + size.y * static_cast(posfmod(pos.z, size.z))) * size.x + - static_cast(posfmod(pos.x, size.x)); + return res; +} +void Clipboard::rotate(Vec3 angle) { + rotationAngle = rotationAngle + angle; + rotationAngle.y = static_cast(posfmod(rotationAngle.y, 360.0f)); + if (rotationAngle.y > 315 || rotationAngle.y <= 45) { + rotation = Rotation::None; + } else if (rotationAngle.y > 45 && rotationAngle.y <= 135) { + rotation = Rotation::Rotate90; + } else if (rotationAngle.y > 135 && rotationAngle.y <= 225) { + rotation = Rotation::Rotate180; + } else if (rotationAngle.y > 225 && rotationAngle.y <= 315) { + rotation = Rotation::Rotate270; } - void Clipboard::storeBlock(BlockInstance& blockInstance, const BlockPos& pos) { - if (pos.containedWithin(BlockPos(0, 0, 0), board)) { - blockslist[getIter(pos)] = std::move(BlockNBTSet(blockInstance)); +} +void Clipboard::flip(enum class FACING facing) { + if (facing == FACING::NEG_Z || facing == FACING::POS_Z) { + if (mirror == Mirror::None) { + mirror = Mirror::X; + } else if (mirror == Mirror::X) { + mirror = Mirror::None; + } else if (mirror == Mirror::Z) { + mirror = Mirror::XZ; + } else if (mirror == Mirror::XZ) { + mirror = Mirror::Z; } - } - BoundingBox Clipboard::getBoundingBox() { - BoundingBox res; - res.min = getPos({0, 0, 0}); - res.min = BlockPos::min(res.min, getPos({board.x, 0, 0})); - res.min = BlockPos::min(res.min, getPos({0, board.y, 0})); - res.min = BlockPos::min(res.min, getPos({0, 0, board.z})); - res.min = BlockPos::min(res.min, getPos({board.x, 0, board.z})); - res.min = BlockPos::min(res.min, getPos({board.x, board.y, 0})); - res.min = BlockPos::min(res.min, getPos({0, board.y, board.z})); - res.min = BlockPos::min(res.min, getPos({board.x, board.y, board.z})); - res.max = getPos({0, 0, 0}); - res.max = BlockPos::max(res.max, getPos({board.x, 0, 0})); - res.max = BlockPos::max(res.max, getPos({0, board.y, 0})); - res.max = BlockPos::max(res.max, getPos({0, 0, board.z})); - res.max = BlockPos::max(res.max, getPos({board.x, 0, board.z})); - res.max = BlockPos::max(res.max, getPos({board.x, board.y, 0})); - res.max = BlockPos::max(res.max, getPos({0, board.y, board.z})); - res.max = BlockPos::max(res.max, getPos({board.x, board.y, board.z})); - if (!(abs(posfmod(rotationAngle.x, 90.0f)) < 0.01 && abs(posfmod(rotationAngle.y, 90.0f)) < 0.01 && - abs(posfmod(rotationAngle.z, 90.0f)) < 0.01)) { - res.min = res.min - 1; - res.max = res.max + 1; + } else if (facing == FACING::NEG_X || facing == FACING::POS_X) { + if (mirror == Mirror::None) { + mirror = Mirror::Z; + } else if (mirror == Mirror::X) { + mirror = Mirror::XZ; + } else if (mirror == Mirror::Z) { + mirror = Mirror::None; + } else if (mirror == Mirror::XZ) { + mirror = Mirror::X; } - return res; + } else if (facing == FACING::NEG_Y || facing == FACING::POS_Y) { + flipY = !flipY; } - void Clipboard::rotate(Vec3 angle) { - rotationAngle = rotationAngle + angle; - rotationAngle.y = static_cast(posfmod(rotationAngle.y, 360.0f)); - if (rotationAngle.y > 315 || rotationAngle.y <= 45) { - rotation = Rotation::None; - } else if (rotationAngle.y > 45 && rotationAngle.y <= 135) { - rotation = Rotation::Rotate90; - } else if (rotationAngle.y > 135 && rotationAngle.y <= 225) { - rotation = Rotation::Rotate180; - } else if (rotationAngle.y > 225 && rotationAngle.y <= 315) { - rotation = Rotation::Rotate270; - } +} +BlockPos Clipboard::getPos(BlockPos const& pos) { + BlockPos res = pos - playerRelPos; + if (mirror == Mirror::XZ) { + res.x = -res.x; + res.z = -res.z; + } else if (mirror == Mirror::X) { + res.z = -res.z; + } else if (mirror == Mirror::Z) { + res.x = -res.x; } - void Clipboard::flip(enum class FACING facing) { - if (facing == FACING::NEG_Z || facing == FACING::POS_Z) { - if (mirror == Mirror::None) { - mirror = Mirror::X; - } else if (mirror == Mirror::X) { - mirror = Mirror::None; - } else if (mirror == Mirror::Z) { - mirror = Mirror::XZ; - } else if (mirror == Mirror::XZ) { - mirror = Mirror::Z; - } - } else if (facing == FACING::NEG_X || facing == FACING::POS_X) { - if (mirror == Mirror::None) { - mirror = Mirror::Z; - } else if (mirror == Mirror::X) { - mirror = Mirror::XZ; - } else if (mirror == Mirror::Z) { - mirror = Mirror::None; - } else if (mirror == Mirror::XZ) { - mirror = Mirror::X; - } - } else if (facing == FACING::NEG_Y || facing == FACING::POS_Y) { - flipY = !flipY; - } + if (flipY) { + res.y = -res.y; } - BlockPos Clipboard::getPos(const BlockPos& pos) { - BlockPos res = pos - playerRelPos; - if (mirror == Mirror::XZ) { + Vec3 angle = rotationAngle; + angle.x = static_cast(posfmod(angle.x, 360.0f)); + angle.y = static_cast(posfmod(angle.y, 360.0f)); + angle.z = static_cast(posfmod(angle.z, 360.0f)); + + if (abs(posfmod(angle.y, 90.0f)) < 0.01f) { + if (abs(angle.y - 90) < 0.01f) { + int tmp = res.x; + res.x = -res.z; + res.z = tmp; + } else if (abs(angle.y - 180) < 0.01f) { res.x = -res.x; res.z = -res.z; - } else if (mirror == Mirror::X) { - res.z = -res.z; - } else if (mirror == Mirror::Z) { - res.x = -res.x; - } - if (flipY) { - res.y = -res.y; + } else if (abs(angle.y - 270) < 0.01f) { + int tmp = res.x; + res.x = res.z; + res.z = -tmp; } - Vec3 angle = rotationAngle; - angle.x = static_cast(posfmod(angle.x, 360.0f)); - angle.y = static_cast(posfmod(angle.y, 360.0f)); - angle.z = static_cast(posfmod(angle.z, 360.0f)); - - if (abs(posfmod(angle.y, 90.0f)) < 0.01f) { - if (abs(angle.y - 90) < 0.01f) { - int tmp = res.x; - res.x = -res.z; - res.z = tmp; - } else if (abs(angle.y - 180) < 0.01f) { - res.x = -res.x; - res.z = -res.z; - } else if (abs(angle.y - 270) < 0.01f) { - int tmp = res.x; - res.x = res.z; - res.z = -tmp; - } - } else { - if (angle.y > 90 && angle.y < 270) { - angle.y -= 180; - res.x = -res.x; - res.z = -res.z; - } - angle.y = angle.y * static_cast(M_PI / 180.0); - auto tanY = tan(angle.y * 0.5); - res.x = static_cast(floor(res.x + 0.5 - (res.z + 0.5) * tanY)); - res.z = static_cast(floor((res.x + 0.5) * sin(angle.y) + res.z + 0.5)); - res.x = static_cast(floor(res.x + 0.5 - (res.z + 0.5) * tanY)); + } else { + if (angle.y > 90 && angle.y < 270) { + angle.y -= 180; + res.x = -res.x; + res.z = -res.z; } + angle.y = angle.y * static_cast(M_PI / 180.0); + auto tanY = tan(angle.y * 0.5); + res.x = static_cast(floor(res.x + 0.5 - (res.z + 0.5) * tanY)); + res.z = static_cast(floor((res.x + 0.5) * sin(angle.y) + res.z + 0.5)); + res.x = static_cast(floor(res.x + 0.5 - (res.z + 0.5) * tanY)); + } - if (abs(posfmod(angle.x, 90.0f)) < 0.01f) { - if (abs(angle.x - 90) < 0.01f) { - int tmp = res.y; - res.y = -res.z; - res.z = tmp; - } else if (abs(angle.x - 180) < 0.01f) { - res.y = -res.y; - res.z = -res.z; - } else if (abs(angle.x - 270) < 0.01f) { - int tmp = res.y; - res.y = res.z; - res.z = -tmp; - } - } else { - if (angle.x > 90 && angle.x < 270) { - angle.x -= 180; - res.y = -res.y; - res.z = -res.z; - } - angle.x = angle.x * static_cast(M_PI / 180.0); - auto tanX = tan(angle.x * 0.5); - res.y = static_cast(floor(res.y + 0.5 - (res.z + 0.5) * tanX)); - res.z = static_cast(floor((res.y + 0.5) * sin(angle.x) + res.z + 0.5)); - res.y = static_cast(floor(res.y + 0.5 - (res.z + 0.5) * tanX)); + if (abs(posfmod(angle.x, 90.0f)) < 0.01f) { + if (abs(angle.x - 90) < 0.01f) { + int tmp = res.y; + res.y = -res.z; + res.z = tmp; + } else if (abs(angle.x - 180) < 0.01f) { + res.y = -res.y; + res.z = -res.z; + } else if (abs(angle.x - 270) < 0.01f) { + int tmp = res.y; + res.y = res.z; + res.z = -tmp; } - if (abs(posfmod(angle.z, 90.0f)) < 0.01f) { - if (abs(angle.z - 90) < 0.01f) { - int tmp = res.x; - res.x = -res.y; - res.y = tmp; - } else if (abs(angle.z - 180) < 0.01f) { - res.x = -res.x; - res.y = -res.y; - } else if (abs(angle.z - 270) < 0.01f) { - int tmp = res.x; - res.x = res.y; - res.y = -tmp; - } - } else { - if (angle.z > 90 && angle.z < 270) { - angle.z -= 180; - res.x = -res.x; - res.y = -res.y; - } - angle.z = angle.z * static_cast(M_PI / 180.0); - auto tanZ = tan(angle.z * 0.5); - res.x = static_cast(floor(res.x + 0.5 - (res.y + 0.5) * tanZ)); - res.y = static_cast(floor((res.x + 0.5) * sin(angle.z) + res.y + 0.5)); - res.x = static_cast(floor(res.x + 0.5 - (res.y + 0.5) * tanZ)); + } else { + if (angle.x > 90 && angle.x < 270) { + angle.x -= 180; + res.y = -res.y; + res.z = -res.z; } - return res; + angle.x = angle.x * static_cast(M_PI / 180.0); + auto tanX = tan(angle.x * 0.5); + res.y = static_cast(floor(res.y + 0.5 - (res.z + 0.5) * tanX)); + res.z = static_cast(floor((res.y + 0.5) * sin(angle.x) + res.z + 0.5)); + res.y = static_cast(floor(res.y + 0.5 - (res.z + 0.5) * tanX)); } - BlockNBTSet& Clipboard::getSet(const BlockPos& pos) { - return blockslist[getIter(pos)]; - } - BlockNBTSet& Clipboard::getSetLoop(const BlockPos& pos) { - return blockslist[getIterLoop(pos)]; - } - bool Clipboard::contains(const BlockPos& pos) { - return blockslist[getIter(pos)].blocks.has_value(); - } - bool Clipboard::setBlocks(const BlockPos& pos, - BlockPos& worldPos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - bool setBiome) { - return blockslist[getIter(pos)].setBlock(worldPos, blockSource, data, funcs, var, rotation, mirror, setBiome); + if (abs(posfmod(angle.z, 90.0f)) < 0.01f) { + if (abs(angle.z - 90) < 0.01f) { + int tmp = res.x; + res.x = -res.y; + res.y = tmp; + } else if (abs(angle.z - 180) < 0.01f) { + res.x = -res.x; + res.y = -res.y; + } else if (abs(angle.z - 270) < 0.01f) { + int tmp = res.x; + res.x = res.y; + res.y = -tmp; + } + } else { + if (angle.z > 90 && angle.z < 270) { + angle.z -= 180; + res.x = -res.x; + res.y = -res.y; + } + angle.z = angle.z * static_cast(M_PI / 180.0); + auto tanZ = tan(angle.z * 0.5); + res.x = static_cast(floor(res.x + 0.5 - (res.y + 0.5) * tanZ)); + res.y = static_cast(floor((res.x + 0.5) * sin(angle.z) + res.y + 0.5)); + res.x = static_cast(floor(res.x + 0.5 - (res.y + 0.5) * tanZ)); } - void Clipboard::forEachBlockInClipboard(const std::function& todo) { - for (int y = 0; y < size.y; y++) - for (int x = 0; x < size.x; ++x) - for (int z = 0; z < size.z; ++z) { - if (contains({x, y, z})) { - todo({x, y, z}); - } + return res; +} +BlockNBTSet& Clipboard::getSet(BlockPos const& pos) { return blockslist[getIter(pos)]; } +BlockNBTSet& Clipboard::getSetLoop(BlockPos const& pos) { + return blockslist[getIterLoop(pos)]; +} +bool Clipboard::contains(BlockPos const& pos) { + return blockslist[getIter(pos)].blocks.has_value(); +} +bool Clipboard::setBlocks( + BlockPos const& pos, + BlockPos& worldPos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + bool setBiome +) { + return blockslist[getIter(pos)] + .setBlock(worldPos, blockSource, data, funcs, var, rotation, mirror, setBiome); +} +void Clipboard::forEachBlockInClipboard(const std::function& todo +) { + for (int y = 0; y < size.y; y++) + for (int x = 0; x < size.x; ++x) + for (int z = 0; z < size.z; ++z) { + if (contains({x, y, z})) { + todo({x, y, z}); } - } -} // namespace worldedit \ No newline at end of file + } +} +} // namespace we \ No newline at end of file diff --git a/old/core/store/Clipboard.hpp b/old/core/store/Clipboard.hpp index b50bb1b..64e10db 100644 --- a/old/core/store/Clipboard.hpp +++ b/old/core/store/Clipboard.hpp @@ -1,52 +1,51 @@ -// -// Created by OEOTYAN on 2022/05/21. -// #pragma once +#include "BlockNBTSet.hpp" #include "Globals.h" -#include #include +#include #include -#include "BlockNBTSet.hpp" -namespace worldedit { +namespace we { - class Clipboard { - public: - std::unique_ptr entities = nullptr; - BlockPos size; - BlockPos playerRelPos; - BlockPos playerPos; - BlockPos board; - Rotation rotation; - Mirror mirror; - Vec3 rotationAngle; - bool flipY = false; - bool used = false; - long long vsize; - std::vector blockslist; - explicit Clipboard() = default; - explicit Clipboard(const Clipboard& other); - explicit Clipboard(Clipboard&&) = default; - Clipboard& operator=(Clipboard&&) = default; - explicit Clipboard(const BlockPos& sizes); - long long getIter(const BlockPos& pos); - long long getIterLoop(const BlockPos& pos); - void storeBlock(BlockInstance& blockInstance, const BlockPos& pos); - BoundingBox getBoundingBox(); - void rotate(Vec3 angle); - void flip(enum class FACING facing); - BlockPos getPos(const BlockPos& pos); - BlockNBTSet& getSet(const BlockPos& pos); - BlockNBTSet& getSetLoop(const BlockPos& pos); - bool contains(const BlockPos& pos); - bool setBlocks(const BlockPos& pos, - BlockPos& worldPos, - BlockSource* blockSource, - class PlayerData& data, - class EvalFunctions& funcs, - phmap::flat_hash_map const& var, - bool setBiome = false); - void forEachBlockInClipboard(const std::function& todo); - }; -} // namespace worldedit \ No newline at end of file +class Clipboard { +public: + std::unique_ptr entities = nullptr; + BlockPos size; + BlockPos playerRelPos; + BlockPos playerPos; + BlockPos board; + Rotation rotation; + Mirror mirror; + Vec3 rotationAngle; + bool flipY = false; + bool used = false; + long long vsize; + std::vector blockslist; + Clipboard() = default; + Clipboard(const Clipboard& other); + Clipboard(Clipboard&&) = default; + Clipboard& operator=(Clipboard&&) = default; + Clipboard(BlockPos const& sizes); + long long getIter(BlockPos const& pos); + long long getIterLoop(BlockPos const& pos); + void storeBlock(BlockInstance& blockInstance, BlockPos const& pos); + BoundingBox getBoundingBox(); + void rotate(Vec3 angle); + void flip(enum class FACING facing); + BlockPos getPos(BlockPos const& pos); + BlockNBTSet& getSet(BlockPos const& pos); + BlockNBTSet& getSetLoop(BlockPos const& pos); + bool contains(BlockPos const& pos); + bool setBlocks( + BlockPos const& pos, + BlockPos& worldPos, + BlockSource* blockSource, + class PlayerData& data, + class EvalFunctions& funcs, + phmap::flat_hash_map const& var, + bool setBiome = false + ); + void forEachBlockInClipboard(const std::function& todo); +}; +} // namespace we \ No newline at end of file diff --git a/old/core/store/ClipboardPattern.cpp b/old/core/store/ClipboardPattern.cpp index e0ff519..4b1bc0e 100644 --- a/old/core/store/ClipboardPattern.cpp +++ b/old/core/store/ClipboardPattern.cpp @@ -1,73 +1,74 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #include "ClipboardPattern.h" #include "Clipboard.hpp" #include "WorldEdit.h" #include "region/Region.h" -namespace worldedit { +namespace we { - ClipboardPattern::ClipboardPattern(std::string_view str, std::string_view xuid) : Pattern(xuid) { - type = Pattern::PatternType::CLIPBOARD; - if (!playerData->clipboard.used) { - return; - } - clipboard = &playerData->clipboard; - auto& region = playerData->region; - if (region != nullptr) { - if (str.find("@c") != std::string::npos) { - bias = region->getCenter().toBlockPos(); - } else { - bias = region->getBoundBox().min; - } +ClipboardPattern::ClipboardPattern(std::string_view str, std::string_view xuid) +: Pattern(xuid) { + type = Pattern::PatternType::CLIPBOARD; + if (!playerData->clipboard.used) { + return; + } + clipboard = &playerData->clipboard; + auto& region = playerData->region; + if (region != nullptr) { + if (str.find("@c") != std::string::npos) { + bias = region->getCenter().toBlockPos(); } else { - bias = BlockPos(0, 0, 0); + bias = region->getBoundBox().min; } - auto strSize = str.size(); - size_t mi = 0; - std::vector poslist; - poslist.clear(); - while (mi < strSize) { - if (str[mi] == '-' || isdigit(str[mi])) { - auto head = mi; + } else { + bias = BlockPos(0, 0, 0); + } + auto strSize = str.size(); + size_t mi = 0; + std::vector poslist; + poslist.clear(); + while (mi < strSize) { + if (str[mi] == '-' || isdigit(str[mi])) { + auto head = mi; + mi++; + while (mi < strSize && (isdigit(str[mi]))) { mi++; - while (mi < strSize && (isdigit(str[mi]))) { - mi++; - } - poslist.push_back(std::stoi(asString(str.substr(head, mi - head)))); } - mi++; - } - auto poslistSize = poslist.size(); - if (poslistSize > 0) { - bias.x -= poslist[0]; + poslist.push_back(std::stoi(asString(str.substr(head, mi - head)))); } - if (poslistSize > 1) { - bias.y -= poslist[1]; - } - if (poslistSize > 2) { - bias.z -= poslist[2]; - } - return; + mi++; } - bool ClipboardPattern::hasBlock(class Block const* block) { - for (auto& x : clipboard->blockslist) { - if (x.blocks.has_value() && block == x.blocks.value().first) { - return true; - } + auto poslistSize = poslist.size(); + if (poslistSize > 0) { + bias.x -= poslist[0]; + } + if (poslistSize > 1) { + bias.y -= poslist[1]; + } + if (poslistSize > 2) { + bias.z -= poslist[2]; + } + return; +} +bool ClipboardPattern::hasBlock(class Block const* block) { + for (auto& x : clipboard->blockslist) { + if (x.blocks.has_value() && block == x.blocks.value().first) { + return true; } - return false; } + return false; +} - bool ClipboardPattern::setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) { - if (clipboard != nullptr) { - return clipboard->getSetLoop(pos - bias).setBlock(pos, blockSource, *playerData, funcs, variables); - } - return false; +bool ClipboardPattern::setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos +) { + if (clipboard != nullptr) { + return clipboard->getSetLoop(pos - bias) + .setBlock(pos, blockSource, *playerData, funcs, variables); } -} // namespace worldedit \ No newline at end of file + return false; +} +} // namespace we \ No newline at end of file diff --git a/old/core/store/ClipboardPattern.h b/old/core/store/ClipboardPattern.h index 1a5a0f1..12363d9 100644 --- a/old/core/store/ClipboardPattern.h +++ b/old/core/store/ClipboardPattern.h @@ -1,24 +1,23 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #pragma once #include "Pattern.h" -namespace worldedit { - class ClipboardPattern final : public Pattern { - public: - BlockPos bias; - class Clipboard* clipboard; +namespace we { +class ClipboardPattern : public Pattern { +public: + BlockPos bias; + class Clipboard* clipboard; - ClipboardPattern(std::string_view str, std::string_view xuid); + ClipboardPattern(std::string_view str, std::string_view xuid); - bool hasBlock(class Block const* block) override; + bool hasBlock(class Block const* block) override; - bool setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) override; - }; -} // namespace worldedit \ No newline at end of file + bool setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos + ) override; +}; +} // namespace we \ No newline at end of file diff --git a/old/core/store/GradientPattern.cpp b/old/core/store/GradientPattern.cpp index b7d6eda..238548d 100644 --- a/old/core/store/GradientPattern.cpp +++ b/old/core/store/GradientPattern.cpp @@ -1,114 +1,121 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #include "GradientPattern.h" +#include "Nlohmann/json.hpp" #include "WorldEdit.h" -#include "utils/StringTool.h" #include "utils/StringHelper.h" -#include "Nlohmann/json.hpp" +#include "utils/StringTool.h" -namespace worldedit { - GradientPattern::GradientPattern(std::string_view str, std::string_view xuid) : Pattern(xuid) { - type = Pattern::PatternType::GRADIENT; - if (frontIs(str, "#lighten")) { - lighten = true; - } +namespace we { +GradientPattern::GradientPattern(std::string_view str, std::string_view xuid) +: Pattern(xuid) { + type = Pattern::PatternType::GRADIENT; + if (frontIs(str, "#lighten")) { + lighten = true; + } - nlohmann::json list; - std::ifstream i(WE_DIR + "mappings/block_gradient.json"); - i >> list; + nlohmann::json list; + std::ifstream i(WE_DIR + "mappings/block_gradient.json"); + i >> list; - phmap::flat_hash_map>> tmpMap; - for (auto& g : list.items()) { - std::string keyGroup = g.key(); - if (!g.value().is_object()) { + phmap::flat_hash_map< + std::string, + phmap::flat_hash_map>> + tmpMap; + for (auto& g : list.items()) { + std::string keyGroup = g.key(); + if (!g.value().is_object()) { + continue; + } + for (auto& k : g.value().items()) { + std::string key = k.key(); + if (!k.value().is_array()) { continue; } - for (auto& k : g.value().items()) { - std::string key = k.key(); - if (!k.value().is_array()) { + auto& blockVector = tmpMap[keyGroup][keyGroup + ":" + key]; + blockVector.clear(); + for (auto& b : k.value()) { + if (!b.is_string()) { continue; } - auto& blockVector = tmpMap[keyGroup][keyGroup + ":" + key]; - blockVector.clear(); - for (auto& b : k.value()) { - if (!b.is_string()) { - continue; - } - Block const* block = tryGetBlockFromAllVersion(b); - if (block == nullptr) { - continue; - } - blockVector.push_back(block); + Block const* block = tryGetBlockFromAllVersion(b); + if (block == nullptr) { + continue; } + blockVector.push_back(block); } } + } - if (lighten) { - str = str.substr(8); - } else { - str = str.substr(7); + if (lighten) { + str = str.substr(8); + } else { + str = str.substr(7); + } + if (str.length() == 0) { + blockGradientMap = tmpMap["nc"]; + } else { + if (str.front() == '[') { + str = str.substr(1); } - if (str.length() == 0) { - blockGradientMap = tmpMap["nc"]; - } else { - if (str.front() == '[') { - str = str.substr(1); - } - if (str.back() == ']') { - str = str.substr(0, str.length() - 1); - } - auto tmpVec = SplitStrWithPattern(asString(str), ","); - phmap::flat_hash_set op(tmpVec.begin(), tmpVec.end()); - if (!op.contains("!nc")) { - op.insert("nc"); - } - for (auto& g : tmpMap) { - if (op.contains(g.first)) { - blockGradientMap.insert(g.second.begin(), g.second.end()); - } - } - for (auto& p : op) { - if (p[0] == '!' && blockGradientMap.contains(p.substr(1))) { - blockGradientMap.erase(p.substr(1)); - } + if (str.back() == ']') { + str = str.substr(0, str.length() - 1); + } + auto tmpVec = SplitStrWithPattern(asString(str), ","); + phmap::flat_hash_set op(tmpVec.begin(), tmpVec.end()); + if (!op.contains("!nc")) { + op.insert("nc"); + } + for (auto& g : tmpMap) { + if (op.contains(g.first)) { + blockGradientMap.insert(g.second.begin(), g.second.end()); } } - for (auto& [vName, vec] : blockGradientMap) { - for (int i = 0; i < vec.size(); i++) { - gradientNameMap[vec[i]] = std::make_pair(vName, i); + for (auto& p : op) { + if (p[0] == '!' && blockGradientMap.contains(p.substr(1))) { + blockGradientMap.erase(p.substr(1)); } } } - - class Block const* GradientPattern::getBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs) { - return nullptr; + for (auto& [vName, vec] : blockGradientMap) { + for (int i = 0; i < vec.size(); i++) { + gradientNameMap[vec[i]] = std::make_pair(vName, i); + } } +} - bool GradientPattern::hasBlock(class Block const* block) { - return gradientNameMap.find(block) != gradientNameMap.end(); - } +class Block const* GradientPattern::getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs +) { + return nullptr; +} - bool GradientPattern::setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) { - Block const* block = &blockSource->getBlock(pos); - if (hasBlock(block)) { - auto [name, iter] = gradientNameMap[block]; - auto& blocklist = blockGradientMap[name]; - if (lighten && iter >= 1) { - --iter; - return playerData->setBlockSimple(blockSource, funcs, variables, pos, blocklist[iter]); - } else if (!lighten) { - ++iter; - if (iter < blocklist.size()) { - return playerData->setBlockSimple(blockSource, funcs, variables, pos, blocklist[iter]); - } +bool GradientPattern::hasBlock(class Block const* block) { + return gradientNameMap.find(block) != gradientNameMap.end(); +} + +bool GradientPattern::setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos +) { + Block const* block = &blockSource->getBlock(pos); + if (hasBlock(block)) { + auto [name, iter] = gradientNameMap[block]; + auto& blocklist = blockGradientMap[name]; + if (lighten && iter >= 1) { + --iter; + return playerData + ->setBlockSimple(blockSource, funcs, variables, pos, blocklist[iter]); + } else if (!lighten) { + ++iter; + if (iter < blocklist.size()) { + return playerData + ->setBlockSimple(blockSource, funcs, variables, pos, blocklist[iter]); } } - return false; } -} // namespace worldedit \ No newline at end of file + return false; +} +} // namespace we \ No newline at end of file diff --git a/old/core/store/GradientPattern.h b/old/core/store/GradientPattern.h index 4f42b1f..309fc40 100644 --- a/old/core/store/GradientPattern.h +++ b/old/core/store/GradientPattern.h @@ -1,29 +1,30 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #pragma once #include "Pattern.h" -namespace worldedit { - class GradientPattern final : public Pattern { - public: - phmap::flat_hash_map> gradientNameMap; - phmap::flat_hash_map> blockGradientMap; +namespace we { +class GradientPattern : public Pattern { +public: + phmap::flat_hash_map> gradientNameMap; + phmap::flat_hash_map> blockGradientMap; - bool lighten = false; + bool lighten = false; - GradientPattern(std::string_view str, std::string_view xuid); + GradientPattern(std::string_view str, std::string_view xuid); - class Block const* getBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs) override; + class Block const* getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ) override; - bool hasBlock(class Block const* block) override; + bool hasBlock(class Block const* block) override; - bool setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) override; - }; -} // namespace worldedit \ No newline at end of file + bool setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos + ) override; +}; +} // namespace we \ No newline at end of file diff --git a/old/core/store/History.cpp b/old/core/store/History.cpp index a38a987..1669057 100644 --- a/old/core/store/History.cpp +++ b/old/core/store/History.cpp @@ -1,7 +1,4 @@ -// -// Created by OEOTYAN on 2023/03/26. -// #include "History.h" -namespace worldedit {} // namespace worldedit \ No newline at end of file +namespace we {} // namespace we \ No newline at end of file diff --git a/old/core/store/History.h b/old/core/store/History.h index 20901a4..0da7c54 100644 --- a/old/core/store/History.h +++ b/old/core/store/History.h @@ -1,31 +1,31 @@ -// -// Created by OEOTYAN on 2023/03/26. -// #pragma once #include "Globals.h" -#include "mc/CompoundTag.hpp" -#include "mc/BlockActor.hpp" #include "mc/Biome.hpp" +#include "mc/BlockActor.hpp" +#include "mc/CompoundTag.hpp" -namespace worldedit { +namespace we { - class ChunkHistory { - public: - phmap::flat_hash_set mAddedEntities; - phmap::flat_hash_map> mRemovedEntities; - phmap::flat_hash_map> mBlockEntities; - phmap::flat_hash_map>> mBiomes; - phmap::flat_hash_map, 2>>> mBlocks; - }; - class History { - public: - class BlockSource* mBlockSource; - short minHeight; - bool needEntities = false; - bool needBiomes = false; - bool used = false; - phmap::flat_hash_set storedPos; - phmap::flat_hash_map mChunks; - }; -} // namespace worldedit +class ChunkHistory { +public: + phmap::flat_hash_set mAddedEntities; + phmap::flat_hash_map> mRemovedEntities; + phmap::flat_hash_map> mBlockEntities; + phmap::flat_hash_map>> mBiomes; + phmap::flat_hash_map< + SubChunkPos, + std::unique_ptr, 2>>> + mBlocks; +}; +class History { +public: + class BlockSource* mBlockSource; + short minHeight; + bool needEntities = false; + bool needBiomes = false; + bool used = false; + phmap::flat_hash_set storedPos; + phmap::flat_hash_map mChunks; +}; +} // namespace we diff --git a/old/core/store/Pattern.cpp b/old/core/store/Pattern.cpp index fd1f87a..a34ed3a 100644 --- a/old/core/store/Pattern.cpp +++ b/old/core/store/Pattern.cpp @@ -1,28 +1,24 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "Patterns.h" #include "WorldEdit.h" #include "utils/StringTool.h" -namespace worldedit { +namespace we { - Pattern::Pattern(std::string_view xuid) { - playerData = &getPlayersData(xuid); - } +Pattern::Pattern(std::string_view xuid) { playerData = &getPlayersData(xuid); } - std::unique_ptr Pattern::createPattern(std::string_view p, std::string_view xuid) { - if (frontIs(p, "#hand")) { - return std::make_unique(BlockListPattern(p, xuid)); - } else if (frontIs(p, "#lighten") || frontIs(p, "#darken")) { - return std::make_unique(GradientPattern(p, xuid)); - } else if (frontIs(p, "#clipboard")) { - return std::make_unique(ClipboardPattern(p, xuid)); - } else { - return std::make_unique(BlockListPattern(p, xuid)); - } - return nullptr; +std::unique_ptr +Pattern::createPattern(std::string_view p, std::string_view xuid) { + if (frontIs(p, "#hand")) { + return std::make_unique(BlockListPattern(p, xuid)); + } else if (frontIs(p, "#lighten") || frontIs(p, "#darken")) { + return std::make_unique(GradientPattern(p, xuid)); + } else if (frontIs(p, "#clipboard")) { + return std::make_unique(ClipboardPattern(p, xuid)); + } else { + return std::make_unique(BlockListPattern(p, xuid)); } + return nullptr; +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/store/Pattern.h b/old/core/store/Pattern.h index fd90359..bc2b6f3 100644 --- a/old/core/store/Pattern.h +++ b/old/core/store/Pattern.h @@ -1,44 +1,46 @@ -// -// Created by OEOTYAN on 2022/05/18. -// #pragma once #include "Globals.h" #include "eval/Eval.h" -namespace worldedit { +namespace we { - class Pattern { - public: - enum class PatternType { - NONE, - BLOCKLIST, - HAND, - CLIPBOARD, - GRADIENT, - }; +class Pattern { +public: + enum class PatternType { + NONE, + BLOCKLIST, + HAND, + CLIPBOARD, + GRADIENT, + }; - class PlayerData* playerData = nullptr; + class PlayerData* playerData = nullptr; - PatternType type = PatternType::NONE; + PatternType type = PatternType::NONE; - Pattern() = default; - Pattern(std::string_view xuid); + Pattern() = default; + Pattern(std::string_view xuid); - virtual class Block const* getBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs) { - return nullptr; - } + virtual class Block const* getBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs + ) { + return nullptr; + } - virtual bool hasBlock(class Block const* block) { return false; } + virtual bool hasBlock(class Block const* block) { return false; } - virtual bool setBlock(const phmap::flat_hash_map<::std::string, double>& variables, - class EvalFunctions& funcs, - BlockSource* blockSource, - const BlockPos& pos) { - return false; - } + virtual bool setBlock( + const phmap::flat_hash_map<::std::string, double>& variables, + class EvalFunctions& funcs, + BlockSource* blockSource, + BlockPos const& pos + ) { + return false; + } - static std::unique_ptr createPattern(std::string_view p, std::string_view xuid); - }; -} // namespace worldedit \ No newline at end of file + static std::unique_ptr + createPattern(std::string_view p, std::string_view xuid); +}; +} // namespace we \ No newline at end of file diff --git a/old/core/store/Patterns.h b/old/core/store/Patterns.h index ffaed2a..226bf62 100644 --- a/old/core/store/Patterns.h +++ b/old/core/store/Patterns.h @@ -1,10 +1,7 @@ -// -// Created by OEOTYAN on 2023/02/02. -// #pragma once -#include "Pattern.h" -#include "GradientPattern.h" +#include "BlockListPattern.h" #include "ClipboardPattern.h" -#include "BlockListPattern.h" \ No newline at end of file +#include "GradientPattern.h" +#include "Pattern.h" diff --git a/old/core/subscribe/player.cpp b/old/core/subscribe/player.cpp index 06e4db0..6ae6121 100644 --- a/old/core/subscribe/player.cpp +++ b/old/core/subscribe/player.cpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/06/10. -// #include "player.hpp" #include "brush/Brushs.h" #include @@ -9,279 +6,340 @@ #define MINIMUM__RESPONSE_TICK 3 -namespace worldedit { +namespace we { - bool playerLeftClick(Player* player, - const bool isLong, - class ItemStack* item, - BlockInstance& blockInstance, - FaceID mFace) { - static phmap::flat_hash_map tickMap; +bool playerLeftClick( + Player* player, + const bool isLong, + class ItemStack* item, + BlockInstance& blockInstance, + FaceID mFace +) { + static phmap::flat_hash_map tickMap; - if (!(player->isOP() && player->isCreative())) { - return true; - } + if (!(player->isOP() && player->isCreative())) { + return true; + } - bool needDiscard = false; + bool needDiscard = false; - auto xuid = player->getXuid(); - long long tick = player->getLevel().getCurrentServerTick().t; - if (tickMap.contains(xuid)) { - if (abs(tick - tickMap[xuid]) < MINIMUM__RESPONSE_TICK) { - needDiscard = true; - } + auto xuid = player->getXuid(); + long long tick = player->getLevel().getCurrentServerTick().t; + if (tickMap.contains(xuid)) { + if (abs(tick - tickMap[xuid]) < MINIMUM__RESPONSE_TICK) { + needDiscard = true; } - auto& playerData = getPlayersData(xuid); + } + auto& playerData = getPlayersData(xuid); - auto itemName = item->getTypeName(); + auto itemName = item->getTypeName(); - if (itemName == "minecraft:wooden_axe") { - if (!isLong) { - tickMap[xuid] = tick; - if (!needDiscard) { - playerData.changeMainPos(blockInstance); - } - return false; - } - } else { + if (itemName == "minecraft:wooden_axe") { + if (!isLong) { tickMap[xuid] = tick; - itemName += std::to_string(item->getAuxValue()); - if (playerData.brushMap.contains(itemName)) { - if (!needDiscard) { - auto& brush = playerData.brushMap[itemName]; - if (brush->lneedFace && blockInstance != BlockInstance::Null) { - BlockPos bPos = blockInstance.getPosition(); - switch (mFace) { - case FaceID::Down: - bPos.y -= 1; - break; - case FaceID::Up: - bPos.y += 1; - break; - case FaceID::North: - bPos.z -= 1; - break; - case FaceID::South: - bPos.z += 1; - break; - case FaceID::West: - bPos.x -= 1; - break; - case FaceID::East: - bPos.x += 1; - break; - default: - break; - } - auto bi = blockInstance.getBlockSource()->getBlockInstance(bPos); - brush->lset(player, bi); - } else { - brush->lset(player, blockInstance); + if (!needDiscard) { + playerData.changeMainPos(blockInstance); + } + return false; + } + } else { + tickMap[xuid] = tick; + itemName += std::to_string(item->getAuxValue()); + if (playerData.brushMap.contains(itemName)) { + if (!needDiscard) { + auto& brush = playerData.brushMap[itemName]; + if (brush->lneedFace && blockInstance != BlockInstance::Null) { + BlockPos bPos = blockInstance.getPosition(); + switch (mFace) { + case FaceID::Down: + bPos.y -= 1; + break; + case FaceID::Up: + bPos.y += 1; + break; + case FaceID::North: + bPos.z -= 1; + break; + case FaceID::South: + bPos.z += 1; + break; + case FaceID::West: + bPos.x -= 1; + break; + case FaceID::East: + bPos.x += 1; + break; + default: + break; } + auto bi = blockInstance.getBlockSource()->getBlockInstance(bPos); + brush->lset(player, bi); + } else { + brush->lset(player, blockInstance); } - return false; } + return false; } - return true; } + return true; +} - bool playerRightClick(Player* player, - const bool isLong, - class ItemStack* item, - BlockInstance& blockInstance, - FaceID mFace) { - static phmap::flat_hash_map tickMap; +bool playerRightClick( + Player* player, + const bool isLong, + class ItemStack* item, + BlockInstance& blockInstance, + FaceID mFace +) { + static phmap::flat_hash_map tickMap; - if (!(player->isOP() && player->isCreative())) { - return true; - } + if (!(player->isOP() && player->isCreative())) { + return true; + } - bool needDiscard = false; + bool needDiscard = false; - auto xuid = player->getXuid(); - long long tick = player->getLevel().getCurrentServerTick().t; - if (tickMap.contains(xuid)) { - if (abs(tick - tickMap[xuid]) < MINIMUM__RESPONSE_TICK) { - needDiscard = true; - } + auto xuid = player->getXuid(); + long long tick = player->getLevel().getCurrentServerTick().t; + if (tickMap.contains(xuid)) { + if (abs(tick - tickMap[xuid]) < MINIMUM__RESPONSE_TICK) { + needDiscard = true; } + } - auto itemName = item->getTypeName(); - auto& playerData = getPlayersData(xuid); + auto itemName = item->getTypeName(); + auto& playerData = getPlayersData(xuid); - if (item->getTypeName() == "minecraft:wooden_axe") { - if (!isLong) { - tickMap[xuid] = tick; - if (!needDiscard) { - playerData.changeVicePos(blockInstance); - } - return false; - } - } else { + if (item->getTypeName() == "minecraft:wooden_axe") { + if (!isLong) { tickMap[xuid] = tick; - itemName += std::to_string(item->getAuxValue()); + if (!needDiscard) { + playerData.changeVicePos(blockInstance); + } + return false; + } + } else { + tickMap[xuid] = tick; + itemName += std::to_string(item->getAuxValue()); - if (playerData.brushMap.contains(itemName)) { - if (!needDiscard) { - auto& brush = playerData.brushMap[itemName]; - if (brush->needFace && blockInstance != BlockInstance::Null) { - BlockPos bPos = blockInstance.getPosition(); - switch (mFace) { - case FaceID::Down: - bPos.y -= 1; - break; - case FaceID::Up: - bPos.y += 1; - break; - case FaceID::North: - bPos.z -= 1; - break; - case FaceID::South: - bPos.z += 1; - break; - case FaceID::West: - bPos.x -= 1; - break; - case FaceID::East: - bPos.x += 1; - break; - default: - break; - } - auto bi = blockInstance.getBlockSource()->getBlockInstance(bPos); - brush->set(player, bi); - } else { - brush->set(player, blockInstance); + if (playerData.brushMap.contains(itemName)) { + if (!needDiscard) { + auto& brush = playerData.brushMap[itemName]; + if (brush->needFace && blockInstance != BlockInstance::Null) { + BlockPos bPos = blockInstance.getPosition(); + switch (mFace) { + case FaceID::Down: + bPos.y -= 1; + break; + case FaceID::Up: + bPos.y += 1; + break; + case FaceID::North: + bPos.z -= 1; + break; + case FaceID::South: + bPos.z += 1; + break; + case FaceID::West: + bPos.x -= 1; + break; + case FaceID::East: + bPos.x += 1; + break; + default: + break; } + auto bi = blockInstance.getBlockSource()->getBlockInstance(bPos); + brush->set(player, bi); + } else { + brush->set(player, blockInstance); } - return false; } + return false; } - return true; } + return true; +} - void playerSubscribe() { - Event::PlayerUseItemOnEvent::subscribe([](const Event::PlayerUseItemOnEvent& ev) { - if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { - return true; - } - return playerRightClick(ev.mPlayer, false, ev.mItemStack, *const_cast(&ev.mBlockInstance), - static_cast(ev.mFace)); - }); - Event::PlayerUseItemEvent::subscribe([](const Event::PlayerUseItemEvent& ev) { - if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { - return true; - } - bool requiereWater = true; - if (Level::getBlock(ev.mPlayer->getPosition().toBlockPos(), ev.mPlayer->getDimensionId()) != - BedrockBlocks::mAir) { - requiereWater = false; - } - FaceID face; - BlockInstance blockInstance = ev.mPlayer->getBlockFromViewVector(face, requiereWater, false, 2048.0f); - return playerRightClick(ev.mPlayer, true, ev.mItemStack, blockInstance, face); - }); +void playerSubscribe() { + Event::PlayerUseItemOnEvent::subscribe([](const Event::PlayerUseItemOnEvent& ev) { + if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { + return true; + } + return playerRightClick( + ev.mPlayer, + false, + ev.mItemStack, + *const_cast(&ev.mBlockInstance), + static_cast(ev.mFace) + ); + }); + Event::PlayerUseItemEvent::subscribe([](const Event::PlayerUseItemEvent& ev) { + if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { + return true; + } + bool requiereWater = true; + if (Level::getBlock( + ev.mPlayer->getPosition().toBlockPos(), + ev.mPlayer->getDimensionId() + ) + != BedrockBlocks::mAir) { + requiereWater = false; + } + FaceID face; + BlockInstance blockInstance = + ev.mPlayer->getBlockFromViewVector(face, requiereWater, false, 2048.0f); + return playerRightClick(ev.mPlayer, true, ev.mItemStack, blockInstance, face); + }); - Event::PlayerDestroyBlockEvent::subscribe([](const Event::PlayerDestroyBlockEvent& ev) { - if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { - return true; - } - bool requiereWater = true; - if (Level::getBlock(ev.mPlayer->getPosition().toBlockPos(), ev.mPlayer->getDimensionId()) != - BedrockBlocks::mAir) { - requiereWater = false; - } - FaceID face; - ev.mPlayer->getBlockFromViewVector(face, requiereWater); - bool res = playerLeftClick(ev.mPlayer, false, ev.mPlayer->getHandSlot(), - *const_cast(&ev.mBlockInstance), face); - if (!res) { - Schedule::nextTick([=]() { - auto be = const_cast(&ev.mBlockInstance)->getBlockEntity(); - if (be) { - auto pkt = be->getServerUpdatePacket(*(ev.mPlayer->getBlockSource())); - if (pkt != nullptr) { - ev.mPlayer->sendNetworkPacket(*(pkt.get())); - } - if (be->getType() == BlockActorType::Chest && ((ChestBlockActor*)be)->isLargeChest()) { - auto pairChest = ev.mPlayer->getBlockSource()->getBlockEntity( - ((ChestBlockActor*)be)->getPairedChestPosition()); - if (pairChest) { - auto ppkt = pairChest->getServerUpdatePacket(*(ev.mPlayer->getBlockSource())); - if (ppkt != nullptr) { - ev.mPlayer->sendNetworkPacket(*(ppkt.get())); - } + Event::PlayerDestroyBlockEvent::subscribe([](const Event::PlayerDestroyBlockEvent& ev + ) { + if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { + return true; + } + bool requiereWater = true; + if (Level::getBlock( + ev.mPlayer->getPosition().toBlockPos(), + ev.mPlayer->getDimensionId() + ) + != BedrockBlocks::mAir) { + requiereWater = false; + } + FaceID face; + ev.mPlayer->getBlockFromViewVector(face, requiereWater); + bool res = playerLeftClick( + ev.mPlayer, + false, + ev.mPlayer->getHandSlot(), + *const_cast(&ev.mBlockInstance), + face + ); + if (!res) { + Schedule::nextTick([=]() { + auto be = + const_cast(&ev.mBlockInstance)->getBlockEntity(); + if (be) { + auto pkt = be->getServerUpdatePacket(*(ev.mPlayer->getBlockSource())); + if (pkt != nullptr) { + ev.mPlayer->sendNetworkPacket(*(pkt.get())); + } + if (be->getType() == BlockActorType::Chest + && ((ChestBlockActor*)be)->isLargeChest()) { + auto pairChest = ev.mPlayer->getBlockSource()->getBlockEntity( + ((ChestBlockActor*)be)->getPairedChestPosition() + ); + if (pairChest) { + auto ppkt = pairChest->getServerUpdatePacket( + *(ev.mPlayer->getBlockSource()) + ); + if (ppkt != nullptr) { + ev.mPlayer->sendNetworkPacket(*(ppkt.get())); } } } - }); - } - return res; - }); + } + }); + } + return res; + }); - Event::PlayerOpenContainerEvent::subscribe([](const Event::PlayerOpenContainerEvent& ev) { + Event::PlayerOpenContainerEvent::subscribe( + [](const Event::PlayerOpenContainerEvent& ev) { if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { return true; } bool requiereWater = true; - if (Level::getBlock(ev.mPlayer->getPosition().toBlockPos(), ev.mPlayer->getDimensionId()) != - BedrockBlocks::mAir) { + if (Level::getBlock( + ev.mPlayer->getPosition().toBlockPos(), + ev.mPlayer->getDimensionId() + ) + != BedrockBlocks::mAir) { requiereWater = false; } - FaceID face; - BlockInstance blockInstance = ev.mPlayer->getBlockFromViewVector(face, requiereWater); - return playerRightClick(ev.mPlayer, false, ev.mPlayer->getHandSlot(), blockInstance, face); - }); + FaceID face; + BlockInstance blockInstance = + ev.mPlayer->getBlockFromViewVector(face, requiereWater); + return playerRightClick( + ev.mPlayer, + false, + ev.mPlayer->getHandSlot(), + blockInstance, + face + ); + } + ); - Event::PlayerPlaceBlockEvent::subscribe([](const Event::PlayerPlaceBlockEvent& ev) { - if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { - return true; - } - bool requiereWater = true; - if (Level::getBlock(ev.mPlayer->getPosition().toBlockPos(), ev.mPlayer->getDimensionId()) != - BedrockBlocks::mAir) { - requiereWater = false; - } - FaceID face; - BlockInstance blockInstance = ev.mPlayer->getBlockFromViewVector(face, requiereWater); - return playerRightClick(ev.mPlayer, false, ev.mPlayer->getHandSlot(), blockInstance, face); - }); - // Event::PlayerSwingEvent::subscribe([](const Event::PlayerSwingEvent& ev) -> bool { - // Player* player = ev.mPlayer; + Event::PlayerPlaceBlockEvent::subscribe([](const Event::PlayerPlaceBlockEvent& ev) { + if (!(ev.mPlayer->isOP() && ev.mPlayer->isCreative())) { + return true; + } + bool requiereWater = true; + if (Level::getBlock( + ev.mPlayer->getPosition().toBlockPos(), + ev.mPlayer->getDimensionId() + ) + != BedrockBlocks::mAir) { + requiereWater = false; + } + FaceID face; + BlockInstance blockInstance = + ev.mPlayer->getBlockFromViewVector(face, requiereWater); + return playerRightClick( + ev.mPlayer, + false, + ev.mPlayer->getHandSlot(), + blockInstance, + face + ); + }); + // Event::PlayerSwingEvent::subscribe([](const Event::PlayerSwingEvent& ev) -> bool { + // Player* player = ev.mPlayer; - // if (!(player->isOP() && player->isCreative())) { - // return true; - // } - // bool requiereWater = true; - // if (Level::getBlock(player->getPosition().toBlockPos(), player->getDimensionId()) != BedrockBlocks::mAir) { - // requiereWater = false; - // } - // FaceID face; - // BlockInstance blockInstance = player->getBlockFromViewVector(face, requiereWater, false, 2048.0f); - // worldedit::playerLeftClick(player, true, player->getHandSlot(), blockInstance, face); - // return true; - // }); - } -} // namespace worldedit + // if (!(player->isOP() && player->isCreative())) { + // return true; + // } + // bool requiereWater = true; + // if (Level::getBlock(player->getPosition().toBlockPos(), player->getDimensionId()) + // != BedrockBlocks::mAir) { + // requiereWater = false; + // } + // FaceID face; + // BlockInstance blockInstance = player->getBlockFromViewVector(face, requiereWater, + // false, 2048.0f); worldedit::playerLeftClick(player, true, player->getHandSlot(), + // blockInstance, face); + // return true; + // }); +} +} // namespace we -THook(void, - "?handle@ServerNetworkHandler@@UEAAXAEBVNetworkIdentifier@@" - "AEBVAnimatePacket@@@Z", - ServerNetworkHandler* serverNetworkHandler, - NetworkIdentifier const& networkIdentifier, - AnimatePacket const& animatePacket) { +THook( + void, + "?handle@ServerNetworkHandler@@UEAAXAEBVNetworkIdentifier@@" + "AEBVAnimatePacket@@@Z", + ServerNetworkHandler* serverNetworkHandler, + NetworkIdentifier const& networkIdentifier, + AnimatePacket const& animatePacket +) { if (animatePacket.mAction == AnimatePacket::Action::Swing) { Player* player = serverNetworkHandler->getServerPlayer(networkIdentifier); if (!(player->isOP() && player->isCreative())) { return original(serverNetworkHandler, networkIdentifier, animatePacket); } bool requiereWater = true; - if (Level::getBlock(player->getPosition().toBlockPos(), player->getDimensionId()) != BedrockBlocks::mAir) { + if (Level::getBlock(player->getPosition().toBlockPos(), player->getDimensionId()) + != BedrockBlocks::mAir) { requiereWater = false; } - FaceID face; - BlockInstance blockInstance = player->getBlockFromViewVector(face, requiereWater, false, 2048.0f); - worldedit::playerLeftClick(player, true, player->getHandSlot(), blockInstance, face); + FaceID face; + BlockInstance blockInstance = + player->getBlockFromViewVector(face, requiereWater, false, 2048.0f); + worldedit::playerLeftClick( + player, + true, + player->getHandSlot(), + blockInstance, + face + ); } return original(serverNetworkHandler, networkIdentifier, animatePacket); } \ No newline at end of file diff --git a/old/core/subscribe/player.hpp b/old/core/subscribe/player.hpp index afdc777..dc7b2ab 100644 --- a/old/core/subscribe/player.hpp +++ b/old/core/subscribe/player.hpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/05/16. -// #pragma once #include "Globals.h" #include @@ -12,21 +9,25 @@ #include // #include // #include -#include -#include -#include #include "WorldEdit.h" +#include +#include +#include -namespace worldedit { - void playerSubscribe(); - bool playerLeftClick(Player* player, - const bool isLong, - class ItemStack* item, - BlockInstance& blockInstance, - FaceID mFace); - bool playerRightClick(Player* player, - const bool isLong, - class ItemStack* item, - BlockInstance& blockInstance, - FaceID mFace); -} // namespace worldedit \ No newline at end of file +namespace we { +void playerSubscribe(); +bool playerLeftClick( + Player* player, + const bool isLong, + class ItemStack* item, + BlockInstance& blockInstance, + FaceID mFace +); +bool playerRightClick( + Player* player, + const bool isLong, + class ItemStack* item, + BlockInstance& blockInstance, + FaceID mFace +); +} // namespace we \ No newline at end of file diff --git a/old/core/subscribe/server.cpp b/old/core/subscribe/server.cpp index 06dd908..26fb229 100644 --- a/old/core/subscribe/server.cpp +++ b/old/core/subscribe/server.cpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/07/18. -// #include "server.hpp" #include "WorldEdit.h" #include @@ -9,69 +6,80 @@ #include // #include // #include -#include "region/Region.h" #include "command/allCommand.hpp" +#include "region/Region.h" -namespace worldedit { - void serverSubscribe() { - Event::ServerStartedEvent::subscribe([](const Event::ServerStartedEvent) { - // for (auto& k : BlockSerializationUtils::BLOCK_REPLACE_DATA_MAP){ - // std::cout << k.first.getString() << std::endl; - // } +namespace we { +void serverSubscribe() { + Event::ServerStartedEvent::subscribe([](const Event::ServerStartedEvent) { + // for (auto& k : BlockSerializationUtils::BLOCK_REPLACE_DATA_MAP){ + // std::cout << k.first.getString() << std::endl; + // } - javaBlockMapInit(); + javaBlockMapInit(); - commandsSetup(); + commandsSetup(); - blockColorMapInit(); + blockColorMapInit(); - auto& playerDataMap = getPlayersDataMap(); - Schedule::repeat( - [&]() { - Global->forEachPlayer([&](Player& player) -> bool { - auto xuid = player.getXuid(); - if (playerDataMap.contains(xuid)) { - auto& data = *playerDataMap[xuid]; - if (data.region != nullptr && data.region->hasSelected()) { - data.region->renderRegion(); - } + auto& playerDataMap = getPlayersDataMap(); + Schedule::repeat( + [&]() { + Global->forEachPlayer([&](Player& player) -> bool { + auto xuid = player.getXuid(); + if (playerDataMap.contains(xuid)) { + auto& data = *playerDataMap[xuid]; + if (data.region != nullptr && data.region->hasSelected()) { + data.region->renderRegion(); } + } - if (playerDataMap.contains(xuid)) { - auto& data = *playerDataMap[xuid]; - if (data.mainPosDim >= 0) { - if (data.mainPosTime <= 0) { - data.mainPosTime = 40; - globalPT().drawCuboid(AABB(Vec3(data.mainPos) - Vec3(0.07f, 0.07f, 0.07f), - Vec3(data.mainPos) + Vec3(1.07f, 1.07f, 1.07f)), - data.mainPosDim, mce::ColorPalette::RED); - } - --data.mainPosTime; + if (playerDataMap.contains(xuid)) { + auto& data = *playerDataMap[xuid]; + if (data.mainPosDim >= 0) { + if (data.mainPosTime <= 0) { + data.mainPosTime = 40; + globalPT().drawCuboid( + AABB( + Vec3(data.mainPos) - Vec3(0.07f, 0.07f, 0.07f), + Vec3(data.mainPos) + Vec3(1.07f, 1.07f, 1.07f) + ), + data.mainPosDim, + mce::ColorPalette::RED + ); } - if (data.vicePosDim >= 0) { - if (data.vicePosDim >= 0 && data.vicePosTime <= 0) { - data.vicePosTime = 40; - globalPT().drawCuboid(AABB(Vec3(data.vicePos) - Vec3(0.07f, 0.07f, 0.07f), - Vec3(data.vicePos) + Vec3(1.07f, 1.07f, 1.07f)), - data.vicePosDim, mce::ColorPalette::VATBLUE); - } - --data.vicePosTime; + --data.mainPosTime; + } + if (data.vicePosDim >= 0) { + if (data.vicePosDim >= 0 && data.vicePosTime <= 0) { + data.vicePosTime = 40; + globalPT().drawCuboid( + AABB( + Vec3(data.vicePos) - Vec3(0.07f, 0.07f, 0.07f), + Vec3(data.vicePos) + Vec3(1.07f, 1.07f, 1.07f) + ), + data.vicePosDim, + mce::ColorPalette::VATBLUE + ); } + --data.vicePosTime; } + } - return true; - }); - }, - 1); - // auto mapm = getBlockColorssMap(); - // std::ofstream outStr(WE_DIR + "structures/" + "filename" + - // ".txt", std::ios::out); for(auto aa : mapm) { - // outStr << "\"" << aa.first << "\" : {\n" << aa.second << - // "\n},\n"; - // } - // outStr.close(); + return true; + }); + }, + 1 + ); + // auto mapm = getBlockColorssMap(); + // std::ofstream outStr(WE_DIR + "structures/" + "filename" + + // ".txt", std::ios::out); for(auto aa : mapm) { + // outStr << "\"" << aa.first << "\" : {\n" << aa.second << + // "\n},\n"; + // } + // outStr.close(); - return true; - }); - } -} // namespace worldedit \ No newline at end of file + return true; + }); +} +} // namespace we \ No newline at end of file diff --git a/old/core/subscribe/server.hpp b/old/core/subscribe/server.hpp index cffaf8b..d59e9e8 100644 --- a/old/core/subscribe/server.hpp +++ b/old/core/subscribe/server.hpp @@ -1,8 +1,5 @@ -// -// Created by OEOTYAN on 2022/05/16. -// #pragma once -namespace worldedit { - void serverSubscribe(); -} // namespace worldedit \ No newline at end of file +namespace we { +void serverSubscribe(); +} // namespace we \ No newline at end of file diff --git a/old/core/subscribe/subscribeall.hpp b/old/core/subscribe/subscribeall.hpp index 9a32e1e..f052224 100644 --- a/old/core/subscribe/subscribeall.hpp +++ b/old/core/subscribe/subscribeall.hpp @@ -1,6 +1,3 @@ -// -// Created by OEOTYAN on 2022/05/16. -// #pragma once #include "subscribe/player.hpp" diff --git a/old/core/utils/ColorTool.cpp b/old/core/utils/ColorTool.cpp index b9448dc..afb0382 100644 --- a/old/core/utils/ColorTool.cpp +++ b/old/core/utils/ColorTool.cpp @@ -1,87 +1,86 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #include "ColorTool.h" #include "mixbox.h" -namespace worldedit { - mce::Color linearLerp(const mce::Color& k, const mce::Color& l, float m) { - return mce::Color::lerp(k.sRGBToLinear(), l.sRGBToLinear(), m).LinearTosRGB(); - } - mce::Color mixboxLerp(const mce::Color& k, const mce::Color& l, float m) { - mce::Color res; - mixbox_lerp_float(k.r, k.g, k.b, l.r, l.g, l.b, m, &res.r, &res.g, &res.b); - res.a = k.a * (1.0f - m) + l.a * m; - return res; - } - mce::Color linearAverage(phmap::flat_hash_map colorWithWeight) { - mce::Color finalColor; - int colorCount = 0; - for (auto& c : colorWithWeight) { - if (colorCount != 0) { - int lastColorCount = colorCount; - colorCount += c.second; - finalColor = linearLerp(c.first, finalColor, static_cast(lastColorCount) / colorCount); - } else { - colorCount = c.second; - finalColor = c.first; - } +namespace we { +mce::Color linearLerp(const mce::Color& k, const mce::Color& l, float m) { + return mce::Color::lerp(k.sRGBToLinear(), l.sRGBToLinear(), m).LinearTosRGB(); +} +mce::Color mixboxLerp(const mce::Color& k, const mce::Color& l, float m) { + mce::Color res; + mixbox_lerp_float(k.r, k.g, k.b, l.r, l.g, l.b, m, &res.r, &res.g, &res.b); + res.a = k.a * (1.0f - m) + l.a * m; + return res; +} +mce::Color linearAverage(phmap::flat_hash_map colorWithWeight) { + mce::Color finalColor; + int colorCount = 0; + for (auto& c : colorWithWeight) { + if (colorCount != 0) { + int lastColorCount = colorCount; + colorCount += c.second; + finalColor = linearLerp( + c.first, + finalColor, + static_cast(lastColorCount) / colorCount + ); + } else { + colorCount = c.second; + finalColor = c.first; } - return finalColor; } - mce::Color mixboxAverage(phmap::flat_hash_map colorWithWeight) { - mixbox_latent finallatent; - int colorCount = 0; - for (auto& c : colorWithWeight) { - if (colorCount != 0) { - int lastColorCount = colorCount; - colorCount += c.second; - float lerpK = static_cast(lastColorCount) / colorCount; - mixbox_latent tmplatent; + return finalColor; +} +mce::Color mixboxAverage(phmap::flat_hash_map colorWithWeight) { + mixbox_latent finallatent; + int colorCount = 0; + for (auto& c : colorWithWeight) { + if (colorCount != 0) { + int lastColorCount = colorCount; + colorCount += c.second; + float lerpK = static_cast(lastColorCount) / colorCount; + mixbox_latent tmplatent; - mixbox_float_rgb_to_latent(c.first.r, c.first.g, c.first.b, tmplatent); + mixbox_float_rgb_to_latent(c.first.r, c.first.g, c.first.b, tmplatent); - for (int i = 0; i < MIXBOX_LATENT_SIZE; i++) { - finallatent[i] = std::lerp(tmplatent[i], finallatent[i], lerpK); - } - } else { - colorCount = c.second; - mixbox_float_rgb_to_latent(c.first.r, c.first.g, c.first.b, finallatent); + for (int i = 0; i < MIXBOX_LATENT_SIZE; i++) { + finallatent[i] = std::lerp(tmplatent[i], finallatent[i], lerpK); } + } else { + colorCount = c.second; + mixbox_float_rgb_to_latent(c.first.r, c.first.g, c.first.b, finallatent); } - mce::Color finalColor; - mixbox_latent_to_float_rgb(finallatent, &finalColor.r, &finalColor.g, &finalColor.b); - return finalColor; } + mce::Color finalColor; + mixbox_latent_to_float_rgb(finallatent, &finalColor.r, &finalColor.g, &finalColor.b); + return finalColor; +} - float clamp(float x, float lowerlimit, float upperlimit) { - if (x < lowerlimit) - x = lowerlimit; - if (x > upperlimit) - x = upperlimit; - return x; - } +float clamp(float x, float lowerlimit, float upperlimit) { + if (x < lowerlimit) x = lowerlimit; + if (x > upperlimit) x = upperlimit; + return x; +} - float smoothstep(float edge0, float edge1, float x) { - // Scale, and clamp x to 0..1 range - x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); +float smoothstep(float edge0, float edge1, float x) { + // Scale, and clamp x to 0..1 range + x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); - return x * x * (3 - 2 * x); - } + return x * x * (3 - 2 * x); +} - float smootherstep(float edge0, float edge1, float x) { - // Scale, and clamp x to 0..1 range - x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); - // Evaluate polynomial - return x * x * x * (x * (x * 6 - 15) + 10); - } +float smootherstep(float edge0, float edge1, float x) { + // Scale, and clamp x to 0..1 range + x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); + // Evaluate polynomial + return x * x * x * (x * (x * 6 - 15) + 10); +} - float smoothBrushAlpha(float r, float density, float opacity, unsigned short size) { - if (density == 1) { - return opacity * (r <= size); - } - return opacity * smoothstep(size, size * density, r); +float smoothBrushAlpha(float r, float density, float opacity, unsigned short size) { + if (density == 1) { + return opacity * (r <= size); } + return opacity * smoothstep(size, size * density, r); +} -} // namespace worldedit \ No newline at end of file +} // namespace we \ No newline at end of file diff --git a/old/core/utils/ColorTool.h b/old/core/utils/ColorTool.h index 901a573..5d36a88 100644 --- a/old/core/utils/ColorTool.h +++ b/old/core/utils/ColorTool.h @@ -1,22 +1,19 @@ -// -// Created by OEOTYAN on 2023/02/01. -// #pragma once #include "Globals.h" -namespace worldedit { - mce::Color linearLerp(const mce::Color& k, const mce::Color& l, float m); - mce::Color mixboxLerp(const mce::Color& k, const mce::Color& l, float m); - mce::Color linearAverage(phmap::flat_hash_map colorWithWeight); - mce::Color mixboxAverage(phmap::flat_hash_map colorWithWeight); +namespace we { +mce::Color linearLerp(const mce::Color& k, const mce::Color& l, float m); +mce::Color mixboxLerp(const mce::Color& k, const mce::Color& l, float m); +mce::Color linearAverage(phmap::flat_hash_map colorWithWeight); +mce::Color mixboxAverage(phmap::flat_hash_map colorWithWeight); - float clamp(float x, float lowerlimit, float upperlimit); +float clamp(float x, float lowerlimit, float upperlimit); - float smoothstep(float edge0, float edge1, float x); +float smoothstep(float edge0, float edge1, float x); - float smootherstep(float edge0, float edge1, float x); +float smootherstep(float edge0, float edge1, float x); - float smoothBrushAlpha(float r, float density, float opacity, unsigned short size); -} \ No newline at end of file +float smoothBrushAlpha(float r, float density, float opacity, unsigned short size); +} // namespace we \ No newline at end of file diff --git a/old/core/utils/StringTool.h b/old/core/utils/StringTool.h index 9b16f90..9e30e3f 100644 --- a/old/core/utils/StringTool.h +++ b/old/core/utils/StringTool.h @@ -1,76 +1,74 @@ -// -// Created by OEOTYAN on 2021/02/19. -// #pragma once -#include #include -namespace worldedit { +#include +namespace we { - namespace { - template - std::string fto_string(const T a_value, int i = 23, bool j = false) { - std::ostringstream out; - out.precision(i); - if (i < 23 && i > -1) { - if (j) { - out << std::fixed << std::setw(i + 3) << std::setfill(' ') << a_value; - } else { - out << std::fixed << a_value; - } - } else if (i < 0) { - out << std::setw(-i) << std::setfill(' ') << a_value; - } else { - out << a_value; - } - return out.str(); +namespace { +template +std::string fto_string(const T a_value, int i = 23, bool j = false) { + std::ostringstream out; + out.precision(i); + if (i < 23 && i > -1) { + if (j) { + out << std::fixed << std::setw(i + 3) << std::setfill(' ') << a_value; + } else { + out << std::fixed << a_value; } - } // namespace - - inline std::string toLowerString(std::string str) { - transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower); - return str; + } else if (i < 0) { + out << std::setw(-i) << std::setfill(' ') << a_value; + } else { + out << a_value; } + return out.str(); +} +} // namespace - inline void stringReplace(std::string& str, std::string_view fstr, std::string_view rep) { - std::string::size_type pos = 0; - std::string::size_type a = fstr.length(); - std::string::size_type b = rep.length(); - if (b == 0) - while ((pos = str.find(fstr, pos)) != std::string::npos) { - str.erase(pos, a); - } - else - while ((pos = str.find(fstr, pos)) != std::string::npos) { - str.replace(pos, a, rep); - pos += b; - } - } +inline std::string toLowerString(std::string str) { + transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower); + return str; +} - inline bool frontIs(std::string_view s, std::string_view front) { - if (s.substr(0, front.size()) == front) { - return true; +inline void stringReplace(std::string& str, std::string_view fstr, std::string_view rep) { + std::string::size_type pos = 0; + std::string::size_type a = fstr.length(); + std::string::size_type b = rep.length(); + if (b == 0) + while ((pos = str.find(fstr, pos)) != std::string::npos) { + str.erase(pos, a); + } + else + while ((pos = str.find(fstr, pos)) != std::string::npos) { + str.replace(pos, a, rep); + pos += b; } - return false; +} + +inline bool frontIs(std::string_view s, std::string_view front) { + if (s.substr(0, front.size()) == front) { + return true; } + return false; +} - inline bool isHex(char s) { - if ('A' <= s && s <= 'F') { - return true; - } - if ('a' <= s && s <= 'f') { - return true; - } - if ('0' <= s && s <= '9') { - return true; - } - return false; +inline bool isHex(char s) { + if ('A' <= s && s <= 'F') { + return true; } + if ('a' <= s && s <= 'f') { + return true; + } + if ('0' <= s && s <= '9') { + return true; + } + return false; +} - inline bool isColorHex(std::string_view x) { - if (x[0] == '#' && (isHex(x[1]) && isHex(x[2]) && isHex(x[3])) && - (x.length() == 4 || (x.length() == 7 && (isHex(x[4]) && isHex(x[5]) && isHex(x[6]))))) { - return true; - } - return false; +inline bool isColorHex(std::string_view x) { + if (x[0] == '#' && (isHex(x[1]) && isHex(x[2]) && isHex(x[3])) + && (x.length() == 4 + || (x.length() == 7 && (isHex(x[4]) && isHex(x[5]) && isHex(x[6]))))) { + return true; } -} // namespace worldedit \ No newline at end of file + return false; +} +} // namespace we \ No newline at end of file diff --git a/scripts/format_all.py b/scripts/format_all.py new file mode 100644 index 0000000..fbca83f --- /dev/null +++ b/scripts/format_all.py @@ -0,0 +1,41 @@ +# execute clang-format at src with multi-threading + +import os +import subprocess +import multiprocessing +import re + + +def format_file(file): + print("formatting {0}".format(file)) + + with open(file, "r") as f: + content = f.read() + with open(file, "w") as f: + if not content.endswith("\n"): + content += "\n" + if file.endswith(".h") and not content.startswith("#pragma once"): + content = "#pragma once\n" + content + f.write(content) + f.close() + + subprocess.run(["clang-format", "-i", file]) + + +def format_all(): + print("formatting") + pool = multiprocessing.Pool( + processes=max(multiprocessing.cpu_count()-2, 1)) + for root, dirs, files in os.walk("./src"): + for file in files: + if file.endswith(".h") or file.endswith(".cpp"): + pool.apply_async(format_file, (os.path.join(root, file),)) + pool.close() + pool.join() + + +if __name__ == "__main__": + try: + format_all() + except Exception as e: + print(f"An error occurred: {e}") diff --git a/src/region/ConvexRegion.cpp b/src/region/ConvexRegion.cpp new file mode 100644 index 0000000..97b7617 --- /dev/null +++ b/src/region/ConvexRegion.cpp @@ -0,0 +1,234 @@ + +#include "ConvexRegion.h" + +namespace we { +void ConvexRegion::updateBoundingBox() { + boundingBox.min = *vertices.begin(); + boundingBox.max = *vertices.begin(); + for (auto& v : vertices) { + boundingBox.min.x = std::min(boundingBox.min.x, v.x); + boundingBox.min.y = std::min(boundingBox.min.y, v.y); + boundingBox.min.z = std::min(boundingBox.min.z, v.z); + boundingBox.max.x = std::max(boundingBox.max.x, v.x); + boundingBox.max.y = std::max(boundingBox.max.y, v.y); + boundingBox.max.z = std::max(boundingBox.max.z, v.z); + } + for (auto& v : vertexBacklog) { + boundingBox.min.x = std::min(boundingBox.min.x, v.x); + boundingBox.min.y = std::min(boundingBox.min.y, v.y); + boundingBox.min.z = std::min(boundingBox.min.z, v.z); + boundingBox.max.x = std::max(boundingBox.max.x, v.x); + boundingBox.max.y = std::max(boundingBox.max.y, v.y); + boundingBox.max.z = std::max(boundingBox.max.z, v.z); + } +} + +void ConvexRegion::updateEdges() { + auto temp{std::move(edges)}; + for (auto& triangle : triangles) { + for (int i = 0; i < 3; ++i) { + Edge edge = triangle.getEdge(i); + if (auto iter = temp.find(edge); iter != temp.end()) { + edges.emplace(edge, std::move(iter->geo)); + } else { + edges.emplace( + edge, + WorldEdit::getInstance().getGeo().line( + getDim(), + Vec3{edge.start} + 0.5, + Vec3{edge.end} + 0.5, + WorldEdit::getInstance().getConfig().colors.region_line_color + ) + ); + } + } + } +} + +ConvexRegion::ConvexRegion(DimensionType d, BoundingBox const& b) : Region(d, b) {} + +bool ConvexRegion::containsRaw(BlockPos const& pt) const { + if (hasLast && lastTriangle.above(pt)) { + return false; + } + for (auto& triangle : triangles) { + if (lastTriangle == triangle) { + continue; + } + if (triangle.above(pt)) { + hasLast = true; + lastTriangle = triangle; + return false; + } + } + return true; +} + +bool ConvexRegion::addVertex(BlockPos const& vertex) { + hasLast = false; + if (vertices.contains(vertex)) { + return false; + } + if (vertices.size() == 3) { + if (vertexBacklog.contains(vertex)) { + return false; + } + if (containsRaw(vertex)) { + vertexBacklog.insert(vertex); + updateBoundingBox(); + return true; + } + } + vertices.insert(vertex); + updateBoundingBox(); + centerAccum = centerAccum + vertex; + + switch (vertices.size()) { + case 0: + case 1: + case 2: { + return true; + }; + case 3: { + triangles.emplace_back( + indexedVertices[0].data, + indexedVertices[1].data, + indexedVertices[2].data + ); + triangles.emplace_back( + indexedVertices[0].data, + indexedVertices[2].data, + indexedVertices[1].data + ); + updateEdges(); + return true; + }; + default: + break; + } + phmap::flat_hash_set borderEdges; + for (auto iter = triangles.begin(); iter != triangles.end();) { + if ((*iter).above(vertex)) { + for (int i = 0; i < 3; ++i) { + Edge edge = (*iter).getEdge(i); + if (!borderEdges.contains(edge)) { + borderEdges.insert(edge); + } else { + borderEdges.erase(edge); + } + } + iter = triangles.erase(iter); + } else { + ++iter; + } + } + for (auto& edge : borderEdges) { + triangles.emplace_back(edge.start, edge.end, vertex); + } + if (!vertexBacklog.empty()) { + vertices.erase(vertex); + phmap::flat_hash_set vertexBacklog2(std::move(vertexBacklog)); + for (auto& vertex2 : vertexBacklog2) { + addVertex(vertex2); + } + vertices.insert(vertex); + } + updateEdges(); + return true; +} + +bool ConvexRegion::addVertexWithIndex(BlockPos const& pos) { + bool res = addVertex(pos); + if (res) { + indexedVertices.emplace_back( + pos, + WorldEdit::getInstance().getGeo().box( + getDim(), + pos, + WorldEdit::getInstance().getConfig().colors.region_point_color + ) + ); + } + return res; +} + +bool ConvexRegion::setMainPos(BlockPos const& pos) { + hasLast = false; + vertices.clear(); + triangles.clear(); + vertexBacklog.clear(); + edges.clear(); + indexedVertices.clear(); + centerAccum = 0; + return addVertexWithIndex(pos); +} + +bool ConvexRegion::setVicePos(BlockPos const& pos) { return addVertexWithIndex(pos); } + +bool ConvexRegion::shift(BlockPos const& change) { + boundingBox.min = boundingBox.min + change; + boundingBox.max = boundingBox.max + change; + auto tmpVertices{std::move(vertices)}; + for (auto& vertice : tmpVertices) { + vertices.insert(vertice + change); + } + auto& geo = WorldEdit::getInstance().getGeo(); + for (auto& pos : indexedVertices) { + pos.data += change; + geo.shift(pos.geo.geo, change); + } + auto tmpVertexBacklog{std::move(vertexBacklog)}; + for (auto& vertex : tmpVertexBacklog) { + vertexBacklog.emplace(vertex + change); + } + for (auto& triangle : triangles) { + triangle.vertices[0] += change; + triangle.vertices[1] += change; + triangle.vertices[2] += change; + triangle.maxDotProduct = triangle.evalMaxDotProduct(); + } + auto tmpEdges{std::move(edges)}; + for (auto& e : tmpEdges) { + geo.shift(e.geo.geo, change); + edges.emplace( + Edge({e.data.start + change, e.data.end + change}), + std::move(e.geo) + ); + } + centerAccum = centerAccum + change * (int)vertices.size(); + hasLast = false; + + return true; +} + +bool ConvexRegion::contains(BlockPos const& pos) const { + if (triangles.empty()) { + return false; + } + + if (!boundingBox.contains(pos)) { + return false; + } + + return containsRaw(pos); +} + +void ConvexRegion::forEachLine( + std::function&& todo +) const { + if (indexedVertices.size() > 1) { + for (int i = 0; i < indexedVertices.size() - 1; ++i) { + todo(indexedVertices[i].data, indexedVertices[i + 1].data); + } + } +} + +uint64_t ConvexRegion::size() const { + double volume = 0; + for (auto triangle : triangles) { + volume += + triangle.getVertex(0).cross(triangle.getVertex(1)).dot(triangle.getVertex(2)); + } + return (uint64_t)std::abs(volume / 6.0); +}; +} // namespace we diff --git a/src/region/ConvexRegion.h b/src/region/ConvexRegion.h new file mode 100644 index 0000000..8d030d9 --- /dev/null +++ b/src/region/ConvexRegion.h @@ -0,0 +1,52 @@ +#pragma once + +#include "Region.h" +#include "utils/Triangle.h" + +namespace we { +class ConvexRegion : public Region { + bool addVertex(BlockPos const& vertex); + + bool addVertexWithIndex(BlockPos const& pos); + + bool containsRaw(BlockPos const& pt) const; + + void updateEdges(); + + phmap::flat_hash_set vertices; + std::vector triangles; + phmap::flat_hash_set> edges; + phmap::flat_hash_set vertexBacklog; + + BlockPos centerAccum; + + Triangle mutable lastTriangle; + bool mutable hasLast{}; + + std::vector> indexedVertices; + +public: + ConvexRegion(DimensionType, BoundingBox const&); + + void updateBoundingBox() override; + + Type getType() const override { return Cuboid; } + + uint64_t size() const override; + + bool shift(BlockPos const&) override; + + Vec3 getCenter() const override { + return Vec3{centerAccum} * (1.0f / vertices.size()) + 0.5; + }; + + void + forEachLine(std::function&&) const override; + + bool setMainPos(BlockPos const&) override; + + bool setVicePos(BlockPos const&) override; + + bool contains(BlockPos const&) const override; +}; +} // namespace we diff --git a/src/region/CuboidRegion.cpp b/src/region/CuboidRegion.cpp new file mode 100644 index 0000000..6e24bb9 --- /dev/null +++ b/src/region/CuboidRegion.cpp @@ -0,0 +1,156 @@ +#include "CuboidRegion.h" +#include "utils/Serialize.h" + +namespace we { +void CuboidRegion::serialize(CompoundTag& tag) const { + Region::serialize(tag); + doSerialize(mainPos, tag["mainPos"]); + doSerialize(vicePos, tag["vicePos"]); +} +void CuboidRegion::deserialize(CompoundTag const& tag) { + Region::deserialize(tag); + ll::reflection::deserialize(mainPos, tag["mainPos"]); + ll::reflection::deserialize(vicePos, tag["vicePos"]); +} + +void CuboidRegion::updateBoundingBox() { + boundingBox.min.x = std::min(mainPos.x, vicePos.x); + boundingBox.min.y = std::min(mainPos.y, vicePos.y); + boundingBox.min.z = std::min(mainPos.z, vicePos.z); + boundingBox.max.x = std::max(mainPos.x, vicePos.x); + boundingBox.max.y = std::max(mainPos.y, vicePos.y); + boundingBox.max.z = std::max(mainPos.z, vicePos.z); + boundingBox.max.x = std::max(mainPos.x, vicePos.x); + box = WorldEdit::getInstance().getGeo().box( + getDim(), + boundingBox, + WorldEdit::getInstance().getConfig().colors.region_line_color + ); +} + +bool CuboidRegion::setMainPos(BlockPos const& pos) { + mainPos = pos; + updateBoundingBox(); + return true; +} + +bool CuboidRegion::setVicePos(BlockPos const& pos) { + vicePos = pos; + updateBoundingBox(); + return true; +} + +bool CuboidRegion::expand(std::span changes) { + for (auto& change : changes) { + if (change.x > 0) { + if (std::max(mainPos.x, vicePos.x) == mainPos.x) { + mainPos += {change.x, 0, 0}; + } else { + vicePos += {change.x, 0, 0}; + } + } else { + if (std::min(mainPos.x, vicePos.x) == mainPos.x) { + mainPos += {change.x, 0, 0}; + } else { + vicePos += {change.x, 0, 0}; + } + } + + if (change.y > 0) { + if (std::max(mainPos.y, vicePos.y) == mainPos.y) { + mainPos += {0, change.y, 0}; + } else { + vicePos += {0, change.y, 0}; + } + } else { + if (std::min(mainPos.y, vicePos.y) == mainPos.y) { + mainPos += {0, change.y, 0}; + } else { + vicePos += {0, change.y, 0}; + } + } + + if (change.z > 0) { + if (std::max(mainPos.z, vicePos.z) == mainPos.z) { + mainPos += {0, 0, change.z}; + } else { + vicePos += {0, 0, change.z}; + } + } else { + if (std::min(mainPos.z, vicePos.z) == mainPos.z) { + mainPos += {0, 0, change.z}; + } else { + vicePos += {0, 0, change.z}; + } + } + } + updateBoundingBox(); + return true; +} + +bool CuboidRegion::contract(std::span changes) { + for (auto& change : changes) { + if (change.x < 0) { + if (std::max(mainPos.x, vicePos.x) == mainPos.x) { + mainPos += {change.x, 0, 0}; + } else { + vicePos += {change.x, 0, 0}; + } + } else { + if (std::min(mainPos.x, vicePos.x) == mainPos.x) { + mainPos += {change.x, 0, 0}; + } else { + vicePos += {change.x, 0, 0}; + } + } + + if (change.y < 0) { + if (std::max(mainPos.y, vicePos.y) == mainPos.y) { + mainPos += {0, change.y, 0}; + } else { + vicePos += {0, change.y, 0}; + } + } else { + if (std::min(mainPos.y, vicePos.y) == mainPos.y) { + mainPos += {0, change.y, 0}; + } else { + vicePos += {0, change.y, 0}; + } + } + + if (change.z < 0) { + if (std::max(mainPos.z, vicePos.z) == mainPos.z) { + mainPos += {0, 0, change.z}; + } else { + vicePos += {0, 0, change.z}; + } + } else { + if (std::min(mainPos.z, vicePos.z) == mainPos.z) { + mainPos += {0, 0, change.z}; + } else { + vicePos += {0, 0, change.z}; + } + } + } + updateBoundingBox(); + return true; +} + +bool CuboidRegion::shift(BlockPos const& change) { + mainPos += change; + vicePos += change; + updateBoundingBox(); + return true; +} + +void CuboidRegion::forEachLine( + std::function&& todo +) const { + todo(mainPos, vicePos); +} + +CuboidRegion::CuboidRegion(DimensionType d, BoundingBox const& b) : Region(d, b) { + mainPos = b.min; + vicePos = b.max; +} +} // namespace we diff --git a/src/region/CuboidRegion.h b/src/region/CuboidRegion.h new file mode 100644 index 0000000..f1fc940 --- /dev/null +++ b/src/region/CuboidRegion.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Region.h" + +namespace we { +class CuboidRegion : public Region { + GeoContainer box; + +protected: + BlockPos mainPos; + BlockPos vicePos; + +public: + CuboidRegion(DimensionType, BoundingBox const&); + + virtual void serialize(CompoundTag&) const; + + virtual void deserialize(CompoundTag const&); + + void updateBoundingBox() override; + + Type getType() const override { return Cuboid; } + + bool needResetVice() const override { return false; } + + bool expand(std::span) override; + + bool contract(std::span) override; + + bool shift(BlockPos const&) override; + + bool setMainPos(BlockPos const&) override; + + bool setVicePos(BlockPos const&) override; + + void forEachLine(std::function&& todo + ) const override; +}; +} // namespace we diff --git a/src/region/ExpandRegion.cpp b/src/region/ExpandRegion.cpp new file mode 100644 index 0000000..6b8a66b --- /dev/null +++ b/src/region/ExpandRegion.cpp @@ -0,0 +1,27 @@ +#include "ExpandRegion.h" + +namespace we { + +bool ExpandRegion::setMainPos(BlockPos const& pos) { + mainPos = pos; + vicePos = pos; + updateBoundingBox(); + return true; +} + +bool ExpandRegion::setVicePos(BlockPos const& pos) { + if (contains(pos)) { + return false; + } + mainPos.x = std::min(mainPos.x, pos.x); + mainPos.y = std::min(mainPos.y, pos.y); + mainPos.z = std::min(mainPos.z, pos.z); + vicePos.x = std::max(pos.x, vicePos.x); + vicePos.y = std::max(pos.y, vicePos.y); + vicePos.z = std::max(pos.z, vicePos.z); + updateBoundingBox(); + return true; +} +ExpandRegion::ExpandRegion(DimensionType d, BoundingBox const& b) : CuboidRegion(d, b) {} + +} // namespace we diff --git a/src/region/ExpandRegion.h b/src/region/ExpandRegion.h new file mode 100644 index 0000000..88b0425 --- /dev/null +++ b/src/region/ExpandRegion.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CuboidRegion.h" + +namespace we { +class ExpandRegion : public CuboidRegion { + +public: + ExpandRegion(DimensionType, BoundingBox const&); + + Type getType() const override { return Expand; } + + bool needResetVice() const override { return true; } + + bool setMainPos(BlockPos const&) override; + + bool setVicePos(BlockPos const&) override; +}; +} // namespace we diff --git a/src/region/Region.cpp b/src/region/Region.cpp new file mode 100644 index 0000000..57dd889 --- /dev/null +++ b/src/region/Region.cpp @@ -0,0 +1,102 @@ +#include "Region.h" +#include "CuboidRegion.h" +#include "ExpandRegion.h" +#include "SphereRegion.h" +#include "utils/Serialize.h" + +namespace we { + +void Region::serialize(CompoundTag& tag) const { + doSerialize(getType(), tag["type"]); + doSerialize(boundingBox, tag["boundingBox"]); + doSerialize(dim.id, tag["dim"]); +} +void Region::deserialize(CompoundTag const&) {} + +void Region::forEachBlockInRegion(std::function&& todo) const { + boundingBox.forEachPos([todo = std::move(todo), this](BlockPos const& pos) { + if (contains(pos)) { + todo(pos); + } + return true; + }); +} +void Region::forEachBlockUVInRegion( + std::function&& todo +) const { + auto size = boundingBox.getSideLength(); + if (size.x == 1) { + Region::forEachBlockInRegion( + [todo = std::move(todo), this, &size](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + todo(pos, (localPos.z + 0.5) / size.z, (localPos.y + 0.5) / size.y); + } + ); + } else if (size.z == 1) { + Region::forEachBlockInRegion( + [todo = std::move(todo), this, &size](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + todo(pos, (localPos.x + 0.5) / size.x, (localPos.y + 0.5) / size.y); + } + ); + } else { + Region::forEachBlockInRegion( + [todo = std::move(todo), this, &size](BlockPos const& pos) { + auto localPos = pos - boundingBox.min; + todo(pos, (localPos.x + 0.5) / size.x, (localPos.z + 0.5) / size.z); + } + ); + } +} + +int Region::getHeighest(Pos2d xz) const { + for (int y = boundingBox.max.y; y >= boundingBox.min.y; y--) { + if (contains({xz.x, y, xz.z})) { + return y; + } + } + return boundingBox.min.y - 1; +} + +Region::Region(DimensionType d, BoundingBox const& b) : boundingBox(b), dim(d) {} + +std::shared_ptr +Region::createRegion(Type type, DimensionType dim, BoundingBox const& box, bool update) { + std::shared_ptr res; + switch (type) { + case Cuboid: + res = std::make_shared(dim, box); + break; + case Expand: + return std::make_shared(dim, box); + case Sphere: + return std::make_shared(dim, box); + // case Poly: + // return std::make_shared(dim, box, show); + // case Convex: + // return std::make_shared(dim, box, show); + // case Cylinder: + // return std::make_shared(dim, box, show); + // case Loft: + // return std::make_shared(dim, box, show); + default: + std::unreachable(); + } + if (update) { + res->updateBoundingBox(); + } + return res; +} + +std::shared_ptr Region::createRegion(CompoundTag const& tag) { + auto res = createRegion( + doDeserialize(tag["type"]), + doDeserialize(tag["dim"]), + doDeserialize(tag["boundingBox"]), + false + ); + res->deserialize(tag); + res->updateBoundingBox(); + return res; +} +} // namespace we diff --git a/src/region/Region.h b/src/region/Region.h new file mode 100644 index 0000000..c04be37 --- /dev/null +++ b/src/region/Region.h @@ -0,0 +1,78 @@ +#pragma once + +#include "worldedit/WorldEdit.h" + +#include "utils/GeoContainer.h" + +namespace we { + +class Region { +protected: + BoundingBox boundingBox; + DimensionType const dim; + + Region(DimensionType, BoundingBox const&); + +public: + enum Type { + Cuboid, + Expand, + Sphere, + Poly, + Convex, + Cylinder, + Loft, + }; + static std::shared_ptr + createRegion(Type, DimensionType, BoundingBox const&, bool update = true); + + static std::shared_ptr createRegion(CompoundTag const&); + + DimensionType getDim() const { return dim; } + + int getHeighest(Pos2d) const; + + virtual ~Region() = default; + + virtual void serialize(CompoundTag&) const; + + virtual void deserialize(CompoundTag const&); + + virtual bool needResetVice() const { return true; } + + virtual Type getType() const = 0; + + virtual BoundingBox getBoundBox() const { return boundingBox; } + + virtual void updateBoundingBox() = 0; + + virtual uint64_t size() const { + return (uint64_t)(boundingBox.max.x - boundingBox.min.x + 1) + * (boundingBox.max.y - boundingBox.min.y + 1) + * (boundingBox.max.z - boundingBox.min.z + 1); + } + virtual bool expand(std::span) { return false; } + + virtual bool contract(std::span) { return false; } + + virtual bool shift(BlockPos const&) { return false; } + + virtual Vec3 getCenter() const { return AABB{boundingBox}.getCenter(); } + + virtual bool setMainPos(BlockPos const&) { return false; } + + virtual bool setVicePos(BlockPos const&) { return false; } + + virtual bool contains(BlockPos const& pos) const { return boundingBox.contains(pos); } + + virtual void forEachBlockInRegion(std::function&&) const; + + virtual void + forEachBlockUVInRegion(std::function&&) const; + + virtual void + forEachLine(std::function&&) const {} + + virtual bool removePoint(int, std::optional const&) { return false; } +}; +} // namespace we diff --git a/src/region/SphereRegion.cpp b/src/region/SphereRegion.cpp new file mode 100644 index 0000000..e615b35 --- /dev/null +++ b/src/region/SphereRegion.cpp @@ -0,0 +1,139 @@ +#include "SphereRegion.h" +#include "utils/Math.h" +#include "utils/Serialize.h" + +namespace we { +void SphereRegion::serialize(CompoundTag& tag) const { + Region::serialize(tag); + doSerialize(center, tag["center"]); + doSerialize(radius, tag["radius"]); +} +void SphereRegion::deserialize(CompoundTag const& tag) { + Region::deserialize(tag); + ll::reflection::deserialize(center, tag["center"]); + ll::reflection::deserialize(radius, tag["radius"]); +} + +void SphereRegion::updateBoundingBox() { + auto newRadius = (int)std::ceil(radius); + boundingBox.min.x = center.x - newRadius; + boundingBox.min.y = center.y - newRadius; + boundingBox.min.z = center.z - newRadius; + boundingBox.max.x = center.x + newRadius; + boundingBox.max.y = center.y + newRadius; + boundingBox.max.z = center.z + newRadius; + + auto& geo = WorldEdit::getInstance().getGeo(); + sphere = geo.sphere( + getDim(), + center.center(), + (float)radius, + WorldEdit::getInstance().getConfig().colors.region_line_color + ); + centerbox = geo.box( + getDim(), + center, + WorldEdit::getInstance().getConfig().colors.region_point_color + ); +} + +void SphereRegion::forEachBlockUVInRegion( + std::function&& todo +) const { + forEachBlockInRegion([todo = std::move(todo), this](BlockPos const& pos) { + int counts = 0; + for (auto& calPos : pos.getNeighbors()) { + counts += contains(calPos); + } + if (counts < 6) { + double y = (pos.y - center.y) / radius; + if (std::abs(y) > 0.8) { + todo( + pos, + (std::atan2(pos.z - center.z, pos.x - center.x) + std::numbers::pi) + / (std::numbers::pi * 2), + std::acos(std::clamp( + -sign(y) + * sqrt(std::max( + 0.0, + pow2(radius) - pow2(static_cast(pos.z) - center.z) + - pow2(static_cast(pos.x) - center.x) + )) + / radius, + -1.0, + 1.0 + )) * std::numbers::inv_pi + ); + } else { + todo( + pos, + (atan2(pos.z - center.z, pos.x - center.x) + std::numbers::pi) + / (std::numbers::pi * 2), + acos(-y) * std::numbers::inv_pi + ); + } + } + }); +} + +bool SphereRegion::setMainPos(BlockPos const& pos) { + center = pos; + radius = 0.5; + updateBoundingBox(); + return true; +} + +bool SphereRegion::setVicePos(BlockPos const& pos) { + if (auto dis = pos.distanceTo(center); dis > radius) { + radius = dis + 0.5f; + updateBoundingBox(); + return true; + } + return false; +} + +std::optional SphereRegion::checkChanges(std::span changes) { + int x = 0, y = 0, z = 0; + for (auto& change : changes) { + x += std::abs(change.x); + y += std::abs(change.y); + z += std::abs(change.z); + } + if (x == y && y == z) { + return x / 2; + } + return {}; +} + +bool SphereRegion::expand(std::span changes) { + auto check = checkChanges(changes); + if (!check) { + return false; + } + radius += *check; + updateBoundingBox(); + return true; +} + +bool SphereRegion::contract(std::span changes) { + auto check = checkChanges(changes); + if (!check) { + return false; + } + radius -= *check; + radius = std::max(radius, 0.5); + updateBoundingBox(); + return true; +} + +bool SphereRegion::shift(BlockPos const& change) { + center = center + change; + updateBoundingBox(); + return true; +} + +SphereRegion::SphereRegion(DimensionType d, BoundingBox const& b) +: Region(d, b), + center((b.min + b.max) / 2), + radius(b.getSideLength().dot(1) / 6.0) {} +} // namespace we diff --git a/src/region/SphereRegion.h b/src/region/SphereRegion.h new file mode 100644 index 0000000..2768624 --- /dev/null +++ b/src/region/SphereRegion.h @@ -0,0 +1,50 @@ +#pragma once + +#include "Region.h" + +namespace we { +class SphereRegion : public Region { + GeoContainer sphere; + GeoContainer centerbox; + + BlockPos center; + double radius; + + static std::optional checkChanges(std::span); + +public: + SphereRegion(DimensionType, BoundingBox const&); + + virtual void serialize(CompoundTag&) const; + + virtual void deserialize(CompoundTag const&); + + void updateBoundingBox() override; + + Type getType() const override { return Sphere; } + + bool expand(std::span) override; + + bool contract(std::span) override; + + bool shift(BlockPos const&) override; + + Vec3 getCenter() const override { return center.center(); }; + + uint64_t size() const override { + return (uint64_t + )std::round((4.0 / 3.0 * std::numbers::pi) * radius * radius * radius); + }; + + void forEachBlockUVInRegion(std::function&&) + const override; + + bool setMainPos(BlockPos const&) override; + + bool setVicePos(BlockPos const&) override; + + bool contains(BlockPos const& pos) const override { + return pos.distanceTo(center) <= radius; + } +}; +} // namespace we diff --git a/src/utils/Bresenham.cpp b/src/utils/Bresenham.cpp new file mode 100644 index 0000000..1202479 --- /dev/null +++ b/src/utils/Bresenham.cpp @@ -0,0 +1,175 @@ +#include "Bresenham.h" + +namespace we { + + +Vec3 KochanekBartelsInterpolation::retrieve(int index) const { + if (index < 0) { + if (circle) { + return nodes[(int)(round(posfmod(index, (double)(nodes.size()))))]; + } else { + return nodes[0]; + } + } else if (index >= nodes.size()) { + if (circle) { + return nodes[(int)(round(posfmod(index, (double)(nodes.size()))))]; + } else { + return nodes[nodes.size() - 1]; + } + } + return nodes[index]; +} +Vec3 KochanekBartelsInterpolation::linearCombination( + int baseIndex, + double f1, + double f2, + double f3, + double f4 +) const { + return retrieve(baseIndex - 1) * (float)f1 + retrieve(baseIndex) * (float)f2 + + retrieve(baseIndex + 1) * (float)f3 + retrieve(baseIndex + 2) * (float)f4; +} + +void KochanekBartelsInterpolation::recalc() { + int nNodes = (int)nodes.size(); + if (circle) { + nNodes += 1; + } + coeffA.resize(nNodes); + coeffB.resize(nNodes); + coeffC.resize(nNodes); + coeffD.resize(nNodes); + if (nNodes < 1) { + return; + } + Node nodeB = nodes[0]; + double tensionB = nodeB.tension; + double biasB = nodeB.bias; + double continuityB = nodeB.continuity; + for (int i = 0; i < nNodes; ++i) { + const double tensionA = tensionB; + const double biasA = biasB; + const double continuityA = continuityB; + if (i + 1 < nNodes) { + if (circle) { + nodeB = nodes[(int)(round(posfmod(i + 1, (double)(nodes.size()))))]; + } else { + nodeB = nodes[i + 1]; + } + tensionB = nodeB.tension; + biasB = nodeB.bias; + continuityB = nodeB.continuity; + } + + const double ta = (1 - tensionA) * (1 + biasA) * (1 + continuityA) / 2; + const double tb = (1 - tensionA) * (1 - biasA) * (1 - continuityA) / 2; + const double tc = (1 - tensionB) * (1 + biasB) * (1 - continuityB) / 2; + const double td = (1 - tensionB) * (1 - biasB) * (1 + continuityB) / 2; + + coeffA[i] = linearCombination(i, -ta, ta - tb - tc + 2, tb + tc - td - 2, td); + coeffB[i] = linearCombination( + i, + 2 * ta, + -2 * ta + 2 * tb + tc - 3, + -2 * tb - tc + td + 3, + -td + ); + coeffC[i] = linearCombination(i, -ta, ta - tb, tb, 0); + coeffD[i] = retrieve(i); + } + scaling = (int)nodes.size(); + if (!circle) { + scaling -= 1; + } +} +void KochanekBartelsInterpolation::setNodes(std::vector inNodes) { + nodes = std::move(inNodes); + recalc(); +} + +Vec3 KochanekBartelsInterpolation::getPosition(double position) const { + position = std::max(0.0, std::min(position, 1.0)); + position *= scaling; + int index = (int)position; + float f = (float)(position - index); + return ((coeffA[index] * f + coeffB[index]) * f + coeffC[index]) * f + coeffD[index]; +} + +Vec3 KochanekBartelsInterpolation::get1stDerivative(double position) const { + position = std::max(0.0, std::min(position, 1.0)); + position *= scaling; + int index = (int)position; + return ((coeffA[index] * (float)(1.5 * position - 3.0 * index) + coeffB[index]) + * (float)(2.0 * position) + + (coeffA[index] * (float)(1.5 * index) - coeffB[index]) + * (float)(2.0 * index) + + coeffC[index]) + * (float)scaling; +} + +double KochanekBartelsInterpolation::arcLength(double positionA, double positionB) const { + if (positionA > positionB) { + std::swap(positionA, positionB); + } + positionA = std::max(0.0, std::min(positionA, 1.0)); + positionB = std::max(0.0, std::min(positionB, 1.0)); + positionA *= scaling; + positionB *= scaling; + int indexA = (int)positionA; + int indexB = (int)positionB; + double fA = positionA - indexA; + double fB = positionB - indexB; + return arcLengthRecursive(indexA, fA, indexB, fB); +} + +double KochanekBartelsInterpolation::arcLengthRecursive( + int indexLeft, + double remainderLeft, + int indexRight, + double remainderRight +) const { + switch (indexRight - indexLeft) { + case 0: + return arcLengthRecursive(indexLeft, remainderLeft, remainderRight); + + case 1: + // This case is merely a speed-up for a very common case + return arcLengthRecursive(indexLeft, remainderLeft, 1.0) + + arcLengthRecursive(indexRight, 0.0, remainderRight); + + default: + return arcLengthRecursive(indexLeft, remainderLeft, indexRight - 1, 1.0) + + arcLengthRecursive(indexRight, 0.0, remainderRight); + } +} + +double KochanekBartelsInterpolation::arcLengthRecursive( + int index, + double remainderLeft, + double remainderRight +) const { + auto a = coeffA[index] * 3; + auto b = coeffB[index] * 2; + auto c = coeffC[index]; + + const int nPoints = 8; + + double accum = + ((a * (float)remainderLeft + b) * (float)remainderLeft + c).length() * 0.5; + for (int i = 0; i < nPoints - 1; ++i) { + float t = (float)((double)i / (double)nPoints); + t = (float)((remainderRight - remainderLeft) * t + remainderLeft); + accum += ((a * t + b) * t + c).length(); + } + accum += ((a * (float)remainderRight + b) * (float)remainderRight + c).length() * 0.5; + return accum * (remainderRight - remainderLeft) / (double)nPoints; +} + +int KochanekBartelsInterpolation::getSegment(double position) const { + position = std::max(0.0, std::min(position, 1.0)); + position *= scaling; + int index = (int)position; + return index; +} + +} // namespace we diff --git a/src/utils/Bresenham.h b/src/utils/Bresenham.h new file mode 100644 index 0000000..d3014f9 --- /dev/null +++ b/src/utils/Bresenham.h @@ -0,0 +1,55 @@ +#pragma once + +#include "Math.h" +#include "worldedit/WorldEdit.h" + +namespace we { +class Node : public Vec3 { +public: + double tension = 0; + double bias = 0; + double continuity = 0; + Node(Vec3 const& pos, double tension = 0, double bias = 0, double continuity = 0) + : Vec3(pos), + tension(tension), + bias(bias), + continuity(continuity) {} + Node(BlockPos const& pos, double tension = 0, double bias = 0, double continuity = 0) + : Node(Vec3{pos} + 0.5, tension, bias, continuity) {} + + Vec3 const& getVec3() const { return *this; } +}; +class KochanekBartelsInterpolation { +public: + std::vector nodes; + std::vector coeffA; + std::vector coeffB; + std::vector coeffC; + std::vector coeffD; + double scaling; + bool circle = false; + KochanekBartelsInterpolation(bool c = false) : circle(c) {} + KochanekBartelsInterpolation(std::vector n, bool c = false) : circle(c) { + setNodes(std::move(n)); + } + Vec3 retrieve(int index) const; + void setNodes(std::vector nodes); + Vec3 getPosition(double position) const; + Vec3 get1stDerivative(double position) const; + double arcLength(double positionA = 0, double positionB = 1) const; + int getSegment(double position) const; + +private: + void recalc(); + Vec3 + linearCombination(int baseIndex, double f1, double f2, double f3, double f4) const; + double arcLengthRecursive( + int indexLeft, + double remainderLeft, + int indexRight, + double remainderRight + ) const; + double + arcLengthRecursive(int index, double remainderLeft, double remainderRight) const; +}; +} // namespace we diff --git a/src/utils/Catenary.h b/src/utils/Catenary.h new file mode 100644 index 0000000..55267ca --- /dev/null +++ b/src/utils/Catenary.h @@ -0,0 +1,14 @@ +#pragma once + +#include "worldedit/WorldEdit.h" + +namespace we { + +inline double getCatenaryParameter(double d, double h, double l) { + const double m = sqrt(l * l - h * h) / d; + double x = acosh(m) + 1; + ll::meta::unroll<10>([&](size_t) { x -= (std::sinh(x) - m * x) / (std::cosh(x) - m); } + ); + return d / (2 * x); +} +} // namespace we diff --git a/src/utils/GeoContainer.h b/src/utils/GeoContainer.h new file mode 100644 index 0000000..736b346 --- /dev/null +++ b/src/utils/GeoContainer.h @@ -0,0 +1,49 @@ +#pragma once + +#include "worldedit/WorldEdit.h" + +namespace we { +struct GeoContainer { + bsci::GeometryGroup::GeoId geo; + + GeoContainer(GeoContainer const&) noexcept = delete; + GeoContainer& operator=(GeoContainer const&) noexcept = delete; + + GeoContainer() noexcept : geo({0}) {} + + GeoContainer(bsci::GeometryGroup::GeoId id) noexcept : geo(id) {} + + GeoContainer(GeoContainer&& other) noexcept : GeoContainer(other.geo) { + other.geo = {0}; + } + GeoContainer& operator=(GeoContainer&& other) noexcept { + if (this == std::addressof(other)) { + return *this; + } + WorldEdit::getInstance().getGeo().remove(geo); + geo = other.geo; + other.geo = {0}; + return *this; + } + ~GeoContainer() { WorldEdit::getInstance().getGeo().remove(geo); } +}; +template +struct WithGeo { + T data; + GeoContainer mutable geo; + WithGeo() = default; + WithGeo(T const& t) : data(t) {} + WithGeo(T const& t, GeoContainer&& geo) : data(t), geo(std::move(geo)) {} + + WithGeo(WithGeo const&) noexcept = delete; + WithGeo& operator=(WithGeo const&) noexcept = delete; + WithGeo(WithGeo&&) noexcept = default; + WithGeo& operator=(WithGeo&&) noexcept = default; + + constexpr bool operator==(WithGeo const& other) const { return data == other.data; } +}; +template +inline size_t hash_value(WithGeo const& d) { + return std::hash()(d.data); +} +} // namespace we diff --git a/src/utils/Hash.h b/src/utils/Hash.h new file mode 100644 index 0000000..0b51089 --- /dev/null +++ b/src/utils/Hash.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +namespace std { +template T> +struct hash { + inline size_t operator()(T const& val) const { return hash_value(val); } +}; +} \ No newline at end of file diff --git a/src/utils/Math.cpp b/src/utils/Math.cpp new file mode 100644 index 0000000..65d8edd --- /dev/null +++ b/src/utils/Math.cpp @@ -0,0 +1,47 @@ +#include "Math.h" + +namespace we { +void plotLine( + BlockPos const& pos0, + BlockPos const& pos1, + std::function const& todo +) { + int x0 = pos0.x; + int y0 = pos0.y; + int z0 = pos0.z; + int x1 = pos1.x; + int y1 = pos1.y; + int z1 = pos1.z; + int dx = abs(x1 - x0); + int dy = abs(y1 - y0); + int dz = abs(z1 - z0); + int sx = x0 < x1 ? 1 : -1; + int sy = y0 < y1 ? 1 : -1; + int sz = z0 < z1 ? 1 : -1; + + int dMax = std::max(dx, std::max(dy, dz)); + if (dMax == dx) { + for (int domstep = 0; domstep <= dx; domstep++) { + int tipx = x0 + domstep * sx; + int tipy = (int)round(y0 + domstep / ((double)dx) * ((double)dy) * sy); + int tipz = (int)round(z0 + domstep / ((double)dx) * ((double)dz) * sz); + todo(BlockPos(tipx, tipy, tipz)); + } + } else if (dMax == dy) { + for (int domstep = 0; domstep <= dy; domstep++) { + int tipx = (int)round(x0 + domstep / ((double)dy) * ((double)dx) * sx); + int tipy = y0 + domstep * sy; + int tipz = (int)round(z0 + domstep / ((double)dy) * ((double)dz) * sz); + todo(BlockPos(tipx, tipy, tipz)); + } + } else { + for (int domstep = 0; domstep <= dz; domstep++) { + int tipx = (int)round(x0 + domstep / ((double)dz) * ((double)dx) * sx); + int tipy = (int)round(y0 + domstep / ((double)dz) * ((double)dy) * sy); + int tipz = z0 + domstep * sz; + todo(BlockPos(tipx, tipy, tipz)); + } + } + return; +} +} // namespace we diff --git a/src/utils/Math.h b/src/utils/Math.h new file mode 100644 index 0000000..efc33bf --- /dev/null +++ b/src/utils/Math.h @@ -0,0 +1,47 @@ +#pragma once + +#include "worldedit/Global.h" + +#include + +namespace we { + +inline double posfmod(double x, double y) { return x - std::floor(x / y) * y; } + +template +constexpr T binpow(T const& a, uint64_t const& b) { + if (b == 0) return static_cast(1); + T res = binpow(a, b / 2); + if (b % 2) return res * res * a; + else return res * res; +} + +template +constexpr T pow2(T const& a) { + return binpow(a, 2); +} + +template +inline T saturate(T const& a) { + return std::min(static_cast(1), std::max(a, static_cast(0))); +} + +template +inline T sign(T const& a) { + if (a == 0) { + return 0; + } + return std::copysign(1, a); +} + +template +inline T signedSqrt(T const& a) { + return sign(a) * std::sqrt(std::abs(a)); +} + +void plotLine( + BlockPos const& pos0, + BlockPos const& pos1, + std::function const& todo +); +} // namespace we diff --git a/src/utils/Serialize.h b/src/utils/Serialize.h new file mode 100644 index 0000000..a0e02df --- /dev/null +++ b/src/utils/Serialize.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace we { +template +inline void doSerialize(T const& t, J& j) { + j = ::ll::reflection::serialize(t); +} +template +inline T doDeserialize(J const& j) { + T t; + ::ll::reflection::deserialize(t, j); + return t; +} +} // namespace we diff --git a/src/utils/Triangle.h b/src/utils/Triangle.h new file mode 100644 index 0000000..67b3a53 --- /dev/null +++ b/src/utils/Triangle.h @@ -0,0 +1,57 @@ +#pragma once + +#include "utils/Math.h" + +namespace we { + +struct Edge { +public: + BlockPos start; + BlockPos end; + + constexpr Edge(BlockPos const& start, BlockPos const& end) : start(start), end(end){}; + constexpr bool operator==(Edge const& other) const { + return (start == other.start && end == other.end) + || (end == other.start && start == other.end); + } +}; +inline size_t hash_value(Edge const& rc) { + size_t seed = std::hash()(rc.start); + ll::hash_utils::hashCombine(std::hash()(rc.start), seed); + return seed; +} +struct Triangle { + std::array vertices; + Vec3 normal; + float maxDotProduct; + + float evalMaxDotProduct() const { + return (float)std::max( + std::max(normal.dot(vertices[0]), normal.dot(vertices[1])), + normal.dot(vertices[2]) + ); + } + + Triangle() = default; + Triangle(BlockPos const& v0, BlockPos const& v1, BlockPos const& v2) + : vertices({v0, v1, v2}), + normal(Vec3((v1 - v0).cross(v2 - v0)).normalize()), + maxDotProduct(evalMaxDotProduct()) {} + + BlockPos const& getVertex(int index) const { return vertices[index]; }; + + Edge getEdge(int index) const { + if (index == 2) return Edge(vertices[index], vertices[0]); + return Edge(vertices[index], vertices[index + 1]); + } + bool below(BlockPos const& pt) const { return normal.dot(pt) < maxDotProduct; } + + bool above(BlockPos const& pt) const { return normal.dot(pt) > maxDotProduct; } + + bool operator==(Triangle const& v) const { + return (v.maxDotProduct == maxDotProduct) && (v.normal == normal) + && (v.vertices[0] == vertices[0]) && (v.vertices[1] == vertices[1]) + && (v.vertices[2] == vertices[2]); + } +}; +} // namespace we diff --git a/src/utils/WithDim.h b/src/utils/WithDim.h index 9f6cd81..bb8d8d5 100644 --- a/src/utils/WithDim.h +++ b/src/utils/WithDim.h @@ -5,6 +5,7 @@ namespace we { template class WithDim { +public: T pos{}; DimensionType dim{-1}; }; diff --git a/src/worldedit/Config.h b/src/worldedit/Config.h index 37f5c81..22b1eb0 100644 --- a/src/worldedit/Config.h +++ b/src/worldedit/Config.h @@ -1,11 +1,13 @@ #pragma once +#include "Global.h" + #include #include namespace we { struct Config { - int version = 1; + int version = 0; struct CmdSetting { bool enabled = true; CommandPermissionLevel permission = CommandPermissionLevel::GameDirectors; @@ -13,5 +15,26 @@ struct Config { struct { CmdSetting weconfig{}; } commands{}; + struct { + mce::Color region_line_color{"#FFEC27"}; + mce::Color region_point_color{"#10E436"}; + } colors{}; }; } // namespace we + +// "#000000" +// "#144A74" +// "#8E65F3" +// "#07946E" +// "#AB5236" +// "#56575F" +// "#A2A3A7" +// "#FFFFFF" +// "#FF3040" +// "#FF7300" +// "#FFEC27" +// "#10E436" +// "#29ADFF" +// "#83769C" +// "#FF77A8" +// "#FFCCAA" \ No newline at end of file diff --git a/src/worldedit/Global.h b/src/worldedit/Global.h index 9e96212..05d6d98 100644 --- a/src/worldedit/Global.h +++ b/src/worldedit/Global.h @@ -1,14 +1,29 @@ #pragma once +#include + +#include #include +#include +#include +#include +#include +#include #include #include +#include #include #include #include +#include #include +#include #include #include #include -#include +#include #include + +using namespace ll::i18n_literals; +using namespace ll::hash_literals; +using namespace ll::chrono_literals; diff --git a/src/worldedit/WorldEdit.cpp b/src/worldedit/WorldEdit.cpp index a541583..b7c7bd0 100644 --- a/src/worldedit/WorldEdit.cpp +++ b/src/worldedit/WorldEdit.cpp @@ -7,6 +7,19 @@ #include #include +namespace mce { +template +inline J serialize(Color const& c) { + return std::format("#{:06x}", (uint)c.toARGB() % (1u << 24)) + + (c.a == 1 ? "" : std::format("{:02x}", (uint)c.toARGB() / (1u << 24))); +} +template +inline void deserialize(Color& ver, J const& j) { + if (j.is_string()) { + ver = mce::Color{(std::string_view)j}; + } +} +} // namespace mce namespace we { @@ -36,6 +49,7 @@ bool WorldEdit::loadConfig() { bool WorldEdit::saveConfig() { return ll::config::saveConfig(*mConfig, getConfigPath()); } bool WorldEdit::load() { + mGeometryGroup = bsci::GeometryGroup::createDefault(); if (!loadConfig()) { return false; } @@ -46,16 +60,14 @@ bool WorldEdit::enable() { if (!mConfig) { loadConfig(); } - static auto geo = bsci::GeometryGroup::createDefault(); - - geo->line( + getGeo().line( 0, BlockPos{0, 70, 0}.center(), BlockPos{10, 73, 6}.center(), mce::Color::BLUE ); - geo->box( + getGeo().box( 0, BoundingBox{ {0, 70, 0}, @@ -64,14 +76,9 @@ bool WorldEdit::enable() { mce::Color::PINK ); - geo->circle(0, BlockPos{0, 73, 0}.center(), Vec3{1, 1, 1}.normalize(), 8); + getGeo().circle(0, BlockPos{0, 73, 0}.center(), Vec3{1, 1, 1}.normalize(), 8); - geo->sphere( - 0, - BlockPos{0, 180, 0}.center(), - 100, - mce::Color::CYAN - ); + getGeo().sphere(0, BlockPos{0, 180, 0}.center(), 100, mce::Color::CYAN); return true; } diff --git a/src/worldedit/WorldEdit.h b/src/worldedit/WorldEdit.h index f34e0be..2222229 100644 --- a/src/worldedit/WorldEdit.h +++ b/src/worldedit/WorldEdit.h @@ -15,6 +15,8 @@ class WorldEdit { [[nodiscard]] ll::plugin::NativePlugin& getSelf() const { return mSelf; } + [[nodiscard]] bsci::GeometryGroup& getGeo() const { return *mGeometryGroup; } + [[nodiscard]] ll::Logger& getLogger() const { return getSelf().getLogger(); } [[nodiscard]] Config& getConfig() { return *mConfig; } @@ -34,8 +36,9 @@ class WorldEdit { bool unload(); private: - ll::plugin::NativePlugin& mSelf; - std::optional mConfig; + ll::plugin::NativePlugin& mSelf; + std::optional mConfig; + std::unique_ptr mGeometryGroup; }; } // namespace we diff --git a/xmake.lua b/xmake.lua index eea4032..c238690 100644 --- a/xmake.lua +++ b/xmake.lua @@ -27,7 +27,7 @@ target("WorldEdit") -- Change this to your plugin name. "/w44738", "/w45204" ) - add_defines("NOMINMAX", "UNICODE") + add_defines("_HAS_CXX23=1", "NOMINMAX", "UNICODE") add_files("src/**.cpp") add_includedirs("src") add_files("thirdparty/**.cpp")