Jump to content

Recommended Posts

Posted

Hi,

 

Im learning modding at the moment and im at a point where i try to create a solar panel creating the new "forge energy" ;)

Overall everything works like it should, but i have a few questions and problems which i want to ask :=)

But first the code i use at the moment:

 

 

First the TileEntityEnergyBase class. This is my base class for all my TileEntities using Energy.

It extends TileEntity and implements IEnergyStorage.

It also exposes the Energy Capability and writes and reads the energy value to/from NBT.

public class TileEntityEnergyBase extends TileEntity implements IEnergyStorage
{
protected int energy;
    protected int capacity;
    protected int maxReceive;
    protected int maxExtract;
    
    public TileEntityEnergyBase()
    {
    	
    }
    
    public TileEntityEnergyBase(int capacity)
    {
        this(capacity, capacity, capacity);
    }

    public TileEntityEnergyBase(int capacity, int maxTransfer)
    {
        this(capacity, maxTransfer, maxTransfer);
    }

    public TileEntityEnergyBase(int capacity, int maxReceive, int maxExtract)
    {
        this.capacity = capacity;
        this.maxReceive = maxReceive;
        this.maxExtract = maxExtract;
    }
    
    
//------Start IEnergyStorage-----//
@Override
public int receiveEnergy(int maxReceive, boolean simulate) 
{
	if (!canReceive())
            return 0;

        int energyReceived = Math.min(capacity - energy, Math.min(this.maxReceive, maxReceive));
        if (!simulate)
            energy += energyReceived;
        return energyReceived;
}

@Override
public int extractEnergy(int maxExtract, boolean simulate) 
{
	if (!canExtract())
            return 0;

        int energyExtracted = Math.min(energy, Math.min(this.maxExtract, maxExtract));
        if (!simulate)
            energy -= energyExtracted;
        return energyExtracted;
}

@Override
public int getEnergyStored() 
{
	return energy;
}

@Override
public int getMaxEnergyStored() 
{
	return capacity;
}

@Override
    public boolean canExtract()
    {
        return this.maxExtract > 0;
    }

    @Override
    public boolean canReceive()
    {
        return this.maxReceive > 0;
    }	
//------End IEnergyStorage-----//

    //Energy Capability Stuff
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
	if(capability == CapabilityEnergy.ENERGY)
	{
		return true;
	}
	return super.hasCapability(capability, facing);
}

@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing) 
{
	if(capability == CapabilityEnergy.ENERGY)
	{
		return (T) this;
	}
	return super.getCapability(capability, facing);
}

//Read and Write Energy from/to NBT (on world load/world unload --> persistent data)
@Override
public void readFromNBT(NBTTagCompound compound) 
{
	super.readFromNBT(compound);
	if(compound.hasKey("energy"))
        {
        	this.energy = compound.getInteger("energy");
        }
}

@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound) 
{
	super.writeToNBT(compound);
        compound.setInteger("energy", energy);
        return compound;
}  	
}

 

Next up is my TileEntitySolarPanel class. (Block Class/ Jsons/ and so on all working):

It extends my TileEntityEnergyBase class above and implements ITickable for update()

Note, the update() Method just gives it 2 Energy per Tick when the capacity is not reached and tries to give energy to TEs on the bottom 10 e/t.

public class TileEntitySolarPanel extends TileEntityEnergyBase implements ITickable
{  
public TileEntitySolarPanel()
{

}

    public TileEntitySolarPanel(int capacity, int maxReceive, int maxExtract)
    {
    	super(capacity, maxReceive, maxExtract);
    }

//------Start ITickable-----//
@Override
public void update() 
{
	System.out.println(energy);
	if(energy < capacity)
	{
		energy += 2;
	}
	if(!(energy < 10))
	{
		TileEntity tile = worldObj.getTileEntity(getPos().down());
		if(tile != null && tile.hasCapability(CapabilityEnergy.ENERGY, EnumFacing.UP))
		{
			tile.getCapability(CapabilityEnergy.ENERGY, EnumFacing.UP).receiveEnergy(10, false);
			energy -= 10;
		}
	}
}
//------End ITickable-----//
}

 

The TileEntitySolarPanel gets created by the BlockSolarPanel with the following parameters:

//----START ITileEntityProvider---//
@Override
public TileEntity createNewTileEntity(World worldIn, int meta) 
{
		return new TileEntitySolarPanel(1000, 0, 10); 
}
//----END ITileEntityProvider---//

 

 

 

So on to my questions:

 

1. My TileEntities get created with parameters for capacity and transfer, but it seems like i always need 1 constructor without parameters so the TE can be restored on world load, is this correct?

If so, do i have to store the capacity and transfer ints also in NBT and not only the current energy?

 

2. Syncing. Everything works fine when i sysout the energy. When i close and reload the world it seems like there are 2 TEs for the Block, 1 with the old energy value and 1 new one startig from 0 again. syout looks like this:

(164 old value)

164
0
2
4
6
8
10
12
14
16
164
164
164
18
20
164
22
24
164
164
26
164
28
164
30
164
32
164

 

I think i need to sync something between client and server here?

 

 

3. How to check if it is day?

My solar panel should produce 2 e/t while its daytime, but the method worldObj.isDaytime() returns:

false
true
false
true
false
true

while it is night. How should i check for day time?

 

Thats it for now, thanks in advance :)

Posted

The whole point of the capability system is that you don't implement interfaces on your

TileEntity

/

Entity

/

Item

. Instead, you store one or more instances of the interface (

IEnergyStorage

) and override the

ICapabilityProvider

methods to return them.

 

EnergyStorage

is the default implementation of

IEnergyStorage

, use or extend this unless you need a completely different implementation.

 

You only need to sync data to the client if it's required for rendering. All game logic is controlled by the server.

 

World#isDaytime

will only return a valid result on the server because the

World#skylightSubtracted

field that it uses is only updated from

WorldServer

.

 

Whenever you print something to the log, it should tell you whether it was done from the client or server thread.

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

Whenever you print something to the log, it should tell you whether it was done from the client or server thread.

 

Unless you print out a pure number. 

System.out.println(someInt)

will print "4" while

System.out.println(someInt + " energy")

will print "[time] [client] [package and class name:line#]: 4 energy"

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

The whole point of the capability system is that you don't implement interfaces on your

TileEntity

/

Entity

/

Item

. Instead, you store one or more instances of the interface (

IEnergyStorage

) and override the

ICapabilityProvider

methods to return them.

 

EnergyStorage

is the default implementation of

IEnergyStorage

, use or extend this unless you need a completely different implementation.

 

ah, i completely missed this while thinking about it.

So i just create a new EnergyStorage object(i want to use teh default implementation) save it in the TileEntity and return this field at getCapability right?

 

 

You only need to sync data to the client if it's required for rendering. All game logic is controlled by the server.

 

I need to figure out why the TE has 2 different values for energy after world loading then...

 

 

World#isDaytime

will only return a valid result on the server because the

World#skylightSubtracted

field that it uses is only updated from

WorldServer

.

 

Whenever you print something to the log, it should tell you whether it was done from the client or server thread.

 

That makes sense, thanks!

Posted

The whole point of the capability system is that you don't implement interfaces on your

TileEntity

/

Entity

/

Item

. Instead, you store one or more instances of the interface (

IEnergyStorage

) and override the

ICapabilityProvider

methods to return them.

 

EnergyStorage

is the default implementation of

IEnergyStorage

, use or extend this unless you need a completely different implementation.

 

ah, i completely missed this while thinking about it.

So i just create a new EnergyStorage object(i want to use teh default implementation) save it in the TileEntity and return this field at getCapability right?

 

Yes.

 

 

You only need to sync data to the client if it's required for rendering. All game logic is controlled by the server.

 

I need to figure out why the TE has 2 different values for energy after world loading then...

 

Is one on the client and one on the server? Only the server reads the

TileEntity

from NBT.

 

 

Whenever you print something to the log, it should tell you whether it was done from the client or server thread.

 

Unless you print out a pure number. 

System.out.println(someInt)

will print "4" while

System.out.println(someInt + " energy")

will print "[time] [client] [package and class name:line#]: 4 energy"

 

Ah, I wasn't aware of that. I always use a log4j

Logger

when writing something to the console/log, which I would also recommend the OP does.

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

 

Is one on the client and one on the server? Only the server reads the

TileEntity

from NBT.

Im relatively new to TEs so how can a TE be on the client and how can i prevent it?

 

 

Ah, I wasn't aware of that. I always use a log4j

Logger

when writing something to the console/log, which I would also recommend the OP does.

 

Well for just testing stuff a sysout + strg + enter is the easiest or what am i missing?

Posted

Another question:

When i store an EnergyStorage object i can only add Energy via storage#receiveEnergy

But how do i implement a way the TE produces Energy but cant receive energy from "outside", cables for example?

Posted

Ah, I wasn't aware of that. I always use a log4j

Logger

when writing something to the console/log, which I would also recommend the OP does.

 

I often forget as I'm accustomed to using basic trace statements for debugging.  I have converted over to using the logger, generally, though.

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

Is one on the client and one on the server? Only the server reads the

TileEntity

from NBT.

 

Im relatively new to TEs so how can a TE be on the client and how can i prevent it?

 

The server and client both have their own instance of the

TileEntity

, this is normal and not something to be prevented.

 

The client won't have any of the data that you write to NBT unless you sync it. The client doesn't need to have this data unless it's required for rendering purposes.

 

 

Ah, I wasn't aware of that. I always use a log4j

Logger

when writing something to the console/log, which I would also recommend the OP does.

 

Well for just testing stuff a sysout + strg + enter is the easiest or what am i missing?

 

You can get a

Logger

named with your mod ID by calling

FMLPreInitializationEvent#getModLog

. You should store this in a field somewhere and use it whenever you want to write something to the log.

 

You can also use your IDE's debugger to pause execution at certain points and inspect the values of fields and local variables.

 

 

Another question:

When i store an EnergyStorage object i can only add Energy via storage#receiveEnergy

But how do i implement a way the TE produces Energy but cant receive energy from "outside", cables for example?

 

You'll probably want to create a class that extends

EnergyStorage

, overrides

EnergyStorage#canReceive

to return

false

and has a copy of the

EnergyStorage#receiveEnergy

method with a different name and/or signature (so it doesn't implement the interface method) that ignores

EnergyStorage#canReceive

.

 

External cables will use the interface method, your internal code can use the method you created.

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 server and client both have their own instance of the

TileEntity

, this is normal and not something to be prevented.

 

The client won't have any of the data that you write to NBT unless you sync it. The client doesn't need to have this data unless it's required for rendering purposes.

 

 

SO the client version of the TE will always start the values again from 0, becuase only the server variant loads the data from nbt. And it is no problem that there are 2 different values as long i dont do client side things with the value?

Posted

 

The server and client both have their own instance of the

TileEntity

, this is normal and not something to be prevented.

 

The client won't have any of the data that you write to NBT unless you sync it. The client doesn't need to have this data unless it's required for rendering purposes.

 

SO the client version of the TE will always start the values again from 0, becuase only the server variant loads the data from nbt. And it is no problem that there are 2 different values as long i dont do client side things with the value?

 

Yes.

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

Can someone link me to examples/tutorials for Server/Client TE syncing? I havent done that at all til now and i guess i need it because i want to add an energy bar to the gui and the gui is client stuff :)

Posted

Can someone link me to examples/tutorials for Server/Client TE syncing? I havent done that at all til now and i guess i need it because i want to add an energy bar to the gui and the gui is client stuff :)

 

For syncing values used in a GUI, you should cache any synced values in the

Container

and override

Container#detectAndSendChanges

to check the current values, send them to the client if they're different to the cached values and then cache the current values.

 

This can be done using vanilla packets or your own custom packets. Use

IContainerListener#sendProgressBarUpdate

to send a pair of

int

s (e.g. the ID of the energy storage and the current energy in it) to the client-side

Container

, which will then have

Container#updateProgressBar

called with them as arguments.

 

Look at

ContainerFurnace

for an example of this.

 

For syncing values used to render the block, you need to send them in the

TileEntity

's update tag and packet. This document explains these in more detail.

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.

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

    • Reach Out To Rapid Digital: What sapp Info: +1 41 4 80 7 14 85 Email INFO: rap iddi gita lrecov ery @ exe cs. com Hello, my name is Jayson, and I’m 35 years old from the United Kingdom. My family and I recently endured an incredibly challenging experience that I wouldn’t wish on anyone. We became victims of a cryptocurrency investment fraud scheme that saw us lose a staggering $807,000 in USDT and Bitcoins. The fraudsters had created a convincing facade, and we were lured into investing, only to discover later that the platform was a complete scam. We were left devastated, not just financially, but emotionally, as we had trusted these people and believed in the legitimacy of the investment. After the initial shock wore off, we desperately searched for ways to recover the lost funds. It seemed like an impossible task, and we felt as though there was no hope. That’s when, by sheer luck, we stumbled across a post about Rapid Digital Recovery, a cryptocurrency and funds recovery organization with a proven track record in cybersecurity and fraud recovery. We decided to reach out to them, and from the first interaction, we were impressed with their professionalism and transparency. They explained the recovery process in detail and reassured us that they had the skills and expertise to track down the perpetrators and recover our funds. This gave us a renewed sense of hope, something we hadn’t felt in months. What truly stood out during our experience with Rapid Digital Recovery was their dedication to the recovery process. The team went above and beyond, using sophisticated tracking tools and cyber forensics to gather critical information. Within a matter of weeks, they had successfully located the funds and traced the scam back to the fraudsters responsible. They worked with the authorities to ensure the criminals were held accountable for their actions. To our relief, the team at Rapid Digital Recovery was able to recover every single penny we had lost. The funds were returned in full, and the sense of closure we felt was invaluable. We couldn’t have imagined such a positive outcome in the early stages of our recovery journey, and we are deeply grateful for the work they did. If you ever find yourself in a similar situation, I highly recommend contacting Rapid Digital Recovery. Their expertise, transparency, and dedication to their clients make them the go-to choice for anyone seeking to recover lost cryptocurrency or funds. They truly gave us back our financial future.  
    • This is my first time modding anything, so maybe just skill issue. I'm using Forge 54.0.12 and Temurin 21.0.5+11-LTS I wanted to create a custom keybind and to check whether it works I'd like to send a chat message. I tried using Minecraft.getInstance().player.sendSystemMessage(Component.literal("test")); but IntelliJ couldnt resolve sendSystemMessage(...). Since I saw people using it in earlier versions, I tried the same thing with 1.20.6(- 50.1.0), where it works fine, now I can't figure out if this is intentional and whether there are other options for sending chat messages. On that note, is there more documentation than https://docs.minecraftforge.net/en/1.21.x/? It seems very incomplete compared to something like the Oracle Java docs
    • Hi, i'm having this error and I wanna fix it. we try: -Reload drivers -Eliminate .minecraft -Eliminate Java -Restart launcher -Verify if minecraft is using gpu -Mods  in .minecraft is empty -Install the latest and recomended version of forge idk what i have to do, help me pls. the lastest log is: https://mclo.gs/WAMao8x  
    • Read the FAQ, Rule #2. (https://forums.minecraftforge.net/topic/125488-rules-and-frequently-asked-questions-faq/)  
    • The link to your log does not work, it says it is forbidden, Error, this is a private paste or is pending moderation.
  • Topics

×
×
  • Create New...

Important Information

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