Fix syncing of everything
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package electroblob.wizardry;
|
||||
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import electroblob.wizardry.inventory.ContainerArcaneWorkbench;
|
||||
import electroblob.wizardry.item.ItemSpectralBow;
|
||||
import electroblob.wizardry.packet.*;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
@@ -261,4 +263,17 @@ public class CommonProxy {
|
||||
public Set<String> getSpellHUDSkins(){
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Notifies nearby players of a bookshelf change, causing any lectern or arcane workbench GUI (client-side) or
|
||||
* container (both sides) to refresh its linked bookshelves (does not send packets). */
|
||||
public void notifyBookshelfChange(World world, BlockPos pos){
|
||||
for(EntityPlayer player : world.playerEntities){
|
||||
if(player.getDistanceSq(pos) < BlockBookshelf.PLAYER_NOTIFY_RANGE * BlockBookshelf.PLAYER_NOTIFY_RANGE){
|
||||
if(player.openContainer instanceof ContainerArcaneWorkbench){
|
||||
((ContainerArcaneWorkbench)player.openContainer).refreshBookshelfSlots();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
@@ -19,19 +20,30 @@ import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.IWorldEventListener;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class BlockBookshelf extends BlockHorizontal implements ITileEntityProvider {
|
||||
|
||||
/** When a bookshelf block (of any kind specified in the config) is added or removed, players within this range will
|
||||
* be notified of the change. */
|
||||
public static final double PLAYER_NOTIFY_RANGE = 32;
|
||||
public static final int SLOT_COUNT = 12;
|
||||
|
||||
public static final UnlistedPropertyBool[] BOOKS = new UnlistedPropertyBool[SLOT_COUNT];
|
||||
@@ -65,6 +77,11 @@ public class BlockBookshelf extends BlockHorizontal implements ITileEntityProvid
|
||||
return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state){
|
||||
super.onBlockAdded(worldIn, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void breakBlock(World world, BlockPos pos, IBlockState block){
|
||||
|
||||
@@ -172,4 +189,49 @@ public class BlockBookshelf extends BlockHorizontal implements ITileEntityProvid
|
||||
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onWorldLoadEvent(WorldEvent.Load event){
|
||||
event.getWorld().addEventListener(Listener.instance);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onWorldUnloadEvent(WorldEvent.Unload event){
|
||||
event.getWorld().removeEventListener(Listener.instance);
|
||||
}
|
||||
|
||||
public static class Listener implements IWorldEventListener {
|
||||
|
||||
public static final Listener instance = new Listener();
|
||||
|
||||
private Listener(){}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(World world, BlockPos pos, IBlockState oldState, IBlockState newState, int flags){
|
||||
|
||||
if(oldState == newState) return; // Probably won't happen but just in case
|
||||
|
||||
if(Settings.containsMetaBlock(Wizardry.settings.bookshelfBlocks, oldState) // Bookshelf removed
|
||||
|| Settings.containsMetaBlock(Wizardry.settings.bookshelfBlocks, newState)){ // Bookshelf placed
|
||||
// It is also possible (with commands) for a bookshelf to be replaced with another bookshelf, in which
|
||||
// case this should still just be called once
|
||||
Wizardry.proxy.notifyBookshelfChange(world, pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Dummy implementations
|
||||
@Override public void notifyLightSet(BlockPos pos){}
|
||||
@Override public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2){}
|
||||
@Override public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, double x, double y, double z, float volume, float pitch){}
|
||||
@Override public void playRecord(SoundEvent soundIn, BlockPos pos){}
|
||||
@Override public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters){}
|
||||
@Override public void spawnParticle(int id, boolean ignoreRange, boolean minimiseParticleLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int... parameters){}
|
||||
@Override public void onEntityAdded(Entity entityIn){}
|
||||
@Override public void onEntityRemoved(Entity entityIn){}
|
||||
@Override public void broadcastSound(int soundID, BlockPos pos, int data){}
|
||||
@Override public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data){}
|
||||
@Override public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress){}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.CommonProxy;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import electroblob.wizardry.client.audio.MovingSoundEntity;
|
||||
import electroblob.wizardry.client.audio.SoundLoop;
|
||||
import electroblob.wizardry.client.audio.SoundLoopSpell;
|
||||
import electroblob.wizardry.client.gui.GuiLectern;
|
||||
import electroblob.wizardry.client.gui.GuiSpellDisplay;
|
||||
import electroblob.wizardry.client.gui.config.NamedBooleanEntry;
|
||||
import electroblob.wizardry.client.gui.config.SpellHUDSkinChooserEntry;
|
||||
@@ -202,6 +204,20 @@ public class ClientProxy extends CommonProxy {
|
||||
return GuiSpellDisplay.getSkinKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBookshelfChange(World world, BlockPos pos){
|
||||
|
||||
super.notifyBookshelfChange(world, pos);
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(player.getDistanceSq(pos) < BlockBookshelf.PLAYER_NOTIFY_RANGE * BlockBookshelf.PLAYER_NOTIFY_RANGE){
|
||||
if(Minecraft.getMinecraft().currentScreen instanceof GuiLectern){
|
||||
((GuiLectern)Minecraft.getMinecraft().currentScreen).refreshAvailableSpells();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SECTION Items
|
||||
// ===============================================================================================================
|
||||
|
||||
|
||||
@@ -127,8 +127,6 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable {
|
||||
|
||||
super.initGui();
|
||||
|
||||
updateAvailableSpells();
|
||||
|
||||
final int left = this.width / 2 - this.xSize / 2;
|
||||
final int top = this.height / 2 - this.ySize / 2;
|
||||
|
||||
@@ -181,8 +179,7 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable {
|
||||
this.searchField.setCanLoseFocus(false);
|
||||
this.searchField.setFocused(true);
|
||||
|
||||
updateMatchingSpells();
|
||||
updateButtonVisiblity();
|
||||
refreshAvailableSpells(); // Must be done last
|
||||
|
||||
}
|
||||
|
||||
@@ -383,9 +380,9 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// TODO: Call this when a bookshelf is added or removed
|
||||
// TODO: Config option to always display all spells when in creative
|
||||
private void updateAvailableSpells(){
|
||||
/** Called on initialisation and whenever a bookshelf is added or removed, to update the list of spells. */
|
||||
public void refreshAvailableSpells(){
|
||||
|
||||
availableSpells.clear();
|
||||
|
||||
@@ -405,6 +402,9 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable {
|
||||
|
||||
if(!availableSpells.contains(currentSpell)) currentSpell = Spells.none; // TODO: Do we want this?
|
||||
|
||||
updateMatchingSpells();
|
||||
updateButtonVisiblity();
|
||||
|
||||
}
|
||||
|
||||
private class GuiButtonLocateBook extends GuiButton {
|
||||
|
||||
@@ -36,7 +36,9 @@ public class BakedModelBookshelf implements IBakedModel {
|
||||
IExtendedBlockState extendedState = (IExtendedBlockState)state;
|
||||
|
||||
for(int i = 0; i<BlockBookshelf.SLOT_COUNT; i++){
|
||||
if(extendedState.getValue(BlockBookshelf.BOOKS[i])) quads.addAll(books[i].getQuads(state, side, rand));
|
||||
Boolean value = extendedState.getValue(BlockBookshelf.BOOKS[i]);
|
||||
if(value == null) return fallback.getQuads(null, side, rand);
|
||||
if(value) quads.addAll(books[i].getQuads(state, side, rand));
|
||||
}
|
||||
|
||||
return quads;
|
||||
|
||||
@@ -212,11 +212,6 @@ public class ContainerArcaneWorkbench extends Container implements ISpellSortabl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: It only seems to be syncing correctly when a stack is put into the slot, not taken out.
|
||||
// This is because markDirty isn't called in the tileentity, I think.
|
||||
// You can simulate this using hoppers!
|
||||
this.tileentity.sync();
|
||||
}
|
||||
|
||||
// FIXME: Shift-clicking a stack of special upgrades when in the arcane workbench causes the whole stack to be
|
||||
@@ -516,9 +511,8 @@ public class ContainerArcaneWorkbench extends Container implements ISpellSortabl
|
||||
// N.B. If we drop the requirement of it working with any container it could potentially be a lot easier since
|
||||
// we then always have control over the bookshelf classes
|
||||
|
||||
// TODO: Call this when a bookshelf is added or removed
|
||||
/** Called on initialisation, and whenever a bookshelf is added or removed. */
|
||||
private void refreshBookshelfSlots(){
|
||||
/** Called on initialisation and whenever a bookshelf is added or removed, to update the virtual slot list. */
|
||||
public void refreshBookshelfSlots(){
|
||||
|
||||
this.inventorySlots.removeAll(bookshelfSlots);
|
||||
bookshelfSlots.clear();
|
||||
|
||||
@@ -48,7 +48,7 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory,
|
||||
|
||||
/** Called to manually sync the tile entity with clients. */
|
||||
public void sync(){
|
||||
this.world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
this.world.markAndNotifyBlock(pos, null, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,8 +113,11 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory,
|
||||
|
||||
@Override
|
||||
public void setInventorySlotContents(int slot, ItemStack stack){
|
||||
|
||||
inventory.set(slot, stack);
|
||||
|
||||
ItemStack previous = inventory.set(slot, stack);
|
||||
|
||||
// Only the central slot affects the in-world rendering, so only sync if that changes
|
||||
if(slot == ContainerArcaneWorkbench.CENTRE_SLOT && previous.isEmpty() != stack.isEmpty()) this.sync();
|
||||
|
||||
if(!stack.isEmpty() && stack.getCount() > getInventoryStackLimit()){
|
||||
stack.setCount(getInventoryStackLimit());
|
||||
@@ -199,12 +202,10 @@ public class TileEntityArcaneWorkbench extends TileEntity implements IInventory,
|
||||
NBTTagList itemList = new NBTTagList();
|
||||
for(int i = 0; i < getSizeInventory(); i++){
|
||||
ItemStack stack = getStackInSlot(i);
|
||||
if(!stack.isEmpty()){
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setByte("Slot", (byte)i);
|
||||
stack.writeToNBT(tag);
|
||||
itemList.appendTag(tag);
|
||||
}
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setByte("Slot", (byte)i);
|
||||
stack.writeToNBT(tag);
|
||||
itemList.appendTag(tag);
|
||||
}
|
||||
|
||||
NBTExtras.storeTagSafely(tagCompound, "Inventory", itemList);
|
||||
|
||||
@@ -30,7 +30,7 @@ public class TileEntityBookshelf extends TileEntity implements IInventory, ITick
|
||||
|
||||
/** Called to manually sync the tile entity with clients. */
|
||||
public void sync(){
|
||||
this.world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
this.world.markAndNotifyBlock(pos, null, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,16 +82,15 @@ public class TileEntityBookshelf extends TileEntity implements IInventory, ITick
|
||||
|
||||
@Override
|
||||
public void setInventorySlotContents(int slot, ItemStack stack){
|
||||
|
||||
inventory.set(slot, stack);
|
||||
|
||||
//ItemStack previous = inventory.set(slot, stack);
|
||||
ItemStack previous = inventory.set(slot, stack);
|
||||
|
||||
//if(previous.isEmpty() != stack.isEmpty()) this.sync();
|
||||
if(previous.isEmpty() != stack.isEmpty()) this.sync();
|
||||
|
||||
if(!stack.isEmpty() && stack.getCount() > getInventoryStackLimit()){
|
||||
stack.setCount(getInventoryStackLimit());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,12 +156,10 @@ public class TileEntityBookshelf extends TileEntity implements IInventory, ITick
|
||||
NBTTagList itemList = new NBTTagList();
|
||||
for(int i = 0; i < getSizeInventory(); i++){
|
||||
ItemStack stack = getStackInSlot(i);
|
||||
if(!stack.isEmpty()){
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setByte("Slot", (byte)i);
|
||||
stack.writeToNBT(tag);
|
||||
itemList.appendTag(tag);
|
||||
}
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setByte("Slot", (byte)i);
|
||||
stack.writeToNBT(tag);
|
||||
itemList.appendTag(tag);
|
||||
}
|
||||
|
||||
NBTExtras.storeTagSafely(tagCompound, "Inventory", itemList);
|
||||
@@ -182,6 +179,7 @@ public class TileEntityBookshelf extends TileEntity implements IInventory, ITick
|
||||
@Override
|
||||
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt){
|
||||
readFromNBT(pkt.getNbtCompound());
|
||||
Wizardry.proxy.notifyBookshelfChange(world, pos);
|
||||
}
|
||||
|
||||
// What are all these for?
|
||||
|
||||
@@ -64,7 +64,7 @@ public class TileEntityLectern extends TileEntity implements ITickable {
|
||||
|
||||
/** Called to manually sync the tile entity with clients. */
|
||||
public void sync(){
|
||||
this.world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
this.world.markAndNotifyBlock(pos, null, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user