package com.sk89q.forge; import io.netty.buffer.ByteBufInputStream; import java.io.EOFException; import java.io.IOException; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; /** * An object that is managed so that its state can be easily saved to disk or * synchronized across a network barrier. * * <p> * When a <tt>Behavior</tt> generates network events on one side of the * connection (for example, the server), those events should end up on the other * side and received by the same behavior on the other side. This means that the * same behavior could be applied to an entity, a tile entity, an item, or any * other object, but the behavior itself would not need to be aware of the * object managing the behavior. * </p> * * <p> * For most of the events and calls, it is important to note that the same tag * is sent to every {@link Behavior} and it cannot be assumed that the given * data was meant specifically for this {@link Behavior}. Ideally, for NBT-based * events and method calls, tag key name collisions should be avoided by * choosing somewhat unique names for the NBT keys, but it is also important for * the managing object (the tile entity, entity, etc.) to not use conflicting * behaviors together, which is dependent on the programmer reading the * documentation/source appropriately. This shared approach to data is to reduce * the bandwidth overhead of tracking the owner of each set of data. * </p> * * <p> * Objects managing <tt>Behavior</tt>s should make sure to add itself as a * {@link BehaviorListener} by calling * {@link #addBehaviorListener(BehaviorListener)}. If multiple * <tt>Behaviors</tt> need to be managed, consider using a {@link BehaviorList}. * </p> */ public interface Behavior { /** * Write NBT data that needs to be saved to the world. * * <p> * This method can be used to write sensitive data that should not be made * available to the client. * </p> * * @see Behavior for an important discussion how the given data is shared * @param tag * the tag */ void writeSaveNBT(NBTTagCompound tag); /** * Read NBT data that has been retrieved from a saved world. * * <p> * This method does not need to validate data as if it had come from the * client, although some validation is required as world files could be * edited with a separate world editor, or corrupted via some means. * </p> * * @see Behavior for an important discussion how the given data is shared * @param tag * the tag */ void readSaveNBT(NBTTagCompound tag); /** * Write the NBT tag that is going to be sent to the other side and handled * by a call to {@link #readNetworkedNBT(NBTTagCompound)} on the other side. * This tag is only called to derive a "full snapshot" of all necessary data * to restore the {@link Behavior}'s state from an empty slate. * * @see Behavior for an important discussion how the given data is shared * @param tag * the tag */ void writeNetworkedNBT(NBTTagCompound tag); /** * Read the NBT tag that is going to be sent to the other side and handled * by a call to {@link #readNetworkedNBT(NBTTagCompound)} on the other side. * This tag is may called to derive a "full snapshot" of all necessary data * to restore the {@link Behavior}'s state from an empty slate, OR it may * only contain partial data as triggered by a call to * {@link BehaviorListener#networkedNbt(NBTTagCompound)}. * * @see Behavior for an important discussion how the given data is shared * @param tag * the tag */ void readNetworkedNBT(NBTTagCompound tag); /** * Read a payload that is received from a client. * * <p> * It is important to check the type of payload as multiple {@link Behavior} * s will all receive the same payload. Therefore, multiple {@link Behavior} * s cannot handle the same payload, or a {@link EOFException} will be * thrown. * </p> * * @param player * the player * @param payload * the payload * @param in * the input stream * @throws IOException * thrown on I/O error */ void readPayload(EntityPlayer player, BehaviorPayload payload, ByteBufInputStream in) throws IOException; /** * Add a listener. * * @param listener * the listener */ void addBehaviorListener(BehaviorListener listener); /** * Remove a listener. * * @param listener * the listener */ void removeBehaviorListener(BehaviorListener listener); }