Jump to content

Recommended Posts

Posted

Hi !

I overhauled the standard FoodStats system and increased the maximum hunger beyond 20. Unfortunately, the GUI still only shows the last 20 points. So I have to remake the Hunger bar so it changes the way hunger level are displayed.

But :

1. The original code looks very obfuscated, do you know any working example of something that sounds a bit like what I'm trying to do ?

2. I can disable the original with RenderGameOverlayEvent, but I don't see how to create the new GUI from here. There's no access to the player or the world.

3. I suspect my code to be functional for only one player. Here is the code replacing the FoodStats class : http://hastebin.com/awopohuzef.java

Am I right ?

 

Anybody ever played with those things ?

 

EDIT : I will use a PlayerTickEvent to show the GUI, but that doesn't answer all my questions.

Posted

You only need to draw a few rectangles, based on the number of food bars you want to display. I suggest you look at GuIngameForge, which is basically a cleaned up version of GuiIngame + the event firing code.

GUIs are client side only. The client only ever has one player and one world:

Minecraft#thePlayer

and

Minecraft#theWorld

.

No, that is not the correct event to "show the GUI". You need to use RenderGameOverlayEvent, as you already mentioned earlier.

 

Okay, I wasn't aware of GuiIngameForge. I should have looked where the event was fired.

I added an other question in my OP regarding the way I replace the food handling class (which I think I should take the multiplayer in account since there are individual food counters in there, but I'm not sure I do since I think the data get stored in only one place which sounds awefully wrong).

 

PS : I know I'm unleashing incompatibility and bad things by starting to use reflection but I had no choice, Forge just doesn't allow to safely modify much about Food and other real game mechanics.

Posted

I improved my code to look only once through fields to find the right one. I'm not sure how player related variables can be made yet : (hashmap maybe ? Or an event is triggered at the "character creation" ?) but I will find out as it's probably something people always ask.

Posted

That makes absolutely no sense.

How so?

Well, HardFoodStats extends FoodStats. Therefore my logic is

HardFoodStats instanceof FoodStats == true,,

FoodStats instanceof FoodStats == true,

HardFoodStats instanceof HardFoodStats == true but

FoodStats instanceof HardFoodStats == false.

 

So if the part of my code under !(getFoodStats instanceof HardFoodStats) is loaded each time (each logging, for the same player) that means each time I log in my player.getFoodStats is NOT the HardFoodStats instance I previously assigned.

Posted

But the instance can't be "renewed". Even in Vanilla. I mean, there is the foodLevel in there. When you renew it, it gets back to max (initial value).

Let's assume a new foodStats instance is automatically created at each EntityJoinWorld, and it seems to be the case, how does vanilla save its food level value ?

Posted

So I will search when and how these methods are called and mimic the vanilla system. Thanks.

 

EDIT : Called in the EntityPlayer class. I need a way to use NBTTagCompound, something like a getNBTfromEntity()... Very interesting.

Posted

That's already what I did. Initially I was using the vanilla "foodLevel" NBT tag so I thought it was the problem. Made a custom one, no changes. That's really strange. I will look if there is some kind of NBT viewer out there.

 

EDIT : I found one and after a few experiments it seems the writing works well but the reading doesn't work.

In my method

    public void readNBT(NBTTagCompound p_75112_1_)
    {
    	System.out.println("Started reading NBT tags...");
        if (p_75112_1_.hasKey("foodLevel"))
        {
        	System.out.println("NBT Tag found !");
            this.foodLevel = p_75112_1_.getInteger("foodLevel");
            this.foodTimer = p_75112_1_.getInteger("foodTickTimer");
            this.foodSaturationLevel = p_75112_1_.getFloat("foodSaturationLevel");
            this.foodExhaustionLevel = p_75112_1_.getFloat("foodExhaustionLevel");
        }
    }

"Started reading..." is printed but not "NBT Tag found !" so .hasKey("foodLevel") never worked. I don't get it because NBTExplorer clearly show the value exist in the save.

Posted

My actual problem is that during the EntityJoinWorld event, player.getEntityData() returns an empty NBTTagCompound.

Does this make sense ? How can I read from it then ?

The readNBT isn't called magically, and all the information on the web is about TileEntities..

Note I have to call readNBT somewhere myself, because at the time getFoodStats().readNBT(compound) is originally called in EntityPlayer, it still has the old class.

I did a workaround by getting values from the vanilla class. But I can't keep it, as not all values have public getters..

Posted

The compound tag returned by

Entity#getEntityData

is added by Forge and only used for custom entity data, it's never written to by Minecraft.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

Then I have two solutions :

Read from the Minecraft compound tag;

Read&Write on a Forge compound tag.

 

But I don't know how to access any of these compound tags if this method doesn't work.

 

EDIT : Fixed. I now write on the EntityPlayer.getEntityData() compound at logout with an event.

Posted

You should be able to call

FoodStats#writeNBT

on the vanilla object to get all of its values, then call

HardFoodStats#readNBT

to read those values into your own object before you replace the vanilla one. If

HardFoodStats

has values in addition to the vanilla ones, you may need to store them in the player's persisted NBT data or an

IExtendedEntityProperties

object.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

The saving now works perfectly, thank you. Back to the GUI displaying, my little method which should hide the original hunger bar and display mine just hide the original. Currently, my custom hunger bar is the vanilla one (I will tweak it once it works).

http://hastebin.com/umiwedupic.java

Maybe I should play with Pre and Post events ? I tried to cancel in Pre and display in Post but it was still the same problem.

 

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



×
×
  • Create New...

Important Information

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