mirror of
https://github.com/neoStudiosLCE/neoLegacy.git
synced 2026-07-03 04:17:03 +00:00
fix: guardians spawn in structure
This commit is contained in:
parent
f313489c97
commit
5c140a95b7
|
|
@ -28,6 +28,9 @@
|
|||
#include "../Minecraft.World/ItemEntity.h"
|
||||
#include "../Minecraft.World/Arrow.h"
|
||||
#include "../Minecraft.World/PrimedTnt.h"
|
||||
#include "../Minecraft.World/RandomLevelSource.h"
|
||||
#include "../Minecraft.World/MobCategory.h"
|
||||
#include "../Minecraft.World/OceanMonumentFeature.h"
|
||||
#include "../Minecraft.World/FallingTile.h"
|
||||
#include "../Minecraft.World/net.minecraft.network.packet.h"
|
||||
#include "../Minecraft.World/Mth.h"
|
||||
|
|
@ -377,6 +380,19 @@ void ServerLevel::tick()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool ServerLevel::canMobSpawnAt(MobCategory *mobCategory, Biome::MobSpawnerData *data, const BlockPos& pos)
|
||||
{
|
||||
RandomLevelSource *rls = dynamic_cast<RandomLevelSource*>(getChunkSource());
|
||||
if (rls)
|
||||
{
|
||||
if (mobCategory == MobCategory::monster && rls->oceanMonument->isInsideBoundingFeature(pos.getX(), pos.getY(), pos.getZ()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Biome::MobSpawnerData *ServerLevel::getRandomMobSpawnAt(MobCategory *mobCategory, int x, int y, int z)
|
||||
{
|
||||
vector<Biome::MobSpawnerData *> *mobList = getChunkSource()->getMobsAt(mobCategory, x, y, z);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public:
|
|||
~ServerLevel();
|
||||
void tick();
|
||||
Biome::MobSpawnerData *getRandomMobSpawnAt(MobCategory *mobCategory, int x, int y, int z);
|
||||
bool canMobSpawnAt(MobCategory *mobCategory, Biome::MobSpawnerData *data, const BlockPos& pos);
|
||||
void updateSleepingPlayerList();
|
||||
protected:
|
||||
void awakenAllPlayers();
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ public:
|
|||
virtual ChunkStorage *createStorage(File dir);
|
||||
|
||||
virtual bool isValidSpawn(int x, int z) const;
|
||||
|
||||
|
||||
virtual bool isHasCeiling() const { return hasCeiling; }
|
||||
virtual float getTimeOfDay(int64_t time, float a) const;
|
||||
virtual int getMoonPhase(int64_t time) const;
|
||||
virtual bool isNaturalDimension();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
class Direction
|
||||
{
|
||||
public:
|
||||
|
|
@ -8,68 +7,71 @@ public:
|
|||
static const int WEST = 1;
|
||||
static const int NORTH = 2;
|
||||
static const int EAST = 3;
|
||||
|
||||
static const int STEP_X[];
|
||||
static const int STEP_Z[];
|
||||
|
||||
static const wstring NAMES[];;
|
||||
|
||||
// for [direction] it gives [tile-face]
|
||||
static const wstring NAMES[];
|
||||
static int DIRECTION_FACING[];
|
||||
|
||||
// for [facing] it gives [direction]
|
||||
static int FACING_DIRECTION[];
|
||||
|
||||
// for [direction] it gives [opposite direction]
|
||||
static int DIRECTION_OPPOSITE[];
|
||||
|
||||
// for [direction] it gives [90 degrees clockwise direction]
|
||||
static int DIRECTION_CLOCKWISE[];
|
||||
|
||||
// for [direction] it gives [90 degrees counter-clockwise direction]
|
||||
static int DIRECTION_COUNTER_CLOCKWISE[];
|
||||
|
||||
// for [direction][world-facing] it gives [tile-facing]
|
||||
static int RELATIVE_DIRECTION_FACING[4][6];
|
||||
|
||||
static int getDirection(double xd, double zd);
|
||||
static int getDirection(int x0, int z0, int x1, int z1);
|
||||
|
||||
static int getStepX(int direction) {
|
||||
switch (direction) {
|
||||
case WEST: return -1;
|
||||
case EAST: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int getStepZ(int direction) {
|
||||
switch (direction) {
|
||||
case NORTH: return -1;
|
||||
case SOUTH: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
static int getStepY(int direction) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int getStepX(int direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case WEST: return -1;
|
||||
case EAST: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Plane
|
||||
{
|
||||
public:
|
||||
static int getStepZ(int direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case NORTH: return -1;
|
||||
case SOUTH: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int getRandomFace(Random* random)
|
||||
{
|
||||
|
||||
static const int horizontal[4] = {
|
||||
Direction::SOUTH,
|
||||
Direction::WEST,
|
||||
Direction::NORTH,
|
||||
Direction::EAST
|
||||
};
|
||||
return horizontal[random->nextInt(4)];
|
||||
}
|
||||
};
|
||||
static int getStepY(int direction)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
static int get3DDataValue(int dir6)
|
||||
{
|
||||
return dir6;
|
||||
}
|
||||
|
||||
static int from3DDataValue(int val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
static int getOpposite(int dir6)
|
||||
{
|
||||
static const int opp[6] = { 1, 0, 3, 2, 5, 4 };
|
||||
if (dir6 >= 0 && dir6 < 6)
|
||||
return opp[dir6];
|
||||
return dir6;
|
||||
}
|
||||
|
||||
class Plane
|
||||
{
|
||||
public:
|
||||
static int getRandomFace(Random* random)
|
||||
{
|
||||
static const int horizontal[4] = {
|
||||
Direction::SOUTH,
|
||||
Direction::WEST,
|
||||
Direction::NORTH,
|
||||
Direction::EAST
|
||||
};
|
||||
return horizontal[random->nextInt(4)];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "com.mojang.nbt.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#include "../Minecraft.World/net.minecraft.world.entity.animal.h"
|
||||
#include "MobEffect.h"
|
||||
#include "MobEffectInstance.h"
|
||||
#include <Difficulty.h>
|
||||
|
||||
|
||||
void Guardian::_init()
|
||||
|
|
@ -34,7 +35,7 @@ void Guardian::_init()
|
|||
attackTimer = 0;
|
||||
}
|
||||
|
||||
Guardian::Guardian(Level *level) : WaterAnimal(level)
|
||||
Guardian::Guardian(Level *level) : Monster(level)
|
||||
{
|
||||
this->defineSynchedData();
|
||||
registerAttributes();
|
||||
|
|
@ -52,7 +53,7 @@ Guardian::Guardian(Level *level) : WaterAnimal(level)
|
|||
|
||||
void Guardian::registerAttributes()
|
||||
{
|
||||
WaterAnimal::registerAttributes();
|
||||
Monster::registerAttributes();
|
||||
getAttributes()->registerAttribute(SharedMonsterAttributes::ATTACK_DAMAGE);
|
||||
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6.0);
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.5);
|
||||
|
|
@ -64,7 +65,7 @@ void Guardian::registerAttributes()
|
|||
|
||||
void Guardian::defineSynchedData()
|
||||
{
|
||||
WaterAnimal::defineSynchedData();
|
||||
Monster::defineSynchedData();
|
||||
entityData->define(16, (byte)0);
|
||||
entityData->define(17, 0);
|
||||
}
|
||||
|
|
@ -75,13 +76,13 @@ void Guardian::defineSynchedData()
|
|||
|
||||
void Guardian::readAdditionalSaveData(CompoundTag *tag)
|
||||
{
|
||||
WaterAnimal::readAdditionalSaveData(tag);
|
||||
Monster::readAdditionalSaveData(tag);
|
||||
setElder(tag->getBoolean(L"Elder"));
|
||||
}
|
||||
|
||||
void Guardian::addAdditonalSaveData(CompoundTag *tag)
|
||||
{
|
||||
WaterAnimal::addAdditonalSaveData(tag);
|
||||
Monster::addAdditonalSaveData(tag);
|
||||
tag->putBoolean(L"Elder", isElder());
|
||||
}
|
||||
|
||||
|
|
@ -202,13 +203,6 @@ float Guardian::getSpikesAnimation(float partialTicks)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
void Guardian::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel)
|
||||
{
|
||||
//loot (prismarine, sponge)
|
||||
}
|
||||
|
||||
float Guardian::getEyeHeight()
|
||||
{
|
||||
return bbHeight * 0.5f;
|
||||
|
|
@ -254,7 +248,7 @@ void Guardian::lookAt(shared_ptr<Entity> e, float yMax, float xMax)
|
|||
|
||||
void Guardian::serverAiStep()
|
||||
{
|
||||
WaterAnimal::serverAiStep();
|
||||
Monster::serverAiStep();
|
||||
|
||||
if (isElder() && !level->isClientSide)
|
||||
{
|
||||
|
|
@ -348,7 +342,16 @@ void Guardian::serverAiStep()
|
|||
{
|
||||
float angle = random->nextFloat() * (float)PI * 2.0f;
|
||||
tx = Mth::cos(angle) * 0.2f;
|
||||
ty = -0.1f + random->nextFloat() * 0.2f;
|
||||
|
||||
|
||||
if (isElder()) {
|
||||
|
||||
ty = -0.15f + random->nextFloat() * 0.15f;
|
||||
} else {
|
||||
|
||||
ty = -0.1f + random->nextFloat() * 0.2f;
|
||||
}
|
||||
|
||||
tz = Mth::sin(angle) * 0.2f;
|
||||
noActionTime = 0;
|
||||
}
|
||||
|
|
@ -437,7 +440,7 @@ void Guardian::aiStep()
|
|||
xBodyRotO = xBodyRot;
|
||||
zBodyRotO = zBodyRot;
|
||||
|
||||
WaterAnimal::aiStep();
|
||||
Monster::aiStep();
|
||||
}
|
||||
|
||||
void Guardian::updateSize(bool elder)
|
||||
|
|
@ -458,10 +461,11 @@ void Guardian::travel(float xa, float ya)
|
|||
xd *= 0.9f;
|
||||
yd *= 0.9f;
|
||||
zd *= 0.9f;
|
||||
yd -= 0.02f;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaterAnimal::travel(xa, ya);
|
||||
Monster::travel(xa, ya);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -473,10 +477,11 @@ void Guardian::travel(float xa, float ya)
|
|||
xd *= 0.9f;
|
||||
yd *= 0.9f;
|
||||
zd *= 0.9f;
|
||||
yd -= 0.02f;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaterAnimal::travel(xa, ya);
|
||||
Monster::travel(xa, ya);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +489,7 @@ void Guardian::travel(float xa, float ya)
|
|||
|
||||
MobGroupData *Guardian::finalizeMobSpawn(MobGroupData *groupData, int extraData)
|
||||
{
|
||||
WaterAnimal::finalizeMobSpawn(groupData, extraData);
|
||||
Monster::finalizeMobSpawn(groupData, extraData);
|
||||
if (extraData == 1)
|
||||
setElder(true);
|
||||
return groupData;
|
||||
|
|
@ -508,7 +513,7 @@ void Guardian::handleEntityEvent(byte eventId)
|
|||
}
|
||||
}
|
||||
|
||||
WaterAnimal::handleEntityEvent(eventId);
|
||||
Monster::handleEntityEvent(eventId);
|
||||
}
|
||||
|
||||
int Guardian::getAmbientSound()
|
||||
|
|
@ -621,7 +626,60 @@ float Guardian::getSoundVolume()
|
|||
return 1.0f;
|
||||
}
|
||||
|
||||
int Guardian::getDeathLoot()
|
||||
bool Guardian::removeWhenFarAway()
|
||||
{
|
||||
return 0;
|
||||
return !isElder();
|
||||
}
|
||||
|
||||
void Guardian::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel)
|
||||
{
|
||||
|
||||
int shards = 2 + random->nextInt(2);
|
||||
spawnAtLocation(Item::prismarine_shard_Id, shards, 0.5f);
|
||||
|
||||
|
||||
int crystals = random->nextInt(2);
|
||||
if (crystals > 0)
|
||||
spawnAtLocation(Item::prismarine_cystal_Id, crystals, 0.5f);
|
||||
|
||||
|
||||
spawnAtLocation(Item::fish_raw_Id, 1, 0.5f);
|
||||
|
||||
|
||||
if (isElder())
|
||||
{
|
||||
spawnAtLocation(Tile::sponge_Id, 1, 0.5f);
|
||||
}
|
||||
|
||||
|
||||
if (wasKilledByPlayer)
|
||||
{
|
||||
level->addEntity(std::make_shared<ExperienceOrb>(
|
||||
level, x, y, z,
|
||||
isElder() ? 10 : 5));
|
||||
}
|
||||
}
|
||||
|
||||
bool Guardian::canSpawn()
|
||||
{
|
||||
if (level->difficulty == Difficulty::PEACEFUL)
|
||||
return false;
|
||||
|
||||
|
||||
bool bypassSky = random->nextInt(20) == 0;
|
||||
if (!bypassSky)
|
||||
{
|
||||
int bx = Mth::floor(x);
|
||||
int by = Mth::floor(y);
|
||||
int bz = Mth::floor(z);
|
||||
if (level->canSeeSkyFromBelowWater(bx, by, bz))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!isInWater())
|
||||
return false;
|
||||
|
||||
|
||||
return level->isUnobstructed(bb) && level->getCubes(shared_from_this(), bb)->empty();
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
#pragma once
|
||||
using namespace std;
|
||||
#include "WaterAnimal.h"
|
||||
#include "Monster.h"
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
|
||||
class Guardian : public WaterAnimal
|
||||
class Guardian : public Monster
|
||||
{
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_GUARDIAN; }
|
||||
|
|
@ -34,12 +34,12 @@ protected:
|
|||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
virtual float getSoundVolume();
|
||||
virtual int getDeathLoot();
|
||||
virtual bool makeStepSound();
|
||||
void playFlopSound();
|
||||
void playAttackSound();
|
||||
void playCurseSound();
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
virtual bool removeWhenFarAway();
|
||||
virtual void serverAiStep();
|
||||
|
||||
public:
|
||||
|
|
@ -57,6 +57,8 @@ public:
|
|||
|
||||
bool isMoving();
|
||||
void setMoving(bool moving);
|
||||
virtual bool canSpawn();
|
||||
virtual bool isWaterMob() { return true; }
|
||||
|
||||
|
||||
int getTargetedEntityId();
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,20 @@ int Level::getDaytimeRawBrightness(int x, int y, int z)
|
|||
return getChunk(x >> 4, z >> 4)->getRawBrightness(x & 15, y, z & 15, 0);
|
||||
}
|
||||
|
||||
int Level::getDaytimeRawBrightness(const BlockPos& pos)
|
||||
{
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
|
||||
if (y < 0)
|
||||
return 0;
|
||||
|
||||
if (y >= maxBuildHeight)
|
||||
y = maxBuildHeight - 1;
|
||||
|
||||
return getChunk(x >> 4, z >> 4)->getRawBrightness(x & 15, y, z & 15, 0);
|
||||
}
|
||||
|
||||
int Level::getRawBrightness(int x, int y, int z)
|
||||
{
|
||||
|
|
@ -4810,4 +4824,42 @@ BlockPos Level::getHeightmapPos(int x, int z)
|
|||
}
|
||||
|
||||
return BlockPos(x, 0, z);
|
||||
}
|
||||
|
||||
bool Level::canSeeSkyFromBelowWater(int x, int y, int z)
|
||||
{
|
||||
if (y < 63)
|
||||
{
|
||||
int cx = x;
|
||||
int cy = 63;
|
||||
int cz = z;
|
||||
|
||||
|
||||
if (dimension->isHasCeiling())
|
||||
return false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
cy--;
|
||||
if (cy <= y)
|
||||
break;
|
||||
|
||||
int tileId = getTile(cx, cy, cz);
|
||||
|
||||
if (Tile::lightBlock[tileId] > 0)
|
||||
{
|
||||
Material *mat = nullptr;
|
||||
if (Tile::tiles[tileId] != nullptr)
|
||||
mat = Tile::tiles[tileId]->material;
|
||||
|
||||
if (mat == nullptr || !mat->isLiquid())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !dimension->isHasCeiling();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ using namespace std;
|
|||
#include "Definitions.h"
|
||||
#include "ParticleTypes.h"
|
||||
#include "Biome.h"
|
||||
#include "BlockPos.h"
|
||||
#include "C4JThread.h"
|
||||
|
||||
#ifdef __PSVITA__
|
||||
|
|
@ -51,6 +52,7 @@ class Minecart;
|
|||
class EntitySelector;
|
||||
class Scoreboard;
|
||||
class GameRules;
|
||||
class BlockPos;
|
||||
|
||||
class Level : public LevelSource
|
||||
{
|
||||
|
|
@ -210,6 +212,7 @@ public:
|
|||
bool reallyHasChunksAt(int x, int y, int z, int r); // 4J added
|
||||
bool reallyHasChunksAt(int x0, int y0, int z0, int x1, int y1, int z1); // 4J added
|
||||
BlockPos getHeightmapPos(int x, int z);
|
||||
bool canSeeSkyFromBelowWater(int x, int y, int z);
|
||||
public:
|
||||
bool hasChunk(int x, int z);
|
||||
bool reallyHasChunk(int x, int z ); // 4J added
|
||||
|
|
@ -237,6 +240,7 @@ public:
|
|||
virtual bool isTileToBeTickedAt(int x, int y, int z, int tileId);
|
||||
bool canSeeSky(int x, int y, int z);
|
||||
int getDaytimeRawBrightness(int x, int y, int z);
|
||||
int getDaytimeRawBrightness(const BlockPos& pos);
|
||||
int getRawBrightness(int x, int y, int z);
|
||||
int getRawBrightness(int x, int y, int z, bool propagate);
|
||||
bool isSkyLit(int x, int y, int z);
|
||||
|
|
@ -560,4 +564,5 @@ public:
|
|||
};
|
||||
|
||||
bool canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@
|
|||
#include "Level.h"
|
||||
#include "ChunkPos.h"
|
||||
#include "TilePos.h"
|
||||
#include "BlockPos.h"
|
||||
#include "net.minecraft.world.level.chunk.h"
|
||||
#include "../Minecraft.Client/ServerLevel.h"
|
||||
#include "MobSpawner.h"
|
||||
#include "Dimension.h"
|
||||
#include "OceanMonumentFeature.h"
|
||||
#include "RandomLevelSource.h"
|
||||
|
||||
const int MobSpawner::MIN_SPAWN_DISTANCE = 24;
|
||||
|
||||
|
|
@ -195,6 +199,7 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
for (unsigned int i = 0; i < MobCategory::values.length; i++)
|
||||
{
|
||||
MobCategory *mobCategory = MobCategory::values[i];
|
||||
|
||||
if ((mobCategory->isFriendly() && !spawnFriendlies) || (!mobCategory->isFriendly() && !spawnEnemies) || (mobCategory->isPersistent() && !spawnPersistent))
|
||||
{
|
||||
continue;
|
||||
|
|
@ -212,7 +217,8 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
// 4J - this is now quite different to the java version. We just have global max counts for the level whereas the original has a max per chunk that
|
||||
// scales with the number of chunks to be polled.
|
||||
int categoryCount = level->countInstanceOf( mobCategory->getEnumBaseClass(), mobCategory->isSingleType());
|
||||
if( categoryCount >= mobCategory->getMaxInstancesPerLevel())
|
||||
|
||||
if( categoryCount >= mobCategory->getMaxInstancesPerLevel() && mobCategory != MobCategory::monster)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -235,13 +241,18 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
// 4J - don't let this actually create/load a chunk that isn't here already - we'll let the normal updateDirtyChunks etc. processes do that, so it can happen on another thread
|
||||
if( !level->hasChunk(cp->x,cp->z) ) continue;
|
||||
|
||||
TilePos start = getRandomPosWithin(level, cp->x, cp->z);
|
||||
int xStart = start.x;
|
||||
int yStart = start.y;
|
||||
int zStart = start.z;
|
||||
|
||||
int xStart = cp->x * 16 + level->random->nextInt(16);
|
||||
int zStart = cp->z * 16 + level->random->nextInt(16);
|
||||
|
||||
int height = level->getChunk(cp->x, cp->z)->getHeightmap(xStart & 15, zStart & 15);
|
||||
int yMax = (height + 1 + 15) & ~15;
|
||||
if (yMax <= 0) yMax = 256;
|
||||
int yStart = level->random->nextInt(yMax);
|
||||
|
||||
if (level->isSolidBlockingTile(xStart, yStart, zStart)) continue;
|
||||
if (level->getMaterial(xStart, yStart, zStart) != mobCategory->getSpawnPositionMaterial()) continue;
|
||||
if (level->getMaterial(xStart, yStart, zStart) != mobCategory->getSpawnPositionMaterial() &&
|
||||
!(mobCategory == MobCategory::monster && level->getMaterial(xStart, yStart, zStart) == Material::water)) continue;
|
||||
int clusterSize = 0;
|
||||
|
||||
for (int dd = 0; dd < 3; dd++)
|
||||
|
|
@ -264,11 +275,18 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
// 4J - don't let this actually create/load a chunk that isn't here already - we'll let the normal updateDirtyChunks etc. processes do that, so it can happen on another thread
|
||||
if( !level->hasChunkAt( x, y, z ) ) continue;
|
||||
|
||||
if (isSpawnPositionOk(mobCategory, level, x, y, z))
|
||||
BlockPos pos(x, y, z);
|
||||
if (currentMobType == nullptr)
|
||||
{
|
||||
currentMobType = level->getRandomMobSpawnAt(mobCategory, x, y, z);
|
||||
}
|
||||
|
||||
if (currentMobType != nullptr && (level->canMobSpawnAt(mobCategory, currentMobType, pos) || isSpawnPositionOk(mobCategory, level, x, y, z)))
|
||||
{
|
||||
float xx = x + 0.5f;
|
||||
float yy = static_cast<float>(y);
|
||||
float zz = z + 0.5f;
|
||||
|
||||
if (level->getNearestPlayer(xx, yy, zz, MIN_SPAWN_DISTANCE) != nullptr)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -285,15 +303,6 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
}
|
||||
}
|
||||
|
||||
if (currentMobType == nullptr)
|
||||
{
|
||||
currentMobType = level->getRandomMobSpawnAt(mobCategory, x, y, z);
|
||||
if (currentMobType == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Mob> mob;
|
||||
// 4J - removed try/catch
|
||||
// try
|
||||
|
|
@ -316,18 +325,13 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
|
||||
if( ( mobType & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK ) || ( mobType & eTYPE_MONSTER ) )
|
||||
{
|
||||
// even more special rule for ghasts, because filling up the nether with 25 of them is a bit unpleasant. In the java version they are
|
||||
// only limited by the fact that the world fills up with pig zombies (the only other type of enemy mob in the nether) before them - they
|
||||
// aren't actually even counted properly themselves
|
||||
if( mobType == eTYPE_GHAST )
|
||||
{
|
||||
if( level->countInstanceOf(mobType, true) >= 4 ) continue;
|
||||
}
|
||||
else if( mobType == eTYPE_ENDERMAN && level->dimension->id == 1 )
|
||||
{
|
||||
// Special rule for the end, as we only have Endermen (plus the dragon). Increase the spawnable counts based on level difficulty
|
||||
int maxEndermen = mobCategory->getMaxInstancesPerLevel();
|
||||
|
||||
if( level->difficulty == Difficulty::NORMAL )
|
||||
{
|
||||
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/4;
|
||||
|
|
@ -336,7 +340,6 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
|||
{
|
||||
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/2;
|
||||
}
|
||||
|
||||
if( level->countInstanceOf(mobType, true) >= maxEndermen ) continue;
|
||||
}
|
||||
else if( level->countInstanceOf(mobType, true) >= ( mobCategory->getMaxInstancesPerLevel() / 2 ) ) continue;
|
||||
|
|
@ -391,6 +394,16 @@ bool MobSpawner::isSpawnPositionOk(MobCategory *category, Level *level, int x, i
|
|||
}
|
||||
#endif
|
||||
|
||||
if (category == MobCategory::monster && level->getMaterial(x, y, z) == Material::water)
|
||||
{
|
||||
|
||||
if (level->getMaterial(x, y - 1, z)->isLiquid())
|
||||
{
|
||||
return !level->isSolidBlockingTile(x, y + 1, z);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (category->getSpawnPositionMaterial() == Material::water)
|
||||
{
|
||||
// 4J - changed to spawn water things only in deep water
|
||||
|
|
@ -403,7 +416,6 @@ bool MobSpawner::isSpawnPositionOk(MobCategory *category, Level *level, int x, i
|
|||
yo++;
|
||||
}
|
||||
|
||||
// 4J - Sometimes deep water could be just a waterfall, so check that it's wide as well
|
||||
bool inEnoughWater = false;
|
||||
if( liquidCount == 5 )
|
||||
{
|
||||
|
|
@ -425,7 +437,7 @@ bool MobSpawner::isSpawnPositionOk(MobCategory *category, Level *level, int x, i
|
|||
int tt = level->getTile(x, y - 1, z);
|
||||
return tt != Tile::unbreakable_Id && !level->isSolidBlockingTile(x, y, z) && !level->getMaterial(x, y, z)->isLiquid() && !level->isSolidBlockingTile(x, y + 1, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MobSpawner::postProcessSpawnMobs(Level *level, Biome *biome, int xo, int zo, int cellWidth, int cellHeight, Random *random)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ void OceanMonumentFeature::prescanNearby(int scanRadiusInGridCells)
|
|||
int validated = 0;
|
||||
int halfSizeChunks = this->level->getLevelData()->getXZSize() / 2;
|
||||
int halfSizeBlocks = (this->level->getLevelData()->getXZSize() * 16) / 2;
|
||||
|
||||
app.DebugPrintf("Ocean Monument pre-scan (HalfSize: %d chunks / %d blocks)\n", halfSizeChunks, halfSizeBlocks);
|
||||
|
||||
for (int gz = -scanRadiusInGridCells; gz <= scanRadiusInGridCells; gz++)
|
||||
|
|
@ -54,18 +55,28 @@ void OceanMonumentFeature::prescanNearby(int scanRadiusInGridCells)
|
|||
int blockZ = cz * 16 + 8;
|
||||
|
||||
if (Mth::abs(blockX) > halfSizeBlocks || Mth::abs(blockZ) > halfSizeBlocks)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
|
||||
if (this->isFeatureChunk(cx, cz))
|
||||
{
|
||||
validated++;
|
||||
|
||||
|
||||
int64_t key = ChunkPos::hashCode(cx, cz);
|
||||
if (cachedStructures.find(key) == cachedStructures.end())
|
||||
{
|
||||
StructureStart *start = createStructureStart(cx, cz);
|
||||
if (start != nullptr)
|
||||
{
|
||||
cachedStructures[key] = start;
|
||||
app.DebugPrintf("prescanNearby: cached MonumentStart at chunk (%d,%d)\n", cx, cz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.DebugPrintf(" Pre-scan done: %d grid slots checked, %d validated monuments found. \n", candidates, validated);
|
||||
app.DebugPrintf(" Pre-scan done: %d grid slots checked, %d validated monuments found.\n", candidates, validated);
|
||||
}
|
||||
|
||||
bool OceanMonumentFeature::isFeatureChunk(int x, int z, bool bIsSuperflat)
|
||||
|
|
@ -120,7 +131,22 @@ bool OceanMonumentFeature::isFeatureChunk(int x, int z, bool bIsSuperflat)
|
|||
StructureStart* OceanMonumentFeature::createStructureStart(int x, int z)
|
||||
{
|
||||
if (this->level == nullptr) return nullptr;
|
||||
return new MonumentStart(level, random, x, z);
|
||||
MonumentStart* start = new MonumentStart(level, random, x, z);
|
||||
|
||||
|
||||
BoundingBox* bb = start->getBoundingBox();
|
||||
if (bb != nullptr)
|
||||
{
|
||||
app.DebugPrintf("MonumentStart BB: x0=%d y0=%d z0=%d x1=%d y1=%d z1=%d\n",
|
||||
bb->x0, bb->y0, bb->z0,
|
||||
bb->x1, bb->y1, bb->z1);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("MonumentStart BB: NULL!\n");
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
OceanMonumentFeature::MonumentStart::MonumentStart() {}
|
||||
|
|
@ -137,7 +163,6 @@ OceanMonumentFeature::MonumentStart::MonumentStart(Level* level, Random* random,
|
|||
|
||||
int startX = chunkX * 16 + 8 - 29;
|
||||
int startZ = chunkZ * 16 + 8 - 29;
|
||||
|
||||
int facing = random->nextInt(4) + 2;
|
||||
|
||||
OceanMonumentPieces::MonumentBuilding* building =
|
||||
|
|
@ -145,4 +170,5 @@ OceanMonumentFeature::MonumentStart::MonumentStart(Level* level, Random* random,
|
|||
pieces.push_back(building);
|
||||
|
||||
calculateBoundingBox();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ public:
|
|||
|
||||
void prescanNearby(int scanRadiusInGridCells = 8);
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
virtual bool isFeatureChunk(int x, int z, bool bIsSuperflat = false) override;
|
||||
virtual StructureStart* createStructureStart(int x, int z) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -326,13 +326,13 @@ OceanMonumentPieces::MonumentBuilding::MonumentBuilding(Random* random, int x, i
|
|||
p->getBoundingBox()->move(baseX, minY, baseZ);
|
||||
|
||||
|
||||
BoundingBox* wing1BB = new BoundingBox(
|
||||
BoundingBox* wing1BB = BoundingBox::fromCorners(
|
||||
getWorldX(1, 1), getWorldY(1), getWorldZ(1, 1),
|
||||
getWorldX(23, 21), getWorldY(8), getWorldZ(23, 21));
|
||||
BoundingBox* wing2BB = new BoundingBox(
|
||||
BoundingBox* wing2BB = BoundingBox::fromCorners(
|
||||
getWorldX(34, 1), getWorldY(1), getWorldZ(34, 1),
|
||||
getWorldX(56, 21), getWorldY(8), getWorldZ(56, 21));
|
||||
BoundingBox* penthouseBB = new BoundingBox(
|
||||
BoundingBox* penthouseBB = BoundingBox::fromCorners(
|
||||
getWorldX(22, 22), getWorldY(13), getWorldZ(22, 22),
|
||||
getWorldX(35, 35), getWorldY(17), getWorldZ(35, 35));
|
||||
|
||||
|
|
@ -1612,7 +1612,7 @@ bool OceanMonumentPieces::WingRoom::postProcess(Level* level, Random* random, Bo
|
|||
|
||||
generateBox(level, chunkBB, 6, 0, 21, 7, 4, 21, Tile::prismarine_Id, blockPrismarineBricks(),Tile::prismarine_Id, blockPrismarineBricks(), false);
|
||||
generateBox(level, chunkBB, 15, 0, 21, 16, 4, 21, Tile::prismarine_Id, blockPrismarineBricks(),Tile::prismarine_Id, blockPrismarineBricks(), false);
|
||||
spawnElderGuardian(level, chunkBB, 11, 2, 16);
|
||||
spawnElderGuardian(level, chunkBB, 11, 5, 16);
|
||||
}
|
||||
else // wingType == 1
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ public:
|
|||
|
||||
class MonumentBuilding : public Piece
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static const int ARRAY_SIZE = 75; // 5*5*3
|
||||
RoomDefinition* entryRoom; // field_175845_o
|
||||
RoomDefinition* coreRoom; // field_175844_p
|
||||
|
|
|
|||
|
|
@ -20,4 +20,7 @@ public:
|
|||
float nextFloat();
|
||||
int64_t nextLong();
|
||||
bool nextBoolean();
|
||||
static int nextInt(Random* r, int n) { return r->nextInt(n); }
|
||||
static bool nextBoolean(Random* r) { return r->nextBoolean(); }
|
||||
static long long nextLong(Random* r) { return r->nextLong(); }
|
||||
};
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
#ifdef __PS3__
|
||||
#include "../Minecraft.Client/PS3/SPU_Tasks/PerlinNoise/PerlinNoiseJob.h"
|
||||
#include "C4JSpursJob.h"
|
||||
#include <OceanMonumentFeature.cpp>
|
||||
#include <OceanMonumentFeature.cpp>
|
||||
static PerlinNoise_DataIn g_lperlinNoise1_SPU __attribute__((__aligned__(16)));
|
||||
static PerlinNoise_DataIn g_lperlinNoise2_SPU __attribute__((__aligned__(16)));
|
||||
static PerlinNoise_DataIn g_perlinNoise1_SPU __attribute__((__aligned__(16)));
|
||||
|
|
@ -841,23 +843,21 @@ wstring RandomLevelSource::gatherStats()
|
|||
|
||||
vector<Biome::MobSpawnerData *> *RandomLevelSource::getMobsAt(MobCategory *mobCategory, int x, int y, int z)
|
||||
{
|
||||
Biome *biome = level->getBiome(x, z);
|
||||
if (biome == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (mobCategory == MobCategory::monster)
|
||||
{
|
||||
if (scatteredFeature->isSwamphut(x, y, z))
|
||||
{
|
||||
return scatteredFeature->getSwamphutEnemies();
|
||||
}
|
||||
if (oceanMonument->isInsideFeature(x, y, z))
|
||||
{
|
||||
Biome *biome = level->getBiome(x, z);
|
||||
if (biome == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (mobCategory == MobCategory::monster)
|
||||
{
|
||||
if (scatteredFeature->isSwamphut(x, y, z))
|
||||
return scatteredFeature->getSwamphutEnemies();
|
||||
|
||||
if (oceanMonument->isInsideBoundingFeature(x, y, z))
|
||||
return oceanMonument->getMonumentEnemies();
|
||||
}
|
||||
}
|
||||
return biome->getMobs(mobCategory);
|
||||
}
|
||||
|
||||
|
||||
return biome->getMobs(mobCategory);
|
||||
}
|
||||
|
||||
TilePos *RandomLevelSource::findNearestMapFeature(Level *level, const wstring& featureName, int x, int y, int z)
|
||||
|
|
@ -878,4 +878,4 @@ void RandomLevelSource::recreateLogicStructuresForChunk(int chunkX, int chunkZ)
|
|||
strongholdFeature->apply(this, level, chunkX, chunkZ, byteArray());
|
||||
scatteredFeature->apply(this, level, chunkX, chunkZ, byteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include "ChunkSource.h"
|
||||
#include "OceanMonumentFeature.h"
|
||||
|
||||
class ProgressListener;
|
||||
class LargeFeature;
|
||||
|
|
@ -62,7 +63,7 @@ public:
|
|||
public:
|
||||
void buildSurfaces(int xOffs, int zOffs, byteArray blocks, byteArray blockData, BiomeArray biomes);
|
||||
|
||||
private:
|
||||
public:
|
||||
LargeFeature *caveFeature;
|
||||
StrongholdFeature *strongholdFeature;
|
||||
VillageFeature *villageFeature;
|
||||
|
|
@ -97,4 +98,5 @@ public:
|
|||
virtual vector<Biome::MobSpawnerData *> *getMobsAt(MobCategory *mobCategory, int x, int y, int z);
|
||||
virtual TilePos *findNearestMapFeature(Level *level, const wstring& featureName, int x, int y, int z);
|
||||
virtual void recreateLogicStructuresForChunk(int chunkX, int chunkZ);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ StructureStart *StructureFeature::getStructureAt(int cellX, int cellY, int cellZ
|
|||
*/
|
||||
list<StructurePiece *> *pieces=pStructureStart->getPieces();
|
||||
|
||||
|
||||
|
||||
|
||||
for (auto& piece : *pieces)
|
||||
{
|
||||
if ( piece->getBoundingBox()->isInside(cellX, cellY, cellZ) )
|
||||
|
|
@ -154,7 +157,13 @@ bool StructureFeature::isInsideBoundingFeature(int cellX, int cellY, int cellZ)
|
|||
StructureStart *structureStart = it.second;
|
||||
if (structureStart->isValid())
|
||||
{
|
||||
return (structureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ));
|
||||
BoundingBox* bb = structureStart->getBoundingBox();
|
||||
if (cellX >= bb->x0 && cellX <= bb->x1 &&
|
||||
cellY >= bb->y0 && cellY <= bb->y1 &&
|
||||
cellZ >= bb->z0 && cellZ <= bb->z1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue