|
| 1 | +/* |
| 2 | + * Minecraft Forge, Patchwork Project |
| 3 | + * Copyright (c) 2016-2020, 2019-2020 |
| 4 | + * |
| 5 | + * This library is free software; you can redistribute it and/or |
| 6 | + * modify it under the terms of the GNU Lesser General Public |
| 7 | + * License as published by the Free Software Foundation version 2.1 |
| 8 | + * of the License. |
| 9 | + * |
| 10 | + * This library is distributed in the hope that it will be useful, |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + * Lesser General Public License for more details. |
| 14 | + * |
| 15 | + * You should have received a copy of the GNU Lesser General Public |
| 16 | + * License along with this library; if not, write to the Free Software |
| 17 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | + */ |
| 19 | + |
| 20 | +package net.minecraftforge.common.extensions; |
| 21 | + |
| 22 | +import net.minecraftforge.common.capabilities.ICapabilitySerializable; |
| 23 | + |
| 24 | +import net.minecraft.block.AbstractSignBlock; |
| 25 | +import net.minecraft.block.Block; |
| 26 | +import net.minecraft.block.BlockState; |
| 27 | +import net.minecraft.block.Blocks; |
| 28 | +import net.minecraft.block.ChestBlock; |
| 29 | +import net.minecraft.block.EnderChestBlock; |
| 30 | +import net.minecraft.block.SkullBlock; |
| 31 | +import net.minecraft.nbt.CompoundTag; |
| 32 | +import net.minecraft.network.ClientConnection; |
| 33 | +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; |
| 34 | +import net.minecraft.block.entity.BlockEntity; |
| 35 | +import net.minecraft.util.math.Box; |
| 36 | +import net.minecraft.util.math.BlockPos; |
| 37 | +import net.minecraft.world.World; |
| 38 | + |
| 39 | +import net.fabricmc.api.EnvType; |
| 40 | +import net.fabricmc.api.Environment; |
| 41 | + |
| 42 | +public interface IForgeTileEntity extends ICapabilitySerializable<CompoundTag> { |
| 43 | + /** |
| 44 | + * Sometimes default render bounding box: infinite in scope. Used to control rendering on {@link TileEntitySpecialRenderer}. |
| 45 | + */ |
| 46 | + Box INFINITE_EXTENT_AABB = new Box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); |
| 47 | + |
| 48 | + default BlockEntity getTileEntity() { |
| 49 | + return (BlockEntity) this; |
| 50 | + } |
| 51 | + |
| 52 | + @Override |
| 53 | + default void deserializeNBT(CompoundTag nbt) { |
| 54 | + getTileEntity().fromTag(nbt); |
| 55 | + } |
| 56 | + |
| 57 | + @Override |
| 58 | + default CompoundTag serializeNBT() { |
| 59 | + CompoundTag ret = new CompoundTag(); |
| 60 | + getTileEntity().toTag(ret); |
| 61 | + return ret; |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Called when you receive a TileEntityData packet for the location this |
| 66 | + * TileEntity is currently in. On the client, the NetworkManager will always |
| 67 | + * be the remote server. On the server, it will be whomever is responsible for |
| 68 | + * sending the packet. |
| 69 | + * |
| 70 | + * @param net The NetworkManager the packet originated from |
| 71 | + * @param pkt The data packet |
| 72 | + */ |
| 73 | + default void onDataPacket(ClientConnection net, BlockEntityUpdateS2CPacket pkt) { |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * Called when the chunk's TE update tag, gotten from {@link #getUpdateTag()}, is received on the client. |
| 78 | + * |
| 79 | + * <p>Used to handle this tag in a special way. By default this simply calls {@link #readFromNBT(NBTTagCompound)}. |
| 80 | + * |
| 81 | + * @param tag The {@link NBTTagCompound} sent from {@link #getUpdateTag()} |
| 82 | + */ |
| 83 | + default void handleUpdateTag(CompoundTag tag) { |
| 84 | + getTileEntity().fromTag(tag); |
| 85 | + } |
| 86 | + |
| 87 | + /** |
| 88 | + * Gets a {@link NBTTagCompound} that can be used to store custom data for this tile entity. |
| 89 | + * It will be written, and read from disc, so it persists over world saves. |
| 90 | + * |
| 91 | + * @return A compound tag for custom data |
| 92 | + */ |
| 93 | + CompoundTag getTileData(); |
| 94 | + |
| 95 | + default void onChunkUnloaded() { |
| 96 | + } |
| 97 | + |
| 98 | + /** |
| 99 | + * Called when this is first added to the world (by {@link World#addTileEntity(TileEntity)}). |
| 100 | + * Override instead of adding {@code if (firstTick)} stuff in update. |
| 101 | + */ |
| 102 | + default void onLoad() { |
| 103 | + requestModelDataUpdate(); |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * Return an {@link AxisAlignedBB} that controls the visible scope of a {@link TileEntitySpecialRenderer} associated with this {@link TileEntity} |
| 108 | + * Defaults to the collision bounding box {@link Block#getCollisionBoundingBoxFromPool(World, int, int, int)} associated with the block |
| 109 | + * at this location. |
| 110 | + * |
| 111 | + * @return an appropriately size {@link AxisAlignedBB} for the {@link TileEntity} |
| 112 | + */ |
| 113 | + @Environment(EnvType.CLIENT) |
| 114 | + default Box getRenderBoundingBox() { |
| 115 | + Box bb = INFINITE_EXTENT_AABB; |
| 116 | + BlockState state = getTileEntity().getCachedState(); |
| 117 | + Block block = state.getBlock(); |
| 118 | + BlockPos pos = getTileEntity().getPos(); |
| 119 | + |
| 120 | + if (block == Blocks.ENCHANTING_TABLE) { |
| 121 | + bb = new Box(pos, pos.add(1, 1, 1)); |
| 122 | + } else if (block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { |
| 123 | + bb = new Box(pos.add(-1, 0, -1), pos.add(2, 2, 2)); |
| 124 | + } else if (block == Blocks.STRUCTURE_BLOCK) { |
| 125 | + bb = INFINITE_EXTENT_AABB; |
| 126 | + } else if (block != null && block != Blocks.BEACON) { |
| 127 | + Box cbb = null; |
| 128 | + |
| 129 | + try { |
| 130 | + cbb = state.getCollisionShape(getTileEntity().getWorld(), pos).getBoundingBox().offset(pos); |
| 131 | + } catch (Exception e) { |
| 132 | + // We have to capture any exceptions that may occur here because BUKKIT servers like to send |
| 133 | + // the tile entity data BEFORE the chunk data, you know, the OPPOSITE of what vanilla does! |
| 134 | + // So we can not GUARANTEE that the world state is the real state for the block... |
| 135 | + // So, once again in the long line of US having to accommodate BUKKIT breaking things, |
| 136 | + // here it is, assume that the TE is only 1 cubic block. Problem with this is that it may |
| 137 | + // cause the TileEntity renderer to error further down the line! But alas, nothing we can do. |
| 138 | + cbb = new Box(pos.add(-1, 0, -1), pos.add(1, 1, 1)); |
| 139 | + } |
| 140 | + |
| 141 | + if (cbb != null) { |
| 142 | + bb = cbb; |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + return bb; |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * Checks if this tile entity knows how to render its 'breaking' overlay effect. |
| 151 | + * If this returns true, The TileEntitySpecialRenderer will be called again with break progress set. |
| 152 | + * |
| 153 | + * @return True to re-render tile with breaking effect. |
| 154 | + */ |
| 155 | + default boolean canRenderBreaking() { |
| 156 | + Block block = getTileEntity().getCachedState().getBlock(); |
| 157 | + return (block instanceof ChestBlock |
| 158 | + || block instanceof EnderChestBlock |
| 159 | + || block instanceof AbstractSignBlock |
| 160 | + || block instanceof SkullBlock); |
| 161 | + } |
| 162 | + |
| 163 | + /** |
| 164 | + * TODO: Deprecated, in Patchwork API 1.14.4, vanilla 1.15 and above, |
| 165 | + * this is never called. See {@link net.minecraftforge.client.model.animation.TileEntityRendererFast}. |
| 166 | + * |
| 167 | + * <p>If the TileEntitySpecialRenderer associated with this TileEntity can be batched in with another renderers, and won't access the GL state. |
| 168 | + * If TileEntity returns true, then TESR should have the same functionality as (and probably extend) the FastTESR class. |
| 169 | + */ |
| 170 | + @Deprecated |
| 171 | + default boolean hasFastRenderer() { |
| 172 | + return false; |
| 173 | + } |
| 174 | + |
| 175 | + /** |
| 176 | + * Requests a refresh for the model data of your TE |
| 177 | + * Call this every time your {@link #getModelData()} changes. |
| 178 | + */ |
| 179 | + default void requestModelDataUpdate() { |
| 180 | + BlockEntity te = getTileEntity(); |
| 181 | + World world = te.getWorld(); |
| 182 | + |
| 183 | + if (world != null && world.isClient) { |
| 184 | + // ModelDataManager.requestModelDataRefresh(te); |
| 185 | + } |
| 186 | + } |
| 187 | + |
| 188 | + /** |
| 189 | + * Allows you to return additional model data. |
| 190 | + * This data can be used to provide additional functionality in your {@link net.minecraft.client.renderer.model.IBakedModel} |
| 191 | + * You need to schedule a refresh of you model data via {@link #requestModelDataUpdate()} if the result of this function changes. |
| 192 | + * <b>Note that this method may be called on a chunk render thread instead of the main client thread</b> |
| 193 | + * |
| 194 | + * @return Your model data |
| 195 | + */ |
| 196 | + //@Nonnull |
| 197 | + //default IModelData getModelData() { |
| 198 | + // return EmptyModelData.INSTANCE; |
| 199 | + //} |
| 200 | +} |
0 commit comments