This code was not tested and breaks in Release builds, reverting to restore
functionality of the nightly. All in-game menus do not work and generating
a world crashes.
This reverts commit a9be52c41a.
223 lines
6.6 KiB
C++
223 lines
6.6 KiB
C++
#include "stdafx.h"
|
|
#include "net.minecraft.world.level.h"
|
|
#include "net.minecraft.world.level.tile.h"
|
|
#include "net.minecraft.world.level.levelgen.h"
|
|
#include "net.minecraft.world.level.dimension.h"
|
|
#include "net.minecraft.world.entity.projectile.h"
|
|
#include "net.minecraft.world.phys.h"
|
|
#include "EnderEyeItem.h"
|
|
#include "SoundTypes.h"
|
|
#include "LevelData.h"
|
|
|
|
EnderEyeItem::EnderEyeItem(int id) : Item(id)
|
|
{
|
|
}
|
|
|
|
bool EnderEyeItem::useOn(shared_ptr<ItemInstance> instance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly)
|
|
{
|
|
int targetType = level->getTile(x, y, z);
|
|
int targetData = level->getData(x, y, z);
|
|
|
|
if (player->mayUseItemAt(x, y, z, face, instance) && targetType == Tile::endPortalFrameTile_Id && !TheEndPortalFrameTile::hasEye(targetData))
|
|
{
|
|
if(bTestUseOnOnly) return true;
|
|
if (level->isClientSide) return true;
|
|
level->setData(x, y, z, targetData + TheEndPortalFrameTile::EYE_BIT, Tile::UPDATE_CLIENTS);
|
|
level->updateNeighbourForOutputSignal(x, y, z, Tile::endPortalFrameTile_Id);
|
|
instance->count--;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
double xp = x + (5.0f + random->nextFloat() * 6.0f) / 16.0f;
|
|
double yp = y + 13.0f / 16.0f;
|
|
double zp = z + (5.0f + random->nextFloat() * 6.0f) / 16.0f;
|
|
double xa = 0;
|
|
double ya = 0;
|
|
double za = 0;
|
|
|
|
level->addParticle(eParticleType_smoke, xp, yp, zp, xa, ya, za);
|
|
}
|
|
|
|
// scan if the circle is complete
|
|
int direction = targetData & 3;
|
|
|
|
// find borders
|
|
int min = 0;
|
|
int max = 0;
|
|
bool firstFound = false;
|
|
bool valid = true;
|
|
int rightHandDirection = Direction::DIRECTION_CLOCKWISE[direction];
|
|
for (int offset = -2; offset <= 2; offset++)
|
|
{
|
|
int testX = x + Direction::STEP_X[rightHandDirection] * offset;
|
|
int testZ = z + Direction::STEP_Z[rightHandDirection] * offset;
|
|
|
|
int tile = level->getTile(testX, y, testZ);
|
|
if (tile == Tile::endPortalFrameTile->id)
|
|
{
|
|
int data = level->getData(testX, y, testZ);
|
|
if (!TheEndPortalFrameTile::hasEye(data))
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
max = offset;
|
|
if (!firstFound)
|
|
{
|
|
min = offset;
|
|
firstFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// got a full frame?
|
|
if (valid && max == min + 2)
|
|
{
|
|
|
|
// check if other edge is valid
|
|
for (int offset = min; offset <= max; offset++)
|
|
{
|
|
int testX = x + Direction::STEP_X[rightHandDirection] * offset;
|
|
int testZ = z + Direction::STEP_Z[rightHandDirection] * offset;
|
|
testX += Direction::STEP_X[direction] * 4;
|
|
testZ += Direction::STEP_Z[direction] * 4;
|
|
|
|
int tile = level->getTile(testX, y, testZ);
|
|
int data = level->getData(testX, y, testZ);
|
|
if (tile != Tile::endPortalFrameTile_Id || !TheEndPortalFrameTile::hasEye(data))
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
// check if edges on the sides are valid
|
|
for (int side = (min - 1); side <= (max + 1); side += 4)
|
|
{
|
|
for (int offset = 1; offset <= 3; offset++)
|
|
{
|
|
int testX = x + Direction::STEP_X[rightHandDirection] * side;
|
|
int testZ = z + Direction::STEP_Z[rightHandDirection] * side;
|
|
testX += Direction::STEP_X[direction] * offset;
|
|
testZ += Direction::STEP_Z[direction] * offset;
|
|
|
|
int tile = level->getTile(testX, y, testZ);
|
|
int data = level->getData(testX, y, testZ);
|
|
if (tile != Tile::endPortalFrameTile_Id || !TheEndPortalFrameTile::hasEye(data))
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (valid)
|
|
{
|
|
|
|
// fill portal
|
|
for (int px = min; px <= max; px++)
|
|
{
|
|
for (int pz = 1; pz <= 3; pz++)
|
|
{
|
|
int targetX = x + Direction::STEP_X[rightHandDirection] * px;
|
|
int targetZ = z + Direction::STEP_Z[rightHandDirection] * px;
|
|
targetX += Direction::STEP_X[direction] * pz;
|
|
targetZ += Direction::STEP_Z[direction] * pz;
|
|
|
|
level->setTileAndData(targetX, y, targetZ, Tile::endPortalTile_Id, 0, Tile::UPDATE_CLIENTS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool EnderEyeItem::TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player)
|
|
{
|
|
HitResult *hr = getPlayerPOVHitResult(level, player, false);
|
|
if (hr != NULL && hr->type == HitResult::TILE)
|
|
{
|
|
int tile = level->getTile(hr->x, hr->y, hr->z);
|
|
delete hr;
|
|
if (tile == Tile::endPortalFrameTile_Id)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if( hr != NULL )
|
|
{
|
|
delete hr;
|
|
}
|
|
|
|
//if (!level->isClientSide)
|
|
{
|
|
if((level->dimension->id==LevelData::DIMENSION_OVERWORLD) && level->getLevelData()->getHasStronghold())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// int x,z;
|
|
// if(app.GetTerrainFeaturePosition(eTerrainFeature_Stronghold,&x,&z))
|
|
// {
|
|
// level->getLevelData()->setXStronghold(x);
|
|
// level->getLevelData()->setZStronghold(z);
|
|
// level->getLevelData()->setHasStronghold();
|
|
//
|
|
// app.DebugPrintf("=== FOUND stronghold in terrain features list\n");
|
|
//
|
|
// app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_StrongholdPosition);
|
|
// }
|
|
// else
|
|
{
|
|
// can't find the stronghold position in the terrain feature list. Do we have to run a post-process?
|
|
app.DebugPrintf("=== Can't find stronghold in terrain features list\n");
|
|
}
|
|
|
|
}
|
|
// TilePos *nearestMapFeature = level->findNearestMapFeature(LargeFeature::STRONGHOLD, (int) player->x, (int) player->y, (int) player->z);
|
|
// if (nearestMapFeature != NULL)
|
|
// {
|
|
// delete nearestMapFeature;
|
|
// return true;
|
|
// }
|
|
}
|
|
return false;
|
|
}
|
|
|
|
shared_ptr<ItemInstance> EnderEyeItem::use(shared_ptr<ItemInstance> instance, Level *level, shared_ptr<Player> player)
|
|
{
|
|
HitResult *hr = getPlayerPOVHitResult(level, player, false);
|
|
if (hr != NULL && hr->type == HitResult::TILE)
|
|
{
|
|
int tile = level->getTile(hr->x, hr->y, hr->z);
|
|
delete hr;
|
|
if (tile == Tile::endPortalFrameTile_Id)
|
|
{
|
|
return instance;
|
|
}
|
|
}
|
|
else if( hr != NULL )
|
|
{
|
|
delete hr;
|
|
}
|
|
|
|
if (!level->isClientSide)
|
|
{
|
|
if((level->dimension->id==LevelData::DIMENSION_OVERWORLD) && level->getLevelData()->getHasStronghold())
|
|
{
|
|
shared_ptr<EyeOfEnderSignal> eyeOfEnderSignal = shared_ptr<EyeOfEnderSignal>( new EyeOfEnderSignal(level, player->x, player->y + 1.62 - player->heightOffset, player->z) );
|
|
eyeOfEnderSignal->signalTo(level->getLevelData()->getXStronghold()<<4, player->y + 1.62 - player->heightOffset, level->getLevelData()->getZStronghold()<<4);
|
|
level->addEntity(eyeOfEnderSignal);
|
|
|
|
level->playEntitySound(player, eSoundType_RANDOM_BOW, 0.5f, 0.4f / (random->nextFloat() * 0.4f + 0.8f));
|
|
level->levelEvent(nullptr, LevelEvent::SOUND_LAUNCH, (int) player->x, (int) player->y, (int) player->z, 0);
|
|
if (!player->abilities.instabuild)
|
|
{
|
|
instance->count--;
|
|
}
|
|
}
|
|
}
|
|
return instance;
|
|
} |