TrapDoorTile placement freedom.

Commented attachedTo checks, made so mayPlace always return true, and implemented setPlacedBy for directional placing when the player placed the trapdoor on the floor or ceiling.
This commit is contained in:
disintegrate 2026-03-30 13:23:02 +08:00
parent ffcb465096
commit b1340925af
4 changed files with 1866 additions and 1566 deletions

View file

@ -1,112 +1,147 @@
#include "stdafx.h"
#include "net.minecraft.world.level.h"
#include "LadderTile.h"
#include "net.minecraft.world.level.h"
#include "stdafx.h"
LadderTile::LadderTile(int id) : Tile(id, Material::decoration,isSolidRender())
LadderTile::LadderTile(int id) : Tile(id, Material::decoration, isSolidRender())
{
}
AABB *LadderTile::getAABB(Level *level, int x, int y, int z)
{
updateShape(level, x, y, z);
return Tile::getAABB(level, x, y, z);
updateShape(level, x, y, z);
return Tile::getAABB(level, x, y, z);
}
AABB *LadderTile::getTileAABB(Level *level, int x, int y, int z)
{
updateShape(level, x, y, z);
return Tile::getTileAABB(level, x, y, z);
updateShape(level, x, y, z);
return Tile::getTileAABB(level, x, y, z);
}
void LadderTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr<TileEntity> forceEntity) // 4J added forceData, forceEntity param
{
setShape(level->getData(x, y, z));
setShape(level->getData(x, y, z));
}
void LadderTile::setShape(int data)
{
int dir = data;
float r = 3 / 16.0f;
int dir = data;
float r = 3 / 16.0f;
if (dir == 2) setShape(0, 0, 1 - r, 1, 1, 1);
if (dir == 3) setShape(0, 0, 0, 1, 1, r);
if (dir == 4) setShape(1 - r, 0, 0, 1, 1, 1);
if (dir == 5) setShape(0, 0, 0, r, 1, 1);
if (dir == 2)
{
setShape(0, 0, 1 - r, 1, 1, 1);
}
if (dir == 3)
{
setShape(0, 0, 0, 1, 1, r);
}
if (dir == 4)
{
setShape(1 - r, 0, 0, 1, 1, 1);
}
if (dir == 5)
{
setShape(0, 0, 0, r, 1, 1);
}
}
bool LadderTile::blocksLight()
{
return false;
return false;
}
bool LadderTile::isSolidRender(bool isServerLevel)
{
return false;
return false;
}
bool LadderTile::isCubeShaped()
{
return false;
return false;
}
int LadderTile::getRenderShape()
{
return Tile::SHAPE_LADDER;
return Tile::SHAPE_LADDER;
}
bool LadderTile::mayPlace(Level *level, int x, int y, int z)
{
if (level->isSolidBlockingTile(x - 1, y, z))
{
return true;
}
else if (level->isSolidBlockingTile(x + 1, y, z))
{
return true;
}
else if (level->isSolidBlockingTile(x, y, z - 1))
{
return true;
}
else if (level->isSolidBlockingTile(x, y, z + 1))
{
return true;
}
return false;
if (level->isSolidBlockingTile(x - 1, y, z))
{
return true;
}
else if (level->isSolidBlockingTile(x + 1, y, z))
{
return true;
}
else if (level->isSolidBlockingTile(x, y, z - 1))
{
return true;
}
else if (level->isSolidBlockingTile(x, y, z + 1))
{
return true;
}
return false;
}
int LadderTile::getPlacedOnFaceDataValue(Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue)
{
int dir = level->getData(x, y, z);
int dir = level->getData(x, y, z);
if ((dir == 0 || face == 2) && level->isSolidBlockingTile(x, y, z + 1)) dir = 2;
if ((dir == 0 || face == 3) && level->isSolidBlockingTile(x, y, z - 1)) dir = 3;
if ((dir == 0 || face == 4) && level->isSolidBlockingTile(x + 1, y, z)) dir = 4;
if ((dir == 0 || face == 5) && level->isSolidBlockingTile(x - 1, y, z)) dir = 5;
if ((dir == 0 || face == 2) && level->isSolidBlockingTile(x, y, z + 1))
{
dir = 2;
}
if ((dir == 0 || face == 3) && level->isSolidBlockingTile(x, y, z - 1))
{
dir = 3;
}
if ((dir == 0 || face == 4) && level->isSolidBlockingTile(x + 1, y, z))
{
dir = 4;
}
if ((dir == 0 || face == 5) && level->isSolidBlockingTile(x - 1, y, z))
{
dir = 5;
}
return dir;
return dir;
}
void LadderTile::neighborChanged(Level *level, int x, int y, int z, int type)
{
int face = level->getData(x, y, z);
bool ok = false;
int face = level->getData(x, y, z);
bool ok = false;
if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) ok = true;
if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) ok = true;
if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) ok = true;
if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) ok = true;
if (!ok)
{
spawnResources(level, x, y, z, face, 0);
level->removeTile(x, y, z);
}
if (face == 2 && level->isSolidBlockingTile(x, y, z + 1))
{
ok = true;
}
if (face == 3 && level->isSolidBlockingTile(x, y, z - 1))
{
ok = true;
}
if (face == 4 && level->isSolidBlockingTile(x + 1, y, z))
{
ok = true;
}
if (face == 5 && level->isSolidBlockingTile(x - 1, y, z))
{
ok = true;
}
if (!ok)
{
spawnResources(level, x, y, z, face, 0);
level->removeTile(x, y, z);
}
Tile::neighborChanged(level, x, y, z, type);
Tile::neighborChanged(level, x, y, z, type);
}
int LadderTile::getResourceCount(Random* random)
int LadderTile::getResourceCount(Random *random)
{
return 1;
}
return 1;
}

File diff suppressed because it is too large Load diff

View file

@ -1,215 +1,299 @@
#include "stdafx.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.level.tile.h"
#include "net.minecraft.h"
#include "TrapDoorTile.h"
#include "net.minecraft.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.tile.h"
#include "stdafx.h"
TrapDoorTile::TrapDoorTile(int id, Material *material) : Tile(id, material,isSolidRender())
TrapDoorTile::TrapDoorTile(int id, Material *material) : Tile(id, material, isSolidRender())
{
float r = 0.5f;
float h = 1.0f;
setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r);
float r = 0.5f;
float h = 1.0f;
setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r);
}
bool TrapDoorTile::blocksLight()
{
return false;
return false;
}
bool TrapDoorTile::isSolidRender(bool isServerLevel)
{
return false;
return false;
}
bool TrapDoorTile::isCubeShaped()
{
return false;
return false;
}
bool TrapDoorTile::isPathfindable(LevelSource *level, int x, int y, int z)
{
return !isOpen(level->getData(x, y, z));
return !isOpen(level->getData(x, y, z));
}
int TrapDoorTile::getRenderShape()
{
return Tile::SHAPE_BLOCK;
return Tile::SHAPE_BLOCK;
}
AABB *TrapDoorTile::getTileAABB(Level *level, int x, int y, int z)
{
updateShape(level, x, y, z);
return Tile::getTileAABB(level, x, y, z);
updateShape(level, x, y, z);
return Tile::getTileAABB(level, x, y, z);
}
AABB *TrapDoorTile::getAABB(Level *level, int x, int y, int z)
{
updateShape(level, x, y, z);
return Tile::getAABB(level, x, y, z);
updateShape(level, x, y, z);
return Tile::getAABB(level, x, y, z);
}
void TrapDoorTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr<TileEntity> forceEntity) // 4J added forceData, forceEntity param
{
setShape(level->getData(x, y, z));
setShape(level->getData(x, y, z));
}
void TrapDoorTile::updateDefaultShape()
{
float r = 3 / 16.0f;
setShape(0, 0.5f - r / 2, 0, 1, 0.5f + r / 2, 1);
float r = 3 / 16.0f;
setShape(0, 0.5f - r / 2, 0, 1, 0.5f + r / 2, 1);
}
void TrapDoorTile::setShape(int data)
{
float r = 3 / 16.0f;
if ((data & TOP_MASK) != 0)
{
setShape(0, 1 - r, 0, 1, 1, 1);
}
else
{
setShape(0, 0, 0, 1, r, 1);
}
if (isOpen(data))
{
if ((data & 3) == 0) setShape(0, 0, 1 - r, 1, 1, 1);
if ((data & 3) == 1) setShape(0, 0, 0, 1, 1, r);
if ((data & 3) == 2) setShape(1 - r, 0, 0, 1, 1, 1);
if ((data & 3) == 3) setShape(0, 0, 0, r, 1, 1);
}
float r = 3 / 16.0f;
if ((data & TOP_MASK) != 0)
{
setShape(0, 1 - r, 0, 1, 1, 1);
}
else
{
setShape(0, 0, 0, 1, r, 1);
}
if (isOpen(data))
{
if ((data & 3) == 0)
{
setShape(0, 0, 1 - r, 1, 1, 1);
}
if ((data & 3) == 1)
{
setShape(0, 0, 0, 1, 1, r);
}
if ((data & 3) == 2)
{
setShape(1 - r, 0, 0, 1, 1, 1);
}
if ((data & 3) == 3)
{
setShape(0, 0, 0, r, 1, 1);
}
}
}
void TrapDoorTile::attack(Level *level, int x, int y, int z, shared_ptr<Player> player)
{
//use(level, x, y, z, player, 0, 0, 0, 0);
// use(level, x, y, z, player, 0, 0, 0, 0);
}
// 4J-PB - Adding a TestUse for tooltip display
bool TrapDoorTile::TestUse()
{
return true;
return true;
}
bool TrapDoorTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly/*=false*/) // 4J added soundOnly param
bool TrapDoorTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly /*=false*/) // 4J added soundOnly param
{
if (material == Material::metal) return true;
if (material == Material::metal)
{
return true;
}
if (soundOnly)
{
// 4J - added - just do enough to play the sound
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return false;
}
if (soundOnly)
{
// 4J - added - just do enough to play the sound
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return false;
}
int dir = level->getData(x, y, z);
level->setData(x, y, z, dir ^ 4, Tile::UPDATE_CLIENTS);
int dir = level->getData(x, y, z);
level->setData(x, y, z, dir ^ 4, Tile::UPDATE_CLIENTS);
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return true;
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return true;
}
void TrapDoorTile::setOpen(Level *level, int x, int y, int z, bool shouldOpen)
{
int dir = level->getData(x, y, z);
int dir = level->getData(x, y, z);
bool wasOpen = (dir & 4) > 0;
if (wasOpen == shouldOpen) return;
bool wasOpen = (dir & 4) > 0;
if (wasOpen == shouldOpen)
{
return;
}
level->setData(x, y, z, dir ^ 4, Tile::UPDATE_CLIENTS);
level->setData(x, y, z, dir ^ 4, Tile::UPDATE_CLIENTS);
level->levelEvent(nullptr, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
level->levelEvent(nullptr, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
}
void TrapDoorTile::neighborChanged(Level *level, int x, int y, int z, int type)
{
if (level->isClientSide) return;
if (level->isClientSide)
{
return;
}
int data = level->getData(x, y, z);
int xt = x;
int zt = z;
if ((data & 3) == 0) zt++;
if ((data & 3) == 1) zt--;
if ((data & 3) == 2) xt++;
if ((data & 3) == 3) xt--;
int data = level->getData(x, y, z);
int xt = x;
int zt = z;
if ((data & 3) == 0)
{
zt++;
}
if ((data & 3) == 1)
{
zt--;
}
if ((data & 3) == 2)
{
xt++;
}
if ((data & 3) == 3)
{
xt--;
}
// if (!attachesTo(level->getTile(xt, y, zt)))
// {
// level->removeTile(x, y, z);
// spawnResources(level, x, y, z, data, 0);
// }
if (!attachesTo(level->getTile(xt, y, zt)))
{
level->removeTile(x, y, z);
spawnResources(level, x, y, z, data, 0);
}
bool signal = level->hasNeighborSignal(x, y, z);
if( signal || ((type > 0 && Tile::tiles[type]->isSignalSource())) )
{
setOpen(level, x, y, z, signal);
}
bool signal = level->hasNeighborSignal(x, y, z);
if (signal || ((type > 0 && Tile::tiles[type]->isSignalSource())))
{
setOpen(level, x, y, z, signal);
}
}
HitResult *TrapDoorTile::clip(Level *level, int xt, int yt, int zt, Vec3 *a, Vec3 *b)
{
updateShape(level, xt, yt, zt);
return Tile::clip(level, xt, yt, zt, a, b);
updateShape(level, xt, yt, zt);
return Tile::clip(level, xt, yt, zt, a, b);
}
int TrapDoorTile::getDir(int dir)
{
if ((dir & 4) == 0)
{
return ((dir - 1) & 3);
}
else
{
return (dir & 3);
}
if ((dir & 4) == 0)
{
return ((dir - 1) & 3);
}
else
{
return (dir & 3);
}
}
int TrapDoorTile::getPlacedOnFaceDataValue(Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue)
{
int dir = 0;
if (face == 2) dir = 0;
if (face == 3) dir = 1;
if (face == 4) dir = 2;
if (face == 5) dir = 3;
if (face != Facing::UP && face != Facing::DOWN && clickY > 0.5f) dir |= TOP_MASK;
return dir;
int dir = 0;
if (face == Facing::NORTH)
{
dir = 0;
}
if (face == Facing::SOUTH)
{
dir = 1;
}
if (face == Facing::WEST)
{
dir = 2;
}
if (face == Facing::EAST)
{
dir = 3;
}
if (face == Facing::DOWN)
{
dir |= TOP_MASK;
}
else if (face == Facing::UP)
{
dir |= 0;
}
else
{
dir |= (clickY > 0.5f ? TOP_MASK : 0);
}
return dir;
}
void TrapDoorTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance)
{
int data = level->getData(x, y, z);
int dir = data & 7;
int flip = data & TOP_MASK;
// We only need to apply player yaw rotation when the trapdoor is placed
// on floor or ceiling (i.e. when it would have been face UP or DOWN).
// Because its allowed placement without support, we detect this case when the initial
// direction is still the default (0) and it's not a clear wall placement.
if (dir == 0)
{
int i = Mth::floor((by->yRot * 4.0f / 360.0f) + 0.5f) & 0x3;
if (i == 0)
{
dir = 0;
}
if (i == 1)
{
dir = 3;
}
if (i == 2)
{
dir = 1;
}
if (i == 3)
{
dir = 2;
}
level->setData(x, y, z, dir | flip, Tile::UPDATE_CLIENTS);
}
}
bool TrapDoorTile::mayPlace(Level *level, int x, int y, int z, int face)
{
if (face == 0) return false;
if (face == 1) return false;
if (face == 2) z++;
if (face == 3) z--;
if (face == 4) x++;
if (face == 5) x--;
return attachesTo(level->getTile(x, y, z));
// if (face == 0) return false;
// if (face == 1) return false;
// if (face == 2) z++;
// if (face == 3) z--;
// if (face == 4) x++;
// if (face == 5) x--;
//
// return attachesTo(level->getTile(x, y, z));
return true;
}
bool TrapDoorTile::isOpen(int data)
{
return (data & 4) != 0;
return (data & 4) != 0;
}
bool TrapDoorTile::attachesTo(int id)
{
if (id <= 0)
{
return false;
}
Tile *tile = Tile::tiles[id];
if (id <= 0)
{
return false;
}
Tile *tile = Tile::tiles[id];
return tile != nullptr && (tile->material->isSolidBlocking() && tile->isCubeShaped()) || tile == Tile::glowstone || (dynamic_cast<HalfSlabTile *>(tile) != nullptr) || (dynamic_cast<StairTile *>(tile) != nullptr);
}
return tile != nullptr && (tile->material->isSolidBlocking() && tile->isCubeShaped()) || tile == Tile::glowstone || (dynamic_cast<HalfSlabTile *>(tile) != nullptr) || (dynamic_cast<StairTile *>(tile) != nullptr);
}

View file

@ -7,81 +7,81 @@ class HitResult;
class TrapDoorTile : public Tile
{
friend class Tile;
private:
static const int TOP_MASK = 0x8;
friend class Tile;
protected:
TrapDoorTile(int id, Material *material);
private:
static const int TOP_MASK = 0x8;
/*
* public int getTexture(int face, int data) { if (face == 0 || face == 1)
* return tex; int dir = getDir(data); if ((dir == 0 || dir == 2) ^ (face <= 3))
* { return tex; } int tt = (dir / 2 + ((face & 1) ^ dir)); tt += ((data & 4) /
* 4); int texture = tex - (data & 8) * 2; if ((tt & 1) != 0) { texture =
* -texture; } // if (getDir(data)==0 // tt-=((face+data&3)&1)^((data&4)>>2);
* return texture; }
*/
protected:
TrapDoorTile(int id, Material *material);
public:
bool blocksLight();
/*
* public int getTexture(int face, int data) { if (face == 0 || face == 1)
* return tex; int dir = getDir(data); if ((dir == 0 || dir == 2) ^ (face <= 3))
* { return tex; } int tt = (dir / 2 + ((face & 1) ^ dir)); tt += ((data & 4) /
* 4); int texture = tex - (data & 8) * 2; if ((tt & 1) != 0) { texture =
* -texture; } // if (getDir(data)==0 // tt-=((face+data&3)&1)^((data&4)>>2);
* return texture; }
*/
public:
bool isSolidRender(bool isServerLevel = false);
public:
bool blocksLight();
public:
bool isCubeShaped();
bool isPathfindable(LevelSource *level, int x, int y, int z);
public:
bool isSolidRender(bool isServerLevel = false);
public:
int getRenderShape();
public:
bool isCubeShaped();
bool isPathfindable(LevelSource *level, int x, int y, int z);
public:
AABB *getTileAABB(Level *level, int x, int y, int z);
public:
int getRenderShape();
public:
AABB *getAABB(Level *level, int x, int y, int z);
public:
AABB *getTileAABB(Level *level, int x, int y, int z);
public:
void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
public:
AABB *getAABB(Level *level, int x, int y, int z);
public:
void updateDefaultShape();
public:
void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
public:
using Tile::setShape;
void setShape(int data);
public:
void updateDefaultShape();
public:
void attack(Level *level, int x, int y, int z, shared_ptr<Player> player);
public:
using Tile::setShape;
void setShape(int data);
public:
virtual bool TestUse();
bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false); // 4J added soundOnly param
public:
void attack(Level *level, int x, int y, int z, shared_ptr<Player> player);
public:
void setOpen(Level *level, int x, int y, int z, bool shouldOpen);
public:
virtual bool TestUse();
bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false); // 4J added soundOnly param
public:
void setOpen(Level *level, int x, int y, int z, bool shouldOpen);
public:
void neighborChanged(Level *level, int x, int y, int z, int type);
public:
void neighborChanged(Level *level, int x, int y, int z, int type);
public:
HitResult *clip(Level *level, int xt, int yt, int zt, Vec3 *a, Vec3 *b);
public:
HitResult *clip(Level *level, int xt, int yt, int zt, Vec3 *a, Vec3 *b);
public:
int getDir(int dir);
public:
int getDir(int dir);
public:
int getPlacedOnFaceDataValue(Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue);
virtual void setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance);
public:
int getPlacedOnFaceDataValue(Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue);
public:
bool mayPlace(Level *level, int x, int y, int z, int face);
public:
bool mayPlace(Level *level, int x, int y, int z, int face);
public:
static bool isOpen(int data);
public:
static bool isOpen(int data);
private:
static bool attachesTo(int id);
};
private:
static bool attachesTo(int id);
};