Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Am I able to save a list of TileEntities to CompoundNBT


CriscoMods
 Share

Recommended Posts

//saving all tile entities
List<CompoundNBT> connectedEntities = new ArrayList<>();
CompoundNBT entity;
for (int entityInList = 0; entityInList <= this.masterEntity.connectedEntities.size();entityInList++)
{
    entity = new CompoundNBT();
    entity.putInt("x",this.masterEntity.connectedEntities.get(entityInList).pos.getX());
    entity.putInt("y",this.masterEntity.connectedEntities.get(entityInList).pos.getY());
    entity.putInt("z",this.masterEntity.connectedEntities.get(entityInList).pos.getZ());
    connectedEntities.add(entity);
}
compound.put("connectedEntities", (INBT) connectedEntities);  
 //restore saved entities
    List<CompoundNBT> connectedEntities = (List<CompoundNBT>) compound.get("connectedEntities");
    CompoundNBT entity;
   if (connectedEntities!= null){
    for (int entityInList = 0; entityInList < connectedEntities.size();entityInList++ )
{
    entity = connectedEntities.get(entityInList);
    this.masterEntity.connectedEntities.add((EngineeringBlockTileEntity)this.world.getTileEntity(new BlockPos(entity.getInt("x"),entity.getInt("y"),entity.getInt("z"))));
}}

 

So I'm trying to save list of TileEntities to a block, because the block uses the list to determine the number of blocks connected to each other. As the blocks are being placed the list expands. If I exit the world and comeback I cannot remove blocks that have already been placed.  It crashes when it attempts to remove that block from the connectedEntities list because the list is empty.

I'm trying to save it using the code above but it's not working. I just need some to be point me in the right direction.

@Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
    EngineeringBlockTileEntity entityRemoved = (EngineeringBlockTileEntity) worldIn.getTileEntity(pos);
   entityRemoved.masterEntity.connectedEntities.remove(entityRemoved);
   entityRemoved.masterEntity.blockCount = entityRemoved.masterEntity.connectedEntities.size();
    super.onBlockHarvested(worldIn, pos, state, player);
}

 

 

Link to comment
Share on other sites

Several issues:

  • For a start onBlockHarvested is not at all the right hook here. You need TileEntity#remove.
  • Your connections need to be lazy. As in: The TEs need to know only the positions and lazily query the world. During readFromNBT there is no world yet, you can't query the world for other TEs.
  • Like 1
Link to comment
Share on other sites

On 12/9/2020 at 8:17 AM, diesieben07 said:

Several issues:

  • For a start onBlockHarvested is not at all the right hook here. You need TileEntity#remove.
  • Your connections need to be lazy. As in: The TEs need to know only the positions and lazily query the world. During readFromNBT there is no world yet, you can't query the world for other TEs.

Okay so I've simplified my connections a great deal. I've Overrided neighborChange. As blocks are added I pass a "masterEntity" to each block so that everyone is capable of updating this multiBlock blockCount to the masterEntity. Instead of having a list of tileEntities I opted for a list of BlockPos like you mentioned.  As I'm writing this I realize I can pass a blockCount to each block instead meaning that I could maybe remove the blockPos list (still not sure what I will do). Then I can use the NBT system to store the block count.

@Override
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor){


        if (world.getTileEntity(neighbor) instanceof EngineeringBlockTileEntity)
        {
            //pass master from this block to the next
            EngineeringBlockTileEntity neighborEntity = (EngineeringBlockTileEntity) world.getTileEntity(neighbor);
            EngineeringBlockTileEntity thisEntity = (EngineeringBlockTileEntity)world.getTileEntity(pos);
            neighborEntity.masterEntity = thisEntity.masterEntity;
            //add neighbor block position to list of master list
            if (!thisEntity.masterEntity.connectedBlocks.contains(neighbor)) {
                neighborEntity.masterEntity.connectedBlocks.add(neighbor);
            }
            //update blockCount
            neighborEntity.masterEntity.blockCount = neighborEntity.masterEntity.connectedBlocks.size();
            System.out.println(neighborEntity.masterEntity.blockCount);
        }
   }

Then for removing blocks from the list  I used remove() as you suggested and woah simple as heck

@Override
public void remove() {

    if (this.masterEntity != null)
    {
        this.masterEntity.connectedBlocks.remove(this.getPos());
    }
    super.remove();
}

I may not have completly understood and implemented a lazy query as you suggested but I was able to get this to work using

less code because of your suggestion. I'm still trying to figure out how to have the block query around them upon reloading of a world.

 Thank you for your help it is much appreciated.

Edited by CriscoMods
Link to comment
Share on other sites

5 hours ago, Vinyarion said:

Your tile entity could have a flag that starts as true at construction, then in the tick method, if(flag){flag=false;/* check for surrounding blocks */}

Good Idea. Works :) Ended up doing this 

 

if (this.InitializeBlocks)
{
    if (this.isMaster) {this.setMaster(); }
    this.lazyQuery();
    this.updateMasterBlockList();

}

IntializeBlocks is set to true upon initialization, but to prevent this piece of code from running in a tick when the block is placed for the first time I set it to false . The flag is also set false in function updateMasterBlockList

@Override
public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) {
    EngineeringBlockTileEntity thisBlock = ((EngineeringBlockTileEntity) worldIn.getTileEntity(pos));
    if (stack.hasDisplayName()) { TileEntity tile = worldIn.getTileEntity(pos);
        if (tile instanceof EngineeringBlockTileEntity) { thisBlock.setCustomName(stack.getDisplayName()); }
    }
    //don't initialize blocks upon placement
    thisBlock.InitializeBlocks = false;
    if (thisBlock.isAlone()) { thisBlock.setMaster(); System.out.println(thisBlock.isMaster);}
    super.onBlockPlacedBy(worldIn, pos, state, placer, stack);

}

 

Edited by CriscoMods
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
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.

 Share



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Hi everyone, I use the Curse Forge app for overwatch and I created a plain 1.17.1 forge 37.1.0 profile. It crashes immediately when I click "play" in the minecraft launcher. I just installed Java 16 and set minecraft to use it in the curse forge app settings. I don't have any mods installed and my log looks like this: [12:36:42] [main/INFO]: ModLauncher running: args [--username, MrKatuffel, --version, forge-37.1.0, --gameDir, C:\Users\Benni\Documents\Minecraft\Instances\1.17.1, --assetsDir, C:\Users\Benni\Documents\Minecraft\Install\assets, --assetIndex, 1.17, --uuid, 2021e6cbc7bc4d2a81effa163cfd62d9, --accessToken, ????????, --userType, mojang, --versionType, release, --width, 1024, --height, 768, --launchTarget, forgeclient, --fml.forgeVersion, 37.1.0, --fml.mcVersion, 1.17.1, --fml.forgeGroup, net.minecraftforge, --fml.mcpVersion, 20210706.113038] [12:36:42] [main/INFO]: ModLauncher 9.0.7+91+master.8569cdf starting: java version 16.0.1 by Microsoft [12:36:42] [main/INFO]: SpongePowered MIXIN Subsystem Version=0.8.4 Source=union:/C:/Users/Benni/Documents/Minecraft/Install/libraries/org/spongepowered/mixin/0.8.4/mixin-0.8.4.jar%2318! Service=ModLauncher Env=CLIENT [12:36:43] [main/INFO]: Found mod file fmlcore-1.17.1-37.1.0.jar of type LIBRARY with locator net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator@6cc0bcf6 [12:36:43] [main/INFO]: Found mod file javafmllanguage-1.17.1-37.1.0.jar of type LANGPROVIDER with locator net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator@6cc0bcf6 [12:36:43] [main/INFO]: Found mod file mclanguage-1.17.1-37.1.0.jar of type LANGPROVIDER with locator net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator@6cc0bcf6 [12:36:43] [main/INFO]: Found mod file client-1.17.1-20210706.113038-srg.jar of type MOD with locator net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator@6cc0bcf6 [12:36:43] [main/INFO]: Found mod file forge-1.17.1-37.1.0-universal.jar of type MOD with locator net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator@6cc0bcf6 So I can see it is indeed using Java 16. The error message of the minecraft launcher is just: So that isn't helping. Anyone have any ideas?
    • Further testing revealed that Forge will not successfully load any library in the IDE at all, if the library is not a mod. This means this is either a Forge bug, or the way to include a library at runtime has been changed. Tested with a random library for Java not included in Minecraft or Forge: build.gradle dependencies { minecraft 'net.minecraftforge:forge:1.18-38.0.8' implementation 'com.github.ben-manes.caffeine:caffeine:3.0.4' } ExampleMod.java package com.example.examplemod; import com.github.benmanes.caffeine.cache.Caffeine; import net.minecraftforge.fml.common.Mod; @Mod("examplemod") public class ExampleMod { public ExampleMod() { Caffeine<Object, Object> graphs = Caffeine.newBuilder(); } } Will result in java.lang.NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine Should I file a bug report?
    • Thank you! I managed to get this working finally after puzzling through it, and your answer gave me a good place to start. I ended up using a combination of several for loops and an int array which was filled with the values of my "weight" json attribute for each recipe. Iterating through each recipe in my main list, I could add to a new array several repeats of the same number for the weight, and this number would correlate to a specific recipe in the main list. E.g. if the weight for the recipe in index 0 was 5, then 0 would be added to the array 5 times. My random number would then be chosen from this new array, and the recipe fetched from the main list using it. This works like an absolute charm. Hope this helps anyone else that might stumble on this thread! 
    • What should you set the Ingredient parameter of SimpleCookingRecipeBuilder.cooking() to?
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.