Jump to content

[1.11] World Capabilities.


Lambda

Recommended Posts

  • Replies 59
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Hey there!

 

So I'm in need of storing a capability that keeps track of an integer inside each chunk.. Is there a way I can store a capability in each of those chunks?

You will have to map it to each chunk. Like

Map<ChunkPos, Integer> chunkData; // Probably going to have to make ChunkPos which will just hold an x and a z.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Well yeah, but how would I create a 'World' capability.. what differences vs. player capabilities, etc.

Nothing except AttachCapabilitiesEvent<World> And then the only other difference is you could also use WorldSavedData. Which I believe is meant more for small data like a few int(s), boolean(s), etc.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

So I should jsut use the WorldSavedData, I already have one storing a few things.. Also the ChunkPos thing... How should I get each chunk and assign a default value to them?

Each chunk has its own coords. World#getChunkFromChunkCoords(x, z) or World#getChunkFromBlockCoords(BlockPos). Then you can get the chunk coords aka the ChunkPos. Or you could just bit shift by 16 from the blocks x and z. And no you should use a World Capability in my opinion because when you save it it will be a lot of data.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

So do chunks work like gird coords? 0,0 1,0 2,0 0,1? And how would I iterate though all of them to assign the capability to them? And can I expose the capability with

World#getChunkFromBlockCoords(BlockPos)

, So I could access it though a TE?

Yes you could access it through a TE(How do you think Chunk Loaders work). You are not assigning the data to each chunk. You are saving data to the world using an identifier that is the Chunks coords(ChunkPos).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Because you're mapping the chunk's location to the value with a hashmap.

 

There's how.

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.

Link to comment
Share on other sites

Well, you know Deep Resonance? How radiation works with the chunks being assigned values? I kinda want that, but a energy value stored to each one.. So I think i need to assign the data to each chunk :/

That would do what you want. What I am saying is that you can't assign it directly IE it saves directly to the Chunk. You will save it to the world, but there will be one for every chunk. Example in my first post.

Hey there!

 

So I'm in need of storing a capability that keeps track of an integer inside each chunk.. Is there a way I can store a capability in each of those chunks?

Map<ChunkPos, Integer> chunkData; // Probably going to have to make ChunkPos which will just hold an x and a z.

You will get the Chunks x and z like so

World#getBlockFromBlockCoord(getPos()).xPosition

World#getBlockFromBlockCoord(getPos()).zPosition

And then get your capability and do

capability.chunkData.get(new ChunkPos(chunkX, chunkZ));

Then you have your energy in that chunk.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Vanilla already has a

ChunkPos

class, you can get a

Chunk

's

ChunkPos

with

Chunk#getPos

.

 

You probably don't want to hold the data for every chunk of every dimension in memory at once, so you should load and save your data with the chunk and remove a chunk's data from the

Map

when it unloads.

 

You can do this by handling

ChunkDataEvent.Load

to read data from the chunk's NBT into a per-dimension

[code]Map<ChunkPos, YourDataClass>

[/code] (stored in your capability) and then handling

ChunkDataEvent.Save

to write data from the

Map

into the chunk's NBT. You'll also want to handle

ChunkEvent.Unload

to remove the entry for the unloaded chunk from the

Map

.

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.

Link to comment
Share on other sites

Vanilla already has a

ChunkPos

class, you can get a

Chunk

's

ChunkPos

with

Chunk#getPos

.

Awesome i didn't know that, never needed it myself. :)

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Do I have to assign the map? Or does the ChuckPos include all loaded chunks?

 

I don't know what you're talking about.

ChunkPos

is simply a class that stores the x and z coordinates of a single chunk.

 

When

ChunkDataEvent.Load

fires, read the data for that

Chunk

from the NBT and store it in the

Map

.

 

When

ChunkDataEvent.Save

fires, write the data for that

Chunk

from the

Map

to the NBT.

 

When

ChunkEvent.Unload

fires, remove the data for that

Chunk

from the

Map

.

 

Use the

Chunk

's

ChunkPos

as the key for the

Map

.

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.

Link to comment
Share on other sites

I don't know if this is right.. but I gave it my best shot :/

 

    @SubscribeEvent
    public void onAddCapabilitiesWorld(AttachCapabilitiesEvent<World> w) {
        w.addCapability(CapabilityVoidEnergyProvider.KEY, new CapabilityVoidEnergyProvider());
    }

    @SubscribeEvent
    public void onChuckLoadEvent(ChunkDataEvent.Load event) {
        if(event.getWorld().hasCapability(CapabilityVoidEnergy.VOID, null)) {
            CapabilityVoidEnergyData cap = event.getWorld().getCapability(CapabilityVoidEnergy.VOID, null);
            cap.chunkData.put(event.getChunk().getPos(), cap.getVoidEnergyStored());
        }
    }

    @SubscribeEvent
    public void onChuckSaveEvent(ChunkDataEvent.Save event) {
        if(event.getWorld().hasCapability(CapabilityVoidEnergy.VOID, null)) {
            CapabilityVoidEnergyData cap = event.getWorld().getCapability(CapabilityVoidEnergy.VOID, null);
            NBTTagCompound tag = new NBTTagCompound();
            tag.setInteger("StartChunkX", event.getChunk().getPos().getXStart());
            tag.setInteger("EndChunkX", event.getChunk().getPos().getXEnd());
            tag.setInteger("StartChunkZ", event.getChunk().getPos().getZStart());
            tag.setInteger("EndChunkZ", event.getChunk().getPos().getZEnd());
            tag.setInteger("VoidStored", cap.getVoidEnergyStored());

            cap.writeData(tag);
        }
    }

    @SubscribeEvent
    public void onChuckUnloadEvent(ChunkDataEvent.Unload event) {
        if(event.getWorld().hasCapability(CapabilityVoidEnergy.VOID, null)) {
            CapabilityVoidEnergyData cap = event.getWorld().getCapability(CapabilityVoidEnergy.VOID, null);
            cap.chunkData.remove(event.getChunk().getPos());
            cap.chunkData.remove(cap.getVoidEnergyStored());
        }
    }

 

 

The Capability Stuff

public class CapabilityVoidEnergy
{
    @CapabilityInject(CapabilityVoidEnergyData.class)
    public static Capability<CapabilityVoidEnergyData> VOID = null;

    public static void register()
    {
        CapabilityManager.INSTANCE.register(CapabilityVoidEnergyData.class, new StorageHelper(), new DefaultInstanceFactory());
    }

    public static class StorageHelper implements Capability.IStorage<CapabilityVoidEnergyData>
    {
        @Override
        public NBTBase writeNBT(Capability<CapabilityVoidEnergyData> capability, CapabilityVoidEnergyData instance, EnumFacing side)
        {
            return instance.writeData();
        }

        @Override
        public void readNBT(Capability<CapabilityVoidEnergyData> capability, CapabilityVoidEnergyData instance, EnumFacing side, NBTBase nbt)
        {
            instance.readData(nbt);
        }
    }

    public static class DefaultInstanceFactory implements Callable<CapabilityVoidEnergyData>
    {
        @Override
        public CapabilityVoidEnergyData call() throws Exception
        {
            return new CapabilityVoidEnergyData(50000, 50000, 2);
        }
    }
}

CapabilityData:

public class CapabilityVoidEnergyData implements IVoidStorage {

    protected int capacity;
    protected int voidStorage;
    protected int regen;

    public Map<ChunkPos, Integer> chunkData;


    public CapabilityVoidEnergyData(int capacity, int voidStorage, int regen) {
        this.capacity = capacity;
        this.voidStorage = voidStorage;
        this.regen = regen;
    }

    @Override
    public void receiveVoidEnergy(int receive) {
        if(canReceiveVoidEnergy(receive)) {
            this.setVoidStorage(this.getVoidEnergyStored() + receive);
        }
    }

    @Override
    public void extractVoidEnergy(int extract) {
        if(canExtractVoidEnergy(extract)) {
            this.setVoidStorage(this.getVoidEnergyStored() - extract);
        }
    }

    public boolean canExtractVoidEnergy(float amount) {
        if((this.getVoidEnergyStored() - amount) >= 0) {
            return true;
        }else {
            return false;
        }
    }

    public boolean canReceiveVoidEnergy(float amount) {
        if((this.getVoidEnergyStored() + amount) <= this.getMaxVoidEnergyStored()) {
            return true;
        }else {
            return false;
        }
    }

    public void writeData(NBTTagCompound compound) {

    }

    public void readData(NBTBase nbt) {

    }

    @Override
    public int getVoidEnergyStored() {
        return voidStorage;
    }

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

    public void setVoidStorage(int amount) {
        this.voidStorage = amount;
    }

    @Override
    public boolean canExtract() {
        return false;
    }

    @Override
    public boolean canReceive() {
        return false;
    }
}

 

Provider:

public class CapabilityVoidEnergyProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound>
{

    public static final ResourceLocation KEY = new ResourceLocation(ModUtil.MOD_ID, "mana");

    private CapabilityVoidEnergyData INSTANCE = new CapabilityVoidEnergyData(50000, 50000, 2);


    @Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing)
    {
        return capability == CapabilityVoidEnergy.VOID;
    }

    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing)
    {
        if (capability == CapabilityVoidEnergy.VOID) return (T) INSTANCE;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT()
    {
        return (NBTTagCompound) CapabilityVoidEnergy.VOID.writeNBT(INSTANCE, null);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt)
    {
        CapabilityVoidEnergy.VOID.readNBT(INSTANCE, null, nbt);
    }

}

 

 

Relatively new to modding.

Currently developing:

https://github.com/LambdaXV/DynamicGenerators

Link to comment
Share on other sites

I see to be getting a NullPointer on:

            cap.chunkData.put(event.getChunk().getPos(), cap.getVoidEnergyStored());

with:

---- Minecraft Crash Report ----
// I'm sorry, Dave.

Time: 12/31/16 12:31 PM
Description: Exception in server tick loop

java.lang.NullPointerException: Exception in server tick loop
at com.lambda.plentifulutilities.event.CommonSideEvents.onChuckLoadEvent(CommonSideEvents.java:40)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_CommonSideEvents_onChuckLoadEvent_Load.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185)
at net.minecraftforge.common.chunkio.ChunkIOProvider.syncCallback(ChunkIOProvider.java:98)
at net.minecraftforge.common.chunkio.ChunkIOExecutor.syncChunkLoad(ChunkIOExecutor.java:94)
at net.minecraft.world.gen.ChunkProviderServer.loadChunk(ChunkProviderServer.java:125)
at net.minecraft.world.gen.ChunkProviderServer.loadChunk(ChunkProviderServer.java:96)
at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:142)
at net.minecraft.server.MinecraftServer.initialWorldChunkLoad(MinecraftServer.java:340)
at net.minecraft.server.integrated.IntegratedServer.loadAllWorlds(IntegratedServer.java:107)
at net.minecraft.server.integrated.IntegratedServer.init(IntegratedServer.java:124)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:507)
at java.lang.Thread.run(Thread.java:745)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- System Details --
Details:
Minecraft Version: 1.11.2
Operating System: Windows 10 (amd64) version 10.0
Java Version: 1.8.0_91, Oracle Corporation
Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
Memory: 1293656720 bytes (1233 MB) / 1717567488 bytes (1638 MB) up to 3814195200 bytes (3637 MB)
JVM Flags: 0 total; 
IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
FML: MCP 9.38 Powered by Forge 13.20.0.2201 5 mods loaded, 5 mods active
States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored
UCHIJAA	minecraft{1.11.2} [Minecraft] (minecraft.jar) 
UCHIJAA	mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) 
UCHIJAA	FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.11.2-13.20.0.2201.jar) 
UCHIJAA	forge{13.20.0.2201} [Minecraft Forge] (forgeSrc-1.11.2-13.20.0.2201.jar) 
UCHIJAA	plentifulutilities{${version}} [Plentiful Utilities] (PlentifulUtilities_main) 
Loaded coremods (and transformers): 
GL info: ~~ERROR~~ RuntimeException: No OpenGL context found in the current thread.
Profiler Position: N/A (disabled)
Player Count: 0 / 8; []
Type: Integrated Server (map_client.txt)
Is Modded: Definitely; Client brand changed to 'fml,forge'

 

Here is the method:

    @SubscribeEvent
    public void onChuckLoadEvent(ChunkDataEvent.Load event) {
        if(event.getWorld().hasCapability(CapabilityVoidEnergy.VOID, null)) {
            CapabilityVoidEnergyData cap = event.getWorld().getCapability(CapabilityVoidEnergy.VOID, null);
            cap.chunkData.put(event.getChunk().getPos(), cap.getVoidEnergyStored());
        }
    }

Relatively new to modding.

Currently developing:

https://github.com/LambdaXV/DynamicGenerators

Link to comment
Share on other sites

I see to be getting a NullPointer on:

            cap.chunkData.put(event.getChunk().getPos(), cap.getVoidEnergyStored());

with:

---- Minecraft Crash Report ----
// I'm sorry, Dave.

Time: 12/31/16 12:31 PM
Description: Exception in server tick loop

java.lang.NullPointerException: Exception in server tick loop
at com.lambda.plentifulutilities.event.CommonSideEvents.onChuckLoadEvent(CommonSideEvents.java:40)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_CommonSideEvents_onChuckLoadEvent_Load.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185)
at net.minecraftforge.common.chunkio.ChunkIOProvider.syncCallback(ChunkIOProvider.java:98)
at net.minecraftforge.common.chunkio.ChunkIOExecutor.syncChunkLoad(ChunkIOExecutor.java:94)
at net.minecraft.world.gen.ChunkProviderServer.loadChunk(ChunkProviderServer.java:125)
at net.minecraft.world.gen.ChunkProviderServer.loadChunk(ChunkProviderServer.java:96)
at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:142)
at net.minecraft.server.MinecraftServer.initialWorldChunkLoad(MinecraftServer.java:340)
at net.minecraft.server.integrated.IntegratedServer.loadAllWorlds(IntegratedServer.java:107)
at net.minecraft.server.integrated.IntegratedServer.init(IntegratedServer.java:124)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:507)
at java.lang.Thread.run(Thread.java:745)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- System Details --
Details:
Minecraft Version: 1.11.2
Operating System: Windows 10 (amd64) version 10.0
Java Version: 1.8.0_91, Oracle Corporation
Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
Memory: 1293656720 bytes (1233 MB) / 1717567488 bytes (1638 MB) up to 3814195200 bytes (3637 MB)
JVM Flags: 0 total; 
IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
FML: MCP 9.38 Powered by Forge 13.20.0.2201 5 mods loaded, 5 mods active
States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored
UCHIJAA	minecraft{1.11.2} [Minecraft] (minecraft.jar) 
UCHIJAA	mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) 
UCHIJAA	FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.11.2-13.20.0.2201.jar) 
UCHIJAA	forge{13.20.0.2201} [Minecraft Forge] (forgeSrc-1.11.2-13.20.0.2201.jar) 
UCHIJAA	plentifulutilities{${version}} [Plentiful Utilities] (PlentifulUtilities_main) 
Loaded coremods (and transformers): 
GL info: ~~ERROR~~ RuntimeException: No OpenGL context found in the current thread.
Profiler Position: N/A (disabled)
Player Count: 0 / 8; []
Type: Integrated Server (map_client.txt)
Is Modded: Definitely; Client brand changed to 'fml,forge'

 

Here is the method:

    @SubscribeEvent
    public void onChuckLoadEvent(ChunkDataEvent.Load event) {
        if(event.getWorld().hasCapability(CapabilityVoidEnergy.VOID, null)) {
            CapabilityVoidEnergyData cap = event.getWorld().getCapability(CapabilityVoidEnergy.VOID, null);
            cap.chunkData.put(event.getChunk().getPos(), cap.getVoidEnergyStored());
        }
    }

public Map<ChunkPos, Integer> chunkData; is never initialized.

 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Okay, how would I add / remove some 'energy' from a chunk, not all of them, current I have:

 

                        cap.chunkData.get(new ChunkPos(this.getPos()));
                        cap.receiveVoidEnergy(5);

 

Which obviously doesn't work because I accessing all chunks with cap.receive... So how would I just do it for that chunk?

Relatively new to modding.

Currently developing:

https://github.com/LambdaXV/DynamicGenerators

Link to comment
Share on other sites

Presumably

cap.chunkData.get()

returns something...

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.

Link to comment
Share on other sites

What is the integer that it returns? the x/y value or the integer that I assigned in the Map?

https://docs.oracle.com/javase/7/docs/api/java/util/Map.html

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Okay, thanks for that.. How would I get the energy value though... Yes it returns the value, however what would I do with said value?

Modify it.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Okay, so why does modifying the values of the keys have to do with my 'energy'? I know I'm doing something wrong here:

 

                        cap.chunkData.put(cap.chunkData.get(new ChunkPos(this.getPos()), /* new value */);

 

Is this correct?

 

If I'm getting this right, then when we assigned the map, ChuckPos is our key, which contains our x,y, and the integer part stores the x,y values? Correct?

Relatively new to modding.

Currently developing:

https://github.com/LambdaXV/DynamicGenerators

Link to comment
Share on other sites

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.