mirror of
https://github.com/celisej567/mcpe.git
synced 2025-12-31 17:49:17 +03:00
246 lines
5.6 KiB
C++
246 lines
5.6 KiB
C++
/********************************************************************
|
|
Minecraft: Pocket Edition - Decompilation Project
|
|
Copyright (C) 2023 iProgramInCpp
|
|
|
|
The following code is licensed under the BSD 1 clause license.
|
|
SPDX-License-Identifier: BSD-1-Clause
|
|
********************************************************************/
|
|
|
|
#include "DoorTile.hpp"
|
|
#include "world/level/Level.hpp"
|
|
#include "world/item/Item.hpp"
|
|
|
|
DoorTile::DoorTile(int ID, Material* pMtl) : Tile(ID, pMtl)
|
|
{
|
|
m_TextureFrame = TEXTURE_DOOR_BOTTOM;
|
|
|
|
if (pMtl == Material::metal)
|
|
m_TextureFrame = TEXTURE_DOOR_IRON_BOTTOM;
|
|
|
|
Tile::setShape(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
|
|
int DoorTile::use(Level* level, int x, int y, int z, Player* player)
|
|
{
|
|
// well, you know, iron doors can't be opened by right clicking
|
|
if (m_pMaterial == Material::metal)
|
|
return 1;
|
|
|
|
int data = level->getData(x, y, z);
|
|
|
|
// if we're the top tile
|
|
if (data & 8)
|
|
{
|
|
if (level->getTile(x, y - 1, z) == m_ID)
|
|
use(level, x, y - 1, z, player);
|
|
}
|
|
else
|
|
{
|
|
data ^= 4;
|
|
if (level->getTile(x, y + 1, z) == m_ID)
|
|
level->setData(x, y + 1, z, data + 8);
|
|
|
|
level->setData(x, y, z, data);
|
|
|
|
// @BUG: marking the wrong tiles as dirty? No problem because setData sends an update immediately anyways
|
|
level->setTilesDirty(x, y - 1, z, x, y, z);
|
|
|
|
std::string snd;
|
|
if (Mth::random() < 0.5f)
|
|
snd = "random.door_open";
|
|
else
|
|
snd = "random.door_close";
|
|
|
|
level->playSound(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f, snd, 1.0f, 0.9f + 0.1f * level->m_random.nextFloat());
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void DoorTile::attack(Level* level, int x, int y, int z, Player* player)
|
|
{
|
|
use(level, x, y, z, player);
|
|
}
|
|
|
|
// @HUH: This function has NO references to itself. Not even in the vtable of the tile.
|
|
// This could have been an attempt by Mojang to override a function, but it clearly failed
|
|
// From this, I suspect that they never actually used the `override` keyword for their classes.
|
|
bool DoorTile::blocksLight()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
HitResult DoorTile::clip(Level* level, int x, int y, int z, Vec3 v1, Vec3 v2)
|
|
{
|
|
// @NOTE: Tile::clip calls updateShape too. So this is redundant
|
|
updateShape(level, x, y, z);
|
|
return Tile::clip(level, x, y, z, v1, v2);
|
|
}
|
|
|
|
AABB* DoorTile::getAABB(Level* level, int x, int y, int z)
|
|
{
|
|
updateShape(level, x, y, z);
|
|
return Tile::getAABB(level, x, y, z);
|
|
}
|
|
|
|
int DoorTile::getDir(int data)
|
|
{
|
|
if (!isOpen(data))
|
|
return (data - 1) & 3;
|
|
|
|
return data & 3;
|
|
}
|
|
|
|
int DoorTile::getRenderShape()
|
|
{
|
|
return SHAPE_DOOR;
|
|
}
|
|
|
|
int DoorTile::getResource(int data, Random* random)
|
|
{
|
|
// breaking the top of the tile doesn't drop anything.
|
|
// In JE, it probably fixed a certain dupe glitch with doors
|
|
if (isTop(data))
|
|
return 0;
|
|
|
|
if (m_pMaterial == Material::metal)
|
|
return Item::door_iron->m_itemID;
|
|
|
|
return Item::door_wood->m_itemID;
|
|
}
|
|
|
|
int DoorTile::getTexture(int dir, int data)
|
|
{
|
|
if (dir == 0 || dir == 1)
|
|
return m_TextureFrame;
|
|
|
|
int doorDir = getDir(data);
|
|
|
|
if ((doorDir == 0 || doorDir == 2) != (dir <= 3))
|
|
return m_TextureFrame;
|
|
|
|
int l = doorDir / 2 + ((dir & 1) ^ doorDir);
|
|
l += (data & 4) / 4;
|
|
|
|
int idx = m_TextureFrame - (data & 8) * 2;
|
|
if ((l & 1) != 0)
|
|
idx = -idx;
|
|
|
|
return idx;
|
|
}
|
|
|
|
AABB DoorTile::getTileAABB(Level* level, int x, int y, int z)
|
|
{
|
|
updateShape(level, x, y, z);
|
|
return Tile::getTileAABB(level, x, y, z);
|
|
}
|
|
|
|
bool DoorTile::isCubeShaped()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool DoorTile::isSolidRender()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool DoorTile::mayPlace(Level* level, int x, int y, int z)
|
|
{
|
|
return y <= 126 && level->isSolidTile(x, y - 1, z) && Tile::mayPlace(level, x, y, z) && Tile::mayPlace(level, x, y + 1, z);
|
|
}
|
|
|
|
void DoorTile::setShape(int dir)
|
|
{
|
|
// @NOTE: What? Why 2 tiles tall??
|
|
Tile::setShape(0.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f);
|
|
switch (dir)
|
|
{
|
|
case 0:
|
|
Tile::setShape(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.1875f);
|
|
break;
|
|
case 1:
|
|
Tile::setShape(0.8125f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
|
|
break;
|
|
case 2:
|
|
Tile::setShape(0.0f, 0.0f, 0.8125f, 1.0f, 1.0f, 1.0f);
|
|
break;
|
|
case 3:
|
|
Tile::setShape(0.0f, 0.0f, 0.0f, 0.1875f, 1.0f, 1.0f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DoorTile::updateShape(LevelSource* level, int x, int y, int z)
|
|
{
|
|
setShape(getDir(level->getData(x, y, z)));
|
|
}
|
|
|
|
void DoorTile::setOpen(Level* level, int x, int y, int z, bool bOpen)
|
|
{
|
|
int data = level->getData(x, y, z);
|
|
if (isTop(data))
|
|
{
|
|
if (level->getTile(x, y - 1, z) == m_ID)
|
|
setOpen(level, x, y - 1, z, bOpen);
|
|
return;
|
|
}
|
|
|
|
if (isOpen(level->getData(x, y, z)) != bOpen)
|
|
{
|
|
if (level->getTile(x, y + 1, z) == m_ID)
|
|
level->setData(x, y + 1, z, (data ^ 4) + 8);
|
|
|
|
level->setData(x, y, z, data ^ 4);
|
|
level->setTilesDirty(x, y - 1, z, x, y, z);
|
|
|
|
std::string snd;
|
|
if (Mth::random() < 0.5f)
|
|
snd = "random.door_open";
|
|
else
|
|
snd = "random.door_close";
|
|
|
|
level->playSound(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f, snd, 1.0f, 0.9f + 0.1f * level->m_random.nextFloat());
|
|
}
|
|
}
|
|
|
|
void DoorTile::neighborChanged(Level* level, int x, int y, int z, int newTile)
|
|
{
|
|
int isTop = level->getData(x, y, z) & 8;
|
|
if (isTop)
|
|
{
|
|
if (level->getTile(x, y - 1, z) != m_ID)
|
|
level->setTile(x, y, z, TILE_AIR);
|
|
|
|
if (newTile > 0)
|
|
{
|
|
if (Tile::tiles[newTile]->isSignalSource())
|
|
neighborChanged(level, x, y - 1, z, newTile);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (level->getTile(x, y + 1, z) != m_ID)
|
|
{
|
|
level->setTile(x, y, z, TILE_AIR);
|
|
isTop = 1;
|
|
}
|
|
|
|
if (!level->isSolidTile(x, y - 1, z))
|
|
{
|
|
level->setTile(x, y, z, TILE_AIR);
|
|
if (level->getTile(x, y + 1, z) == m_ID)
|
|
level->setTile(x, y + 1, z, TILE_AIR);
|
|
}
|
|
|
|
if (!isTop && newTile > 0 && Tile::tiles[newTile]->isSignalSource())
|
|
{
|
|
bool bOpen = false;
|
|
if (level->hasNeighborSignal(x, y, z) || level->hasNeighborSignal(x, y + 1, z))
|
|
bOpen = true;
|
|
|
|
setOpen(level, x, y, z, bOpen);
|
|
}
|
|
}
|