mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-04 19:36:43 +03:00
181 lines
4.5 KiB
C++
181 lines
4.5 KiB
C++
/********************************************************************
|
|
Minecraft: Pocket Edition - Decompilation Project
|
|
Copyright (C) 2024 iProgramInCpp
|
|
|
|
The following code is licensed under the BSD 1 clause license.
|
|
SPDX-License-Identifier: BSD-1-Clause
|
|
********************************************************************/
|
|
#include "RedStoneRepeaterTile.hpp"
|
|
#include "world/level/Level.hpp"
|
|
|
|
RedStoneRepeaterTile::RedStoneRepeaterTile(int id, int texture, Material* pMtl) : Tile(id, texture, pMtl)
|
|
{
|
|
m_bActive = id == TILE_REPEATER_ON;
|
|
m_delay = 0;
|
|
|
|
setShape(0, 0, 0, 1, 0.125f, 1);
|
|
}
|
|
|
|
bool RedStoneRepeaterTile::isCubeShaped()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RedStoneRepeaterTile::isSolidRender()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RedStoneRepeaterTile::isSignalSource()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getTickDelay()
|
|
{
|
|
return 2; // 2 in game ticks per redstone tick
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getRenderShape()
|
|
{
|
|
return SHAPE_REPEATER;
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getTexture(int dir, int data)
|
|
{
|
|
switch (dir)
|
|
{
|
|
case DIR_YPOS:
|
|
return m_TextureFrame;
|
|
case DIR_YNEG:
|
|
return TEXTURE_STONE_SLAB_TOP;
|
|
}
|
|
return m_TextureFrame;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::onPlace(Level* level, int x, int y, int z)
|
|
{
|
|
if (isActive())
|
|
updateNeighbors(level, x, y, z, m_ID);
|
|
m_delay = level->getData(x, y, z) >> 2;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::onRemove(Level* level, int x, int y, int z)
|
|
{
|
|
if (isActive())
|
|
updateNeighbors(level, x, y, z, m_ID);
|
|
}
|
|
|
|
void RedStoneRepeaterTile::neighborChanged(Level* level, int x, int y, int z, int dir)
|
|
{
|
|
Tile::neighborChanged(level, x, y, z, dir);
|
|
level->addToTickNextTick(x, y, z, m_ID, getTickDelay() * (m_delay + 1));
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getResource(int data, Random* random)
|
|
{
|
|
return Tile::repeater_off->m_ID;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::tick(Level* level, int x, int y, int z, Random* random)
|
|
{
|
|
//if (level->m_bIsMultiplayer)
|
|
// return;
|
|
|
|
if (hasSignalFromBehind(level, x, y, z))
|
|
level->setTileAndData(x, y, z, Tile::repeater_on->m_ID, level->getData(x, y, z));
|
|
else
|
|
level->setTileAndData(x, y, z, Tile::repeater_off->m_ID, level->getData(x, y, z));
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getDirectSignal(LevelSource* level, int x, int y, int z, int dir)
|
|
{
|
|
return getSignal(level, x, y, z, dir);
|
|
}
|
|
|
|
int RedStoneRepeaterTile::getSignal(LevelSource* level, int x, int y, int z, int dir)
|
|
{
|
|
if (!isActive()) return 0;
|
|
int face = level->getData(x, y, z) & 3;
|
|
switch (dir)
|
|
{
|
|
case DIR_ZNEG:
|
|
return face == 1;
|
|
case DIR_ZPOS:
|
|
return face == 3;
|
|
case DIR_XNEG:
|
|
return face == 0;
|
|
case DIR_XPOS:
|
|
return face == 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::setPlacedBy(Level* level, int x, int y, int z, Mob* mob)
|
|
{
|
|
int data = level->getData(x, y, z);
|
|
|
|
data &= 0xC; // 0b1100
|
|
if (data == 0)
|
|
data |= m_delay << 2;
|
|
|
|
data |= mob->getDirection();
|
|
|
|
level->setData(x, y, z, data);
|
|
}
|
|
|
|
int RedStoneRepeaterTile::use(Level* level, int x, int y, int z, Player* player)
|
|
{
|
|
m_delay = (m_delay + 1) % 3;
|
|
level->setData(x, y, z, (level->getData(x, y, z) & 3) | (m_delay << 2));
|
|
return 1;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::updateNeighbors(Level* level, int x, int y, int z, int id)
|
|
{
|
|
level->updateNeighborsAt(x - 1, y, z, id);
|
|
level->updateNeighborsAt(x + 1, y, z, id);
|
|
level->updateNeighborsAt(x, y, z - 1, id);
|
|
level->updateNeighborsAt(x, y, z + 1, id);
|
|
}
|
|
|
|
bool RedStoneRepeaterTile::hasSignalFromBehind(Level* level, int x, int y, int z)
|
|
{
|
|
int data = level->getData(x, y, z) & 3;
|
|
if (data == 0 && level->getSignal(x - 1, y, z, DIR_XPOS)) return true;
|
|
if (data == 2 && level->getSignal(x + 1, y, z, DIR_XNEG)) return true;
|
|
if (data == 1 && level->getSignal(x, y, z - 1, DIR_ZPOS)) return true;
|
|
if (data == 3 && level->getSignal(x, y, z + 1, DIR_ZNEG)) return true;
|
|
return false;
|
|
}
|
|
|
|
void RedStoneRepeaterTile::animateTick(Level* level, int x, int y, int z, Random* random)
|
|
{
|
|
float partX = float(x) + 0.5f, partZ = float(z) + 0.5f, partY = float(y) + 0.7f;
|
|
|
|
// @NOTE: Need to use addParticle("reddust") 5 times. Invalid data values don't actually generate a smoke
|
|
switch (level->getData(x, y, z) & 3)
|
|
{
|
|
case 0:
|
|
partX -= 0.27f;
|
|
partY += 0.22f;
|
|
level->addParticle("reddust", partX, partY, partZ, 0.0f, 0.0f, 0.0f);
|
|
break;
|
|
case 1:
|
|
partX += 0.27f;
|
|
partY += 0.22f;
|
|
level->addParticle("reddust", partX, partY, partZ, 0.0f, 0.0f, 0.0f);
|
|
break;
|
|
case 2:
|
|
partZ -= 0.27f;
|
|
partY += 0.22f;
|
|
level->addParticle("reddust", partX, partY, partZ, 0.0f, 0.0f, 0.0f);
|
|
break;
|
|
case 3:
|
|
partZ += 0.27f;
|
|
partY += 0.22f;
|
|
level->addParticle("reddust", partX, partY, partZ, 0.0f, 0.0f, 0.0f);
|
|
break;
|
|
}
|
|
}
|