- 1,159
- 38
- 544
Доброго времени суток и с наступающим, дорогие форумчане! Я хочу встретить новый год с чистой совестью, а потому желаю отрефакторить определение поворота в своем кастомном блоке.
Сейчас я сохраняю мету в NBT и синхронизирую это дело через
Ужас! Дед мороз точно мне ничего не подарит, если я оставлю это все как есть.
Я решил сделать определение лицевой стороны в своем блоке точно таким же способом, как и в ванильном коде. Всем известно, что за направление блока отвечает его метадата. Но вот ее вычисление в некоторых местах сбивает меня с толку. Давайте для начала взглянем на код печки (в ванильный код я добавил некоторые пояснения):
Все довольно просто, но почему печка подставляет вместо меты не вычисленное значение, а иные константы: 2 (север), 3 (юг), 4 (восток), 5 (запад)? Может константы 1 и 2 используются печкой для обозначения чего-то еще? В таком случае у меня не получается найти где используются значения 1 и 2. Такая же ситуация кстати и с наковальней, поршнем, сундуком и другими блоками. Однако
Короче, вот что меня интересует:
Сейчас я сохраняю мету в NBT и синхронизирую это дело через
TileEntity#getDescriptionPacket()
UpgradeStationEntity.java:
public class UpgradeStationEntity extends TileEntity {
...
// TODO: Сохранять направление в NBT - нерационально. Нужно юзать метадату - http://www.minecraftforge.net/forum/topic/25239-solved1710-saving-block-direction-state/
@Override
public void writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
upgradeStationInventory.writeToNBT(compound); // TODO: Синхронизировать инвентарь на уровне тайла - это просто дно. Не тайл синхронизирут инвентарь, а открытый игроком контейнер!
compound.setInteger("dir", this.blockMetadata);
}
@Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
upgradeStationInventory.readFromNBT(compound);
this.blockMetadata = compound.getInteger("dir");
}
// TODO: Отказаться от хранения поворота в NBT. Это следует делать в метадате блока как в печке!
// Синхронизирует переменные блока с блоком на клиенте
@Override
public Packet getDescriptionPacket() {
NBTTagCompound tag = new NBTTagCompound();
writeToNBT(tag);
return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, tag);
}
// Нужно для метода выше
@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
readFromNBT(pkt.func_148857_g());
}
// http://cazzar.net/tutorials/minecraft/Tile-Entity-Updates-The-Quick-and-Dirty-Method/
public void markForUpdate() {
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
}
}
Ужас! Дед мороз точно мне ничего не подарит, если я оставлю это все как есть.
Я решил сделать определение лицевой стороны в своем блоке точно таким же способом, как и в ванильном коде. Всем известно, что за направление блока отвечает его метадата. Но вот ее вычисление в некоторых местах сбивает меня с толку. Давайте для начала взглянем на код печки (в ванильный код я добавил некоторые пояснения):
BlockFurnace.java:
public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
{
// Стандартное вычисление направления, в которое должна смотреть морда блока
// Результатом вычислений будет int, описывающий одну из сторон света
int l = MathHelper.floor_double((double)(p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
if (l == 0) // Север (отрицателный z)
{
p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 2, 2);
}
if (l == 1) // Восток (положительный x)
{
p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 5, 2);
}
if (l == 2) // Юг (положительный z)
{
p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 3, 2);
}
if (l == 3) // Запад (отрицательный x)
{
p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 4, 2);
}
...
}
Все довольно просто, но почему печка подставляет вместо меты не вычисленное значение, а иные константы: 2 (север), 3 (юг), 4 (восток), 5 (запад)? Может константы 1 и 2 используются печкой для обозначения чего-то еще? В таком случае у меня не получается найти где используются значения 1 и 2. Такая же ситуация кстати и с наковальней, поршнем, сундуком и другими блоками. Однако
BlockCocoa
сразу юзает результат вычисления направления:
BlockCocoa.java:
public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
{
int l = ((MathHelper.floor_double((double)(p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 0) % 4;
// WTF?
p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, l, 2);
}
Короче, вот что меня интересует:
- Чзх творится с метадатой?
- Как метадата синхронизируется с клиентом?
- Должен ли я заботиться о сохранении меты в NBT?