From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- .../GameRules/ApplySchematicRuleDefinition.cpp | 249 +++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 Minecraft.Client/Common/GameRules/ApplySchematicRuleDefinition.cpp (limited to 'Minecraft.Client/Common/GameRules/ApplySchematicRuleDefinition.cpp') diff --git a/Minecraft.Client/Common/GameRules/ApplySchematicRuleDefinition.cpp b/Minecraft.Client/Common/GameRules/ApplySchematicRuleDefinition.cpp new file mode 100644 index 00000000..aa4a8fb2 --- /dev/null +++ b/Minecraft.Client/Common/GameRules/ApplySchematicRuleDefinition.cpp @@ -0,0 +1,249 @@ +#include "stdafx.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.phys.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.dimension.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.chunk.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "ApplySchematicRuleDefinition.h" +#include "LevelGenerationOptions.h" +#include "ConsoleSchematicFile.h" + +ApplySchematicRuleDefinition::ApplySchematicRuleDefinition(LevelGenerationOptions *levelGenOptions) +{ + m_levelGenOptions = levelGenOptions; + m_location = Vec3::newPermanent(0,0,0); + m_locationBox = NULL; + m_totalBlocksChanged = 0; + m_totalBlocksChangedLighting = 0; + m_rotation = ConsoleSchematicFile::eSchematicRot_0; + m_completed = false; + m_dimension = 0; + m_schematic = NULL; +} + +ApplySchematicRuleDefinition::~ApplySchematicRuleDefinition() +{ + app.DebugPrintf("Deleting ApplySchematicRuleDefinition.\n"); + if(!m_completed) m_levelGenOptions->releaseSchematicFile(m_schematicName); + m_schematic = NULL; + delete m_location; +} + +void ApplySchematicRuleDefinition::writeAttributes(DataOutputStream *dos, UINT numAttrs) +{ + GameRuleDefinition::writeAttributes(dos, numAttrs + 5); + + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_filename); + dos->writeUTF(m_schematicName); + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_x); + dos->writeUTF(_toString(m_location->x)); + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_y); + dos->writeUTF(_toString(m_location->y)); + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_z); + dos->writeUTF(_toString(m_location->z)); + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_rot); + + switch (m_rotation) + { + case ConsoleSchematicFile::eSchematicRot_0: dos->writeUTF(_toString( 0 )); break; + case ConsoleSchematicFile::eSchematicRot_90: dos->writeUTF(_toString( 90 )); break; + case ConsoleSchematicFile::eSchematicRot_180: dos->writeUTF(_toString( 180 )); break; + case ConsoleSchematicFile::eSchematicRot_270: dos->writeUTF(_toString( 270 )); break; + } +} + +void ApplySchematicRuleDefinition::addAttribute(const wstring &attributeName, const wstring &attributeValue) +{ + if(attributeName.compare(L"filename") == 0) + { + m_schematicName = attributeValue; + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter filename=%s\n",m_schematicName.c_str()); + + if(!m_schematicName.empty()) + { + if(m_schematicName.substr( m_schematicName.length() - 4, m_schematicName.length()).compare(L".sch") != 0) + { + m_schematicName.append(L".sch"); + } + m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName); + } + } + else if(attributeName.compare(L"x") == 0) + { + m_location->x = _fromString(attributeValue); + if( ((int)abs(m_location->x))%2 != 0) m_location->x -=1; + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter x=%f\n",m_location->x); + } + else if(attributeName.compare(L"y") == 0) + { + m_location->y = _fromString(attributeValue); + if( ((int)abs(m_location->y))%2 != 0) m_location->y -= 1; + if(m_location->y < 0) m_location->y = 0; + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter y=%f\n",m_location->y); + } + else if(attributeName.compare(L"z") == 0) + { + m_location->z = _fromString(attributeValue); + if(((int)abs(m_location->z))%2 != 0) m_location->z -= 1; + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter z=%f\n",m_location->z); + } + else if(attributeName.compare(L"rot") == 0) + { + int degrees = _fromString(attributeValue); + + while(degrees < 0) degrees += 360; + while(degrees >= 360) degrees -= 360; + float quad = degrees/90; + degrees = (int)(quad + 0.5f); + switch(degrees) + { + case 1: + m_rotation = ConsoleSchematicFile::eSchematicRot_90; + break; + case 2: + m_rotation = ConsoleSchematicFile::eSchematicRot_180; + break; + case 3: + case 4: + m_rotation = ConsoleSchematicFile::eSchematicRot_270; + break; + case 0: + default: + m_rotation = ConsoleSchematicFile::eSchematicRot_0; + break; + }; + + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter rot=%d\n",m_rotation); + } + else if(attributeName.compare(L"dim") == 0) + { + m_dimension = _fromString(attributeValue); + if(m_dimension > 1 || m_dimension < -1) m_dimension = 0; + //app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter dimension=%d\n",m_dimension); + } + else + { + GameRuleDefinition::addAttribute(attributeName, attributeValue); + } +} + +void ApplySchematicRuleDefinition::updateLocationBox() +{ + if(m_schematic == NULL) m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName); + + m_locationBox = AABB::newPermanent(0,0,0,0,0,0); + + m_locationBox->x0 = m_location->x; + m_locationBox->y0 = m_location->y; + m_locationBox->z0 = m_location->z; + + m_locationBox->y1 = m_location->y + m_schematic->getYSize(); + + switch(m_rotation) + { + case ConsoleSchematicFile::eSchematicRot_90: + case ConsoleSchematicFile::eSchematicRot_270: + m_locationBox->x1 = m_location->x + m_schematic->getZSize(); + m_locationBox->z1 = m_location->z + m_schematic->getXSize(); + break; + case ConsoleSchematicFile::eSchematicRot_0: + case ConsoleSchematicFile::eSchematicRot_180: + default: + m_locationBox->x1 = m_location->x + m_schematic->getXSize(); + m_locationBox->z1 = m_location->z + m_schematic->getZSize(); + break; + }; +} + +void ApplySchematicRuleDefinition::processSchematic(AABB *chunkBox, LevelChunk *chunk) +{ + if( m_completed ) return; + if(chunk->level->dimension->id != m_dimension) return; + + PIXBeginNamedEvent(0, "Processing ApplySchematicRuleDefinition"); + if(m_schematic == NULL) m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName); + + if(m_locationBox == NULL) updateLocationBox(); + if(chunkBox->intersects( m_locationBox )) + { + m_locationBox->y1 = min((double)Level::maxBuildHeight, m_locationBox->y1 ); + +#ifdef _DEBUG + app.DebugPrintf("Applying schematic %ls to chunk (%d,%d)\n",m_schematicName.c_str(),chunk->x, chunk->z); +#endif + PIXBeginNamedEvent(0,"Applying blocks and data"); + m_totalBlocksChanged += m_schematic->applyBlocksAndData(chunk, chunkBox, m_locationBox, m_rotation); + PIXEndNamedEvent(); + + // Add the tileEntities + PIXBeginNamedEvent(0,"Applying tile entities"); + m_schematic->applyTileEntities(chunk, chunkBox, m_locationBox, m_rotation); + PIXEndNamedEvent(); + + // TODO This does not take into account things that go outside the bounds of the world + int targetBlocks = (m_locationBox->x1 - m_locationBox->x0) + * (m_locationBox->y1 - m_locationBox->y0) + * (m_locationBox->z1 - m_locationBox->z0); + if( (m_totalBlocksChanged == targetBlocks) && (m_totalBlocksChangedLighting == targetBlocks) ) + { + m_completed = true; + //m_levelGenOptions->releaseSchematicFile(m_schematicName); + //m_schematic = NULL; + } + } + PIXEndNamedEvent(); +} + +void ApplySchematicRuleDefinition::processSchematicLighting(AABB *chunkBox, LevelChunk *chunk) +{ + if( m_completed ) return; + if(chunk->level->dimension->id != m_dimension) return; + + PIXBeginNamedEvent(0, "Processing ApplySchematicRuleDefinition (lighting)"); + if(m_schematic == NULL) m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName); + + if(m_locationBox == NULL) updateLocationBox(); + if(chunkBox->intersects( m_locationBox )) + { + m_locationBox->y1 = min((double)Level::maxBuildHeight, m_locationBox->y1 ); + +#ifdef _DEBUG + app.DebugPrintf("Applying schematic %ls to chunk (%d,%d)\n",m_schematicName.c_str(),chunk->x, chunk->z); +#endif + PIXBeginNamedEvent(0,"Patching lighting"); + m_totalBlocksChangedLighting += m_schematic->applyLighting(chunk, chunkBox, m_locationBox, m_rotation); + PIXEndNamedEvent(); + + // TODO This does not take into account things that go outside the bounds of the world + int targetBlocks = (m_locationBox->x1 - m_locationBox->x0) + * (m_locationBox->y1 - m_locationBox->y0) + * (m_locationBox->z1 - m_locationBox->z0); + if( (m_totalBlocksChanged == targetBlocks) && (m_totalBlocksChangedLighting == targetBlocks) ) + { + m_completed = true; + //m_levelGenOptions->releaseSchematicFile(m_schematicName); + //m_schematic = NULL; + } + } + PIXEndNamedEvent(); +} + +bool ApplySchematicRuleDefinition::checkIntersects(int x0, int y0, int z0, int x1, int y1, int z1) +{ + if( m_locationBox == NULL ) updateLocationBox(); + return m_locationBox->intersects(x0,y0,z0,x1,y1,z1); +} + +int ApplySchematicRuleDefinition::getMinY() +{ + if( m_locationBox == NULL ) updateLocationBox(); + return m_locationBox->y0; +} + +void ApplySchematicRuleDefinition::reset() +{ + m_totalBlocksChanged = 0; + m_totalBlocksChangedLighting = 0; + m_completed = false; +} \ No newline at end of file -- cgit v1.2.3