This commit is contained in:
GabsPuNs
2026-05-14 21:52:21 -04:00
parent 1b2f5c6fe8
commit f8a2d644f5
291 changed files with 7363 additions and 18368 deletions

View File

@@ -5,8 +5,6 @@
#include "net.minecraft.world.level.material.h"
#include "net.minecraft.world.level.tile.entity.h"
#include "net.minecraft.world.entity.h"
#include "net.minecraft.world.entity.monster.h"
#include "net.minecraft.world.entity.npc.h"
#include "WeighedTreasure.h"
#include "StructurePiece.h"
#include "BoundingBox.h"
@@ -14,7 +12,6 @@
#include "JavaMath.h"
#include "Facing.h"
#include "DoorItem.h"
#include "EnchantedBookItem.h"
/**
*
@@ -50,7 +47,6 @@ StructurePiece::StructurePiece()
boundingBox = nullptr;
orientation = 0;
genDepth = 0;
dirty = false;
// for reflection
}
@@ -70,28 +66,27 @@ CompoundTag *StructurePiece::createTag()
{
CompoundTag *tag = new CompoundTag();
tag->putString(L"id", StructureFeatureIO::getEncodeId(this));
tag->put(L"BB", boundingBox->createTag(L"BB"));
tag->putInt(L"O", orientation);
tag->putInt(L"GD", genDepth);
addAdditonalSaveData(tag);
return tag;
}
void StructurePiece::write(DataOutputStream *dos)
void StructurePiece::load(Level *level, CompoundTag *tag)
{
wstring encodeId = StructureFeatureIO::getEncodeId(this);
dos->writeUTF(encodeId);
boundingBox->write(dos);
dos->writeInt(orientation);
dos->writeInt(genDepth);
addAdditionalSaveData(dos);
}
void StructurePiece::load(Level *level, DataInputStream *dis)
{
boundingBox = new BoundingBox();
boundingBox->read(dis);
if (tag->contains(L"BB"))
{
boundingBox = new BoundingBox(tag->getIntArray(L"BB"));
}
orientation = tag->getInt(L"O");
genDepth = tag->getInt(L"GD");
orientation = dis->readInt();
genDepth = dis->readInt();
readAdditonalSaveData(dis);
readAdditonalSaveData(tag);
}
void StructurePiece::addChildren( StructurePiece* startPiece, list< StructurePiece* > *pieces, Random* random )
@@ -769,36 +764,7 @@ void StructurePiece::generateUpperHalfSphere( Level* level, BoundingBox* chunkBB
}
}
}
}
void StructurePiece::generateFullSphere( Level* level, BoundingBox* chunkBB, int cx, int cy, int cz, int radius,
int edgeTile, int edgeData, int fillTile, int fillData, bool skipAir )
{
for ( int y = cy - radius; y <= cy + radius; y++ )
{
for ( int x = cx - radius; x <= cx + radius; x++ )
{
for ( int z = cz - radius; z <= cz + radius; z++ )
{
float dx = ( float )( abs( x - cx ) ) + 0.5f;
float dy = ( float )( abs( y - cy ) ) + 0.5f;
float dz = ( float )( abs( z - cz ) ) + 0.5f;
float dist = sqrtf( dx * dx + dy * dy + dz * dz );
if ( !skipAir || getBlock( level, x, y, z, chunkBB ) != 0 )
{
if ( fabsf( dist - ( float )radius ) <= 0.5f )
placeBlock( level, edgeTile, edgeData, x, y, z, chunkBB );
}
if ( ( float ) radius - dist > 0.5f )
{
placeBlock( level, fillTile, fillData, x, y, z, chunkBB );
}
}
}
}
}
void StructurePiece::generateAirColumnUp( Level* level, int x, int startY, int z, BoundingBox* chunkBB )
@@ -819,17 +785,6 @@ void StructurePiece::generateAirColumnUp( Level* level, int x, int startY, int z
}
}
void StructurePiece::generateAirBoxUp( Level* level, int x0, int z0, int x1, int z1, int y, BoundingBox* chunkBB )
{
for ( int x = x0; x < x1; ++x )
{
for ( int z = z0; z < z1; ++z )
{
placeBlock( level, 0, 0, x, y, z, chunkBB );
}
}
}
void StructurePiece::fillColumnDown( Level* level, int tile, int tileData, int x, int startY, int z, BoundingBox* chunkBB )
{
int worldX = getWorldX( x, z );
@@ -848,17 +803,6 @@ void StructurePiece::fillColumnDown( Level* level, int tile, int tileData, int x
}
}
void StructurePiece::fillBoxDown( Level* level, int tileId, int tileData, int x0, int y0, int z0, int x1, int z1, BoundingBox* chunkBB )
{
for ( int x = x0; x <= x1; x++ )
{
for ( int z = z0; z <= z1; z++ )
{
fillColumnDown( level, tileId, tileData, x, y0, z, chunkBB );
}
}
}
bool StructurePiece::createChest( Level* level, BoundingBox* chunkBB, Random* random, int x, int y, int z,
WeighedTreasureArray treasure, int numRolls )
{
@@ -879,7 +823,6 @@ bool StructurePiece::createChest( Level* level, BoundingBox* chunkBB, Random* ra
return false;
}
bool StructurePiece::createDispenser(Level *level, BoundingBox *chunkBB, Random *random, int x, int y, int z, int facing, WeighedTreasureArray items, int numRolls)
{
int worldX = getWorldX(x, z);
@@ -899,507 +842,15 @@ bool StructurePiece::createDispenser(Level *level, BoundingBox *chunkBB, Random
return false;
}
int StructurePiece::getBlockDataValue( StructureTable::eBlockDataType type, int tile, int data )
void StructurePiece::createDoor( Level* level, BoundingBox* chunkBB, Random* random, int x, int y, int z,
int orientation )
{
if ( type == StructureTable::eBlockDataType_Orientation )
return getOrientationData( tile, data );
int worldX = getWorldX( x, z );
int worldY = getWorldY( y );
int worldZ = getWorldZ( x, z );
if ( type == StructureTable::eBlockDataType_Inverted )
return ~data & 0xF;
return data;
}
void StructurePiece::createCrops( Level *level, BoundingBox *chunkBB, Random *random, int x0, int z0, int x1, int z1, int y, int tileId, int minData, int maxData )
{
for ( int x = x0; x <= x1; x++ )
{
for ( int z = z0; z <= z1; z++ )
{
placeBlock( level, tileId, Mth::nextInt( random, minData, maxData ), x, y, z, chunkBB );
}
}
}
void StructurePiece::generateStructureFromData( Level *level, BoundingBox *chunkBB, Random *random, StructureTable::StructurePiece *piece, vector<bool> &objectPlacedFlags,
vector<bool> featureConditions, vector<int> tileOptionRemap, vector<int> &entitySpawnCounts )
{
unordered_map<int, bool> failures;
int treasureCount = piece->treasure.size();
WeighedTreasureArray treasureItems;
if ( treasureCount > 0 )
if ( chunkBB->isInside( worldX, worldY, worldZ ) )
{
treasureItems = WeighedTreasureArray( treasureCount );
for ( unsigned int i = 0; i < treasureCount; ++i )
{
const StructureTable::TreasureData &t = piece->treasure[i];
treasureItems[i] = new WeighedTreasure( t.itemId, t.auxValue, t.minCount, t.maxCount, t.weight );
}
}
for ( unsigned int i = 0; i < piece->structures.size(); ++i )
{
StructureTable::StructureData &s = piece->structures[i];
bool shouldGenerate = true;
if ( s.v26.size() == 2 )
{
int bitIndex = s.v26[0];
bool invert = s.v26[1] != 0;
if ( bitIndex >= (int)featureConditions.size() )
{
shouldGenerate = false;
}
else
{
bool bit = featureConditions[bitIndex];
if ( invert )
{
if ( bit )
{
shouldGenerate = false;
}
}
else
{
if ( !bit )
{
shouldGenerate = false;
}
}
}
}
if (!s.v27.empty())
{
for (unsigned int depIdx = 0; depIdx < s.v27.size(); ++depIdx)
{
if (s.id != eGenerateStructure_CheckBlock)
{
auto it = failures.find(s.v27[depIdx]);
if (it != failures.end() && it->second)
{
shouldGenerate = false;
break;
}
}
}
}
if (shouldGenerate && !s.cropAges.empty())
{
for (unsigned int exclIdx = 0; exclIdx < s.cropAges.size(); ++exclIdx)
{
for (unsigned int remapIdx = 0; remapIdx < tileOptionRemap.size(); ++remapIdx)
{
if (s.cropAges[exclIdx] == tileOptionRemap[remapIdx])
{
shouldGenerate = false;
break;
}
}
if (!shouldGenerate) break;
}
}
if (!shouldGenerate)
continue;
// @Patoke todo: this is broken, please fix
for (unsigned int remapIdx = 0; remapIdx < tileOptionRemap.size(); ++remapIdx)
{
int offsetValue = tileOptionRemap[remapIdx];
// start
if (s.startRemap0 == remapIdx) s.x0 += offsetValue;
if (s.startRemap1 == remapIdx) s.x0 += offsetValue;
if (s.startRemap2 == remapIdx) s.y0 += offsetValue;
// end
if (s.endRemap0 == remapIdx) s.x1 += offsetValue;
if (s.endRemap1 == remapIdx) s.x1 += offsetValue;
if (s.endRemap2 == remapIdx) s.y1 += offsetValue;
}
switch( s.id )
{
case eGenerateStructure_Block:
placeBlock( level, s.tileId, getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data ), s.x0, s.y0, s.z0, chunkBB );
break;
/*
case eGenerateStructure_maybeGenerateBlock:
maybeGenerateBlock( level, chunkBB, random, s.probability, s.x0, s.y0, s.z0, s.tileId, s.data );
break;
case eGenerateStructure_AirBox:
generateAirBox( level, chunkBB, s.x0, s.y0, s.z0, s.x1, s.y1, s.z1 );
break;
*/
case eGenerateStructure_Box:
{
int data0 = getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data );
int data1 = getBlockDataValue( (StructureTable::eBlockDataType)s.secondDataType, s.secondTileId, s.secondData );
generateBox( level, chunkBB, s.x0, s.y0, s.z0, s.x1, s.y1, s.z1, s.tileId, data0, s.secondTileId, data1, false );
break;
}
/*
case eGenerateStructure_MaybeBox:
generateMaybeBox( level, chunkBB, random, s.probability, s.x0, s.y0, s.z0, s.x1, s.y1, s.z1, s.tileId, s.data, false );
break;
case eGenerateStructure_UpperHalfSphere:
generateUpperHalfSphere( level, chunkBB, s.x0, s.y0, s.z0, s.x1, s.y1, s.z1, s.tileId, false );
break;
*/
case eGenerateStructure_FullSphere:
{
int data0 = getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data );
int data1 = getBlockDataValue( (StructureTable::eBlockDataType)s.secondDataType, s.secondTileId, s.secondData );
generateFullSphere( level, chunkBB, s.x0, s.y0, s.z0, s.v25[0], s.tileId, data0, s.secondTileId, data1, false );
break;
}
/*
case eGenerateStructure_AirColumnUp:
generateAirColumnUp( level, s.x0, s.y0, s.z0, chunkBB );
break;
*/
case eGenerateStructure_fillColumnDown:
{
int data0 = getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data );
fillColumnDown( level, s.tileId, data0, s.x0, s.y0, s.z0, chunkBB );
break;
}
case eGenerateStructure_fillBoxDown:
{
int data0 = getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data );
fillBoxDown( level, s.tileId, data0, s.x0, s.y0, s.z0, s.x1, s.z1, chunkBB );
break;
}
case eGenerateStructure_generateAirBoxUp:
generateAirBoxUp( level, s.x0, s.z0, s.x1, s.z1, s.y0, chunkBB );
break;
case eGenerateStructure_Crops:
{
if( tileOptionRemap.empty() )
break;
if( s.cropAges.size() != 2 )
break;
if( piece->cropTiles.empty() )
break;
if( s.tileId >= (int)tileOptionRemap.size() )
break;
if( s.x0 > s.x1 )
break;
int minCropAge = s.cropAges[0];
int maxCropAge = s.cropAges[1];
int remapIdx = tileOptionRemap[s.tileId];
int cropTileId = ( remapIdx >= (int)piece->cropTiles.size() ) ? piece->cropTiles.back() : piece->cropTiles[remapIdx];
createCrops( level, chunkBB, random, s.x0, s.z0, s.x1, s.z1, s.y0, cropTileId, minCropAge, maxCropAge);
break;
}
case eGenerateStructure_CreateDoor:
{
int worldX = getWorldX( s.x0, s.z0 );
int worldY = getWorldY( s.y0 );
int worldZ = getWorldZ( s.x0, s.z0 );
if( chunkBB->isInside( worldX, worldY, worldZ ) )
{
int doorData = getBlockDataValue( (StructureTable::eBlockDataType)s.dataType, s.tileId, s.data );
if( s.tileId == Tile::door_wood_Id )
{
DoorItem::place( level, worldX, worldY, worldZ, doorData, Tile::door_wood );
}
else
{
DoorItem::place( level, worldX, worldY, worldZ, doorData, Tile::door_iron );
}
}
break;
}
case eGenerateStructure_CheckBlock:
{
int block = getBlock(level, s.x0, s.y0, s.z0, chunkBB);
bool match = (block != 0);
if (!s.v25.empty() && s.v25[0] == 0)
{
match = (block == 0);
}
if (!match)
{
if (!s.v27.empty())
{
failures[s.v27[0]] = true;
}
}
break;
}
default:
break;
}
}
vector<bool> newObjectPlacedFlags;
for ( unsigned int i = 0; i < piece->objects.size(); ++i )
{
const StructureTable::ObjectData &o = piece->objects[i];
bool process = true;
if ( (int)objectPlacedFlags.size() == (int)piece->objects.size() )
{
process = objectPlacedFlags[i];
}
bool placed = false;
if ( process )
{
if ( o.id == eGenerateObject_Chest || o.id == eGenerateObject_Dispenser )
{
if ( o.canGenEnchantedBooks )
{
WeighedTreasure* book = Item::enchantedBook->createForRandomTreasure( random, o.minEnchantedBooks, o.maxEnchantedBooks, o.enchantedBookWeight );
WeighedTreasureArray treasure = WeighedTreasureArray( treasureCount + 1 );
for ( int k = 0; k < treasureCount; k++ )
{
treasure[k] = treasureItems[k];
treasure[treasureCount] = book;
}
int rollOffset = random->nextInt( o.rollWeight );
if ( o.id == eGenerateObject_Chest )
{
placed = createChest( level, chunkBB, random, o.x, o.y, o.z, treasure, o.rollCount + rollOffset );
}
else
{
placed = createDispenser( level, chunkBB, random, o.x, o.y, o.z, o.dispenserDir, treasure, o.rollCount + rollOffset );
}
delete book;
}
else
{
int rollOffset = random->nextInt( o.rollWeight );
if ( o.id == eGenerateObject_Chest )
{
placed = createChest( level, chunkBB, random, o.x, o.y, o.z, treasureItems, o.rollCount + rollOffset );
}
else
{
placed = createDispenser( level, chunkBB, random, o.x, o.y, o.z, o.dispenserDir, treasureItems, o.rollCount + rollOffset );
}
}
}
}
newObjectPlacedFlags.push_back( placed );
}
objectPlacedFlags = newObjectPlacedFlags;
for ( unsigned int j = 0; j < piece->entities.size(); ++j )
{
const StructureTable::EntityData &e = piece->entities[j];
if ( j >= entitySpawnCounts.size() )
{
entitySpawnCounts.push_back( 0 );
}
spawnEntity( level, chunkBB, e.x, e.y, e.z, (eGenerateEntity)e.id, e.count, const_cast<vector<int>&>( e.professions ), entitySpawnCounts[j] );
}
for (int i = 0; i < treasureItems.length; i++)
{
delete treasureItems[i];
DoorItem::place( level, worldX, worldY, worldZ, orientation, Tile::door_wood );
}
}
void StructurePiece::setDirty()
{
dirty = true;
}
void StructurePiece::spawnEntity( Level *level, BoundingBox *chunkBB, int x, int y, int z, eGenerateEntity entityType, int count, vector<int> &professions, int &entitySpawnCounts )
{
while ( entitySpawnCounts < count )
{
int worldX = getWorldX( x, z );
int worldY = getWorldY( y );
int worldZ = getWorldZ( x, z );
worldX += entitySpawnCounts;
if ( !chunkBB->isInside( worldX, worldY, worldZ ) )
{
return;
}
if ( entityType == eGenerateEntity_Witch )
{
setDirty();
shared_ptr<Witch> witch = shared_ptr<Witch>( new Witch( level ) );
witch->moveTo( worldX + 0.5, worldY, worldZ + 0.5, 0, 0 );
level->addEntity( witch );
}
else if ( entityType == eGenerateEntity_Villager )
{
int profession = 0;
if ( !professions.empty() && entitySpawnCounts < professions.size() )
profession = professions[entitySpawnCounts];
setDirty();
shared_ptr<Villager> villager = shared_ptr<Villager>( new Villager( level, profession ) );
villager->moveTo( worldX + 0.5, worldY, worldZ + 0.5, 0, 0 );
level->addEntity( villager );
}
entitySpawnCounts++;
}
}
void StructurePiece::getRandomValuesFromDataSet( StructureTable::StructurePiece *piece, Random *random, vector<bool> &stateConditions, vector<int> &placedTiles )
{
for ( int i = 0; i < piece->v8; i++ )
{
bool value = random->nextBoolean();
stateConditions.push_back( value );
}
for ( unsigned int i = 0; i < piece->v11.size(); i++ )
{
int value = random->nextInt( piece->v11[i] );
placedTiles.push_back( value );
}
}
void StructurePiece::addStructurePieceSaveData(DataOutputStream *dos, vector<bool> &objectState, vector<bool> &featureConditions, vector<int> &tileOptionRemap, vector<int> &entitySpawnCounts)
{
addBoolSaveData( dos, objectState );
addBoolSaveData( dos, featureConditions );
addIntSaveData( dos, tileOptionRemap );
addIntSaveData( dos, entitySpawnCounts );
}
void StructurePiece::readStructurePieceSaveData(DataInputStream *dis, vector<bool> &objectState, vector<bool> &featureConditions, vector<int> &tileOptionRemap, vector<int> &entitySpawnCounts)
{
objectState = readBoolSaveData( dis );
featureConditions = readBoolSaveData( dis );
tileOptionRemap = readIntSaveData( dis );
entitySpawnCounts = readIntSaveData( dis );
}
void StructurePiece::clearDirty()
{
dirty = false;
}
bool StructurePiece::isDirty()
{
return dirty;
}
void StructurePiece::addBoolSaveData(DataOutputStream *dos, vector<bool> &data)
{
wstring outData;
outData.assign( L"\0" );
for ( size_t i = 0; i < data.size(); ++i )
{
wostringstream woss;
woss << boolalpha << data[i];
outData.append( woss.str() );
if ( i < data.size() - 1 )
{
outData.append( L"," );
}
}
dos->writeUTF( outData );
}
vector<bool> StructurePiece::readBoolSaveData( DataInputStream *dis )
{
wstring data = dis->readUTF();
vector<wstring> tokens = stringSplit( data, L',' );
vector<bool> outData;
for ( size_t i = 0; i < tokens.size(); ++i )
{
wistringstream wiss( tokens[i] );
bool outVal = false;
wiss >> boolalpha >> outVal;
outData.push_back( outVal );
}
return outData;
}
void StructurePiece::addIntSaveData(DataOutputStream *dos, vector<int> &data)
{
wstring outData;
outData.assign( L"\0" );
for ( size_t i = 0; i < data.size(); ++i )
{
wostringstream woss;
woss << dec << data[i];
outData.append( woss.str() );
if ( i < data.size() - 1 )
{
outData.append( L"," );
}
}
dos->writeUTF( outData );
}
vector<int> StructurePiece::readIntSaveData(DataInputStream *dis)
{
wstring data = dis->readUTF();
vector<wstring> tokens = stringSplit( data, L',' );
vector<int> outData;
for ( size_t i = 0; i < tokens.size(); ++i )
{
wistringstream wiss( tokens[i] );
int outVal = 0;
wiss >> dec >> outVal;
outData.push_back( outVal );
}
return outData;
}