Jump to content

[1.10.2] [SOLVED] Waila Support with Forge Energy Capabilities


Recommended Posts

Posted (edited)

Hi,

 

I'm currently having the problem that my solar panels show with Waila how many Forge Energy is stored in them, but they only update

the value when you right click on the solar panel and open the GUI.

 

@Optional.Interface(iface = "mcp.mobius.waila.api.IWailaDataProvider", modid = Constants.MODID_WAILA)
public class WailaCompat implements IWailaDataProvider {
    
    public static final WailaCompat INSTANCE = new WailaCompat();
    
    public static void load(IWailaRegistrar registrar) {
        registrar.registerBodyProvider(INSTANCE, TileEntityEnergy.class);
        registrar.registerNBTProvider(INSTANCE, TileEntityEnergy.class);
    }

    @Override
    @Nullable
    public ItemStack getWailaStack(IWailaDataAccessor accessor, IWailaConfigHandler config) {
        return null;
    }

    @Override
    @Nullable
    public List<String> getWailaHead(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
            IWailaConfigHandler config) {
        return currenttip;
    }

    @Override
    @Nullable
    public List<String> getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
            IWailaConfigHandler config) {
        
        TileEntity tile = accessor.getTileEntity();
        
        if(tile instanceof TileEntityEnergy) {
            TileEntityEnergy tileEnergy = (TileEntityEnergy) tile;
            
            if(tileEnergy.container != null) {
                if(currenttip.size() > 4)
                    currenttip.add("");
                
                int stored = tileEnergy.container.getEnergyStored();
                int max = tileEnergy.container.getMaxEnergyStored();
                
                currenttip.add(String.format("%s%s%s / %s%s%s %s", TextFormatting.WHITE, stored, TextFormatting.RESET,
                        TextFormatting.WHITE, max, TextFormatting.RESET, ModConfig.ENERGY_NAME));
            }
        }
        
        return currenttip;
    }

    @Override
    @Nullable
    public List<String> getWailaTail(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
            IWailaConfigHandler config) {
        return currenttip;
    }

    @Override
    @Nullable
    public NBTTagCompound getNBTData(EntityPlayerMP player, TileEntity te, NBTTagCompound tag, World world,
            BlockPos pos) {
        return tag;
    }
}

 

So, how can I fix this problem?

Just to note, the container of my TileEntityEnergy is the EnergyManager which stores all the energy and provides methods for extracting and receiving energy while also supporting other Energy systems like Tesla and handling the transition between them.

 

Thx in advance.

Bektor

Edited by Bektor

Developer of Primeval Forest.

Posted

If I were to guess I'd say it's a syncing issue. Are you by chance syncing up your server and client tileentity the moment you open the gui / right click the block? In any case I would like to see the block and tileentity classes (:

Posted
  On 6/2/2017 at 5:46 PM, tommyte said:

If I were to guess I'd say it's a syncing issue. Are you by chance syncing up your server and client tileentity the moment you open the gui / right click the block? In any case I would like to see the block and tileentity classes (:

Expand  
  Reveal hidden contents

Thats the basic tile entity class, the block class does actually nothing, except for creating the tile entity.

 

And here are the main methods of the TileEntityEnergy. There are some other methods, but they are not important as they are

mostly getters etc.

  Reveal hidden contents

 

Developer of Primeval Forest.

Posted

I can't find any networking here. I'd really like to see where you are syncing up your client side with your server side. 

 

  On 6/2/2017 at 6:04 PM, Bektor said:

if(!this.hasWorld() || this.getWorld().isRemote) return;

Expand  

 

You are, logically, only changing the amount of energy stored on server side, so the client side, what waila is displaying (I think), doesn't know of any changes in the amount of energy stored until you send a packet there ;)

Posted
  On 6/2/2017 at 6:10 PM, tommyte said:

I can't find any networking here. I'd really like to see where you are syncing up your client side with your server side. 

 

 

You are, logically, only changing the amount of energy stored on server side, so the client side, what waila is displaying (I think), doesn't know of any changes in the amount of energy stored until you send a packet there ;)

Expand  

The only other stuff there is is the Container for the GUI:

public class ContainerSolarPanel extends Container {
	
	private int energyStored;
	private int productionAmount;
	private TileEntitySolarPanel panel;
	
	public ContainerSolarPanel(InventoryPlayer playerInv, TileEntitySolarPanel panel) {
		this.panel = panel;
		
		for(int y = 0; y < 3; ++y)
			for(int x = 0; x < 9; ++x)
				this.addSlotToContainer(new Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
		
		for(int x = 0; x < 9; ++x)
			this.addSlotToContainer(new Slot(playerInv, x, 8 + x * 18, 142));
	}
	
	@Override
	public void detectAndSendChanges() {
		super.detectAndSendChanges();
		
		for(int i = 0; i < this.listeners.size(); i++) {
			IContainerListener listener = (IContainerListener) this.listeners.get(i);
			
			if(this.energyStored != this.panel.getField(0))
				listener.sendProgressBarUpdate(this, 0, this.panel.getField(0));
			if(this.productionAmount != this.panel.getField(1))
				listener.sendProgressBarUpdate(this, 1, this.panel.getField(1));
		}
		
		this.energyStored = this.panel.getField(0);
		this.productionAmount = this.panel.getField(1);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void updateProgressBar(int id, int data) {
		super.updateProgressBar(id, data);
		this.panel.setField(id, data);
	}
	
    @Override
    public boolean canInteractWith(EntityPlayer playerIn) {
        return this.panel.isUsableByPlayer(playerIn);
    }
}

 

Developer of Primeval Forest.

Posted

WAILA doesn't load the container, so the container's synchronization code doesn't work for displaying information to WAILA, ergo, you are not syncing the information except when the player opens the gui by right clicking the block. 

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
  On 6/2/2017 at 6:45 PM, Bektor said:

@Override public void detectAndSendChanges()

{

super.detectAndSendChanges();

for(int i = 0; i < this.listeners.size(); i++)

{

IContainerListener listener = (IContainerListener)

this.listeners.get(i);

if(this.energyStored != this.panel.getField(0)) listener.sendProgressBarUpdate(this, 0, this.panel.getField(0));

if(this.productionAmount != this.panel.getField(1)) listener.sendProgressBarUpdate(this, 1, this.panel.getField(1));

}

this.energyStored = this.panel.getField(0);

this.productionAmount = this.panel.getField(1);

}

Expand  

There you go :) This method, as the name implies detects and sends changes (on server side) and sends them to the client. This then only occurs when the container is activated, aka when the player open the gui. You should set up your own networking to sync properly between server and client. Here is an article about in on the docs: https://mcforge.readthedocs.io/en/latest/networking/

 

Read all the articles there about networking and then you should be good to go ;)

Posted (edited)

Ok, I just got now my network message done.

But how can I access in the message handler the tile entity to change the energy value on the client?

Just to note, my message only sends a basic integer value.

 

I'm also wondering to which players I should send the message for the best performance.

I also guess I should just send the update every time when I call markDirty() in the tile entity itself, am I right?

Edited by Bektor

Developer of Primeval Forest.

Posted

I usually do it like this: 

data.setIntArray("ints", new int[]{pos.getX(), pos.getY(), pos.getZ(), amount});

Here I set an array of integers with the three coords of the tile entity and the number i'd like to transfer. 

 

int[] values = message.data.getIntArray("ints");
final String name = message.data.getString("string");
final BlockPos pos = new BlockPos(values[0], values[1], values[2]);
final int amount = values[3];

Then in the messagehandler I read these values like this.

TileEntity entity = theplayer.getEntityWorld().getTileEntity(pos);
				
if(entity != null && entity.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null))
{
//here do something like entity.getCapability(etc., etc.).setEnergy(amount);
}

You'd put something like this into your run method.

Posted (edited)

Hm, how can I get the client world and the client player entitiy from my MessageContext#getClientHandler() as the message gets send to the client from the server.?

Edited by Bektor

Developer of Primeval Forest.

Posted
  On 6/2/2017 at 7:22 PM, Bektor said:

Hm, how can I get the client world and the client player entitiy from my MessageContext#getClientHandler() as the message gets send to the client from the server.?

Expand  

You can get the singleplayer player by calling Minecraft.getMinecraft().player. 

Posted

Seriously?

 

Minecraft.getMinecraft().player.getWorld() was too hard?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
  On 6/2/2017 at 7:27 PM, Bektor said:

And how do I get the world?

Expand  

player.getEntityWorld(); (or something like that)

 

  On 6/2/2017 at 7:27 PM, Bektor said:

Also, how can I send the new data only to all players currently looking at the block?

Expand  

you can use this:

PacketDispatcher.sendToAllAround(message, new NetworkRegistry.TargetPoint(dimension, x, y, z, range));

Just set the range to a value that would make sure no one outside it can hover over the block.

Posted

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • You are using Create 6 - some addons are not compatible with it Remove all addons and add these one by one littlecontraptions is mentioned - keep this one removed
    • Different problem now. https://paste.ee/p/iDo8lS35
    • I would like to have a BoP sapling drop from my block if it is also installed. I think I have done everything and I cannot pinpoint the problem, which is the error in the logs that appears when joining a world:   [Worker-Main-11/ERROR] [ne.mi.co.ForgeHooks/]: Couldn't parse element loot_tables:grasses:blocks/leaves_block com.google.gson.JsonSyntaxException: Expected name to be an item, was unknown string 'biomesoplenty:magic_sapling' My code:   LootItemConditions.CONDITIONS.register(modEventBus); public class LootItemConditions { public static final DeferredRegister<LootItemConditionType> CONDITIONS = DeferredRegister.create(Registries.LOOT_CONDITION_TYPE, Grasses.MOD_ID); public static final RegistryObject<LootItemConditionType> IS_MOD_LOADED = CONDITIONS.register("is_mod_loaded", () -> new LootItemConditionType(new IsModLoaded.ConditionSerializer())); } public class IsModLoaded implements LootItemCondition { private final boolean exists; private final String modID; public IsModLoaded(String modID) { this.exists = ModList.get().isLoaded(modID); this.modID = modID; } @Override public LootItemConditionType getType() { return LootItemConditions.IS_MOD_LOADED.get(); } @Override public boolean test(LootContext context) { return this.exists; } public static LootItemCondition.Builder builder(String modid) { return () -> new IsModLoaded(modid); } public static class ConditionSerializer implements Serializer<IsModLoaded> { @Override public void serialize(JsonObject json, IsModLoaded instance, JsonSerializationContext ctx) { json.addProperty("modid", instance.modID); } @Override public IsModLoaded deserialize(JsonObject json, JsonDeserializationContext ctx) { return new IsModLoaded(GsonHelper.getAsString(json, "modid")); } } } protected LootTable.Builder createLeavesDropsWithModIDCheck(Block selfBlock, Item sapling, Property<?>[] properties, String modIDToCheck, float... chances) { CopyBlockState.Builder blockStateCopyBuilder = CopyBlockState.copyState(selfBlock); for(Property<?> property : properties) { blockStateCopyBuilder.copy(property); } return LootTable.lootTable() .withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F)) .add(LootItem.lootTableItem(selfBlock) .when(HAS_SHEARS_OR_SILK_TOUCH) .apply(blockStateCopyBuilder))) .withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F)) .add(this.applyExplosionCondition(selfBlock, LootItem.lootTableItem(sapling)) .when(IsModLoaded.builder(modIDToCheck))) .when(BonusLevelTableCondition.bonusLevelFlatChance(Enchantments.BLOCK_FORTUNE, chances)) .when(HAS_NO_SHEARS_OR_SILK_TOUCH)) .withPool(LootPool.lootPool().name("sticks").setRolls(ConstantValue.exactly(1.0F)) .add(this.applyExplosionDecay(selfBlock, LootItem.lootTableItem(Items.STICK). apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 2.0F)))) .when(BonusLevelTableCondition.bonusLevelFlatChance(Enchantments.BLOCK_FORTUNE, NORMAL_LEAVES_STICK_CHANCES)) .when(HAS_NO_SHEARS_OR_SILK_TOUCH))); } I don't know. Am I making a mistake somewhere? Am I forgetting something? Should there be something else?
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.