Jump to content

Jipthechip

Members
  • Posts

    28
  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Jipthechip's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  1. I'm trying to use Geckolib to have a block animation play when the block is right clicked, however it isn't working properly. When I right click the block the animation will play once, and then any subsequent times I right click, nothing happens. Here's my Block class: public class MagicChurnerBlock extends BlockWithEntity { protected MagicChurnerBlock(Settings settings) { super(settings); } @Nullable @Override public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return new MagicChurner(pos, state); } @Nullable @Override public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) { return checkType(type, DiabolismEntities.MAGIC_CHURNER_BLOCKENTITY, MagicChurner::ticker); } @Override public BlockRenderType getRenderType(BlockState state) { return BlockRenderType.ENTITYBLOCK_ANIMATED; } @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { MagicChurner magicChurner = (MagicChurner) world.getBlockEntity(pos); if(magicChurner != null && world.isClient){ magicChurner.turn(); } return ActionResult.SUCCESS; } } And my Block Entity Class: public class MagicChurner extends AbstractFluidContainer implements IAnimatable { private AnimationFactory factory = new InstancedAnimationFactory(this); private boolean hasBeenTurned =false; public MagicChurner(BlockPos pos, BlockState state) { super(DiabolismEntities.MAGIC_CHURNER_BLOCKENTITY, pos, state, 1000); } @Override public void registerControllers(AnimationData animationData) { animationData.addAnimationController(new AnimationController<MagicChurner>(this, "controller", 0, this::predicate)); } private <E extends IAnimatable>PlayState predicate(AnimationEvent<E> event){ if(hasBeenTurned) { event.getController().setAnimation(new AnimationBuilder().addAnimation("magic_churner_turn", (ILoopType) ILoopType.EDefaultLoopTypes.PLAY_ONCE)); hasBeenTurned = false; } return PlayState.CONTINUE; } @Override public AnimationFactory getFactory() { return this.factory; } public static void ticker(World world, BlockPos pos, BlockState state, MagicChurner be) { be.tick(world, pos, state); } private void tick(World world, BlockPos pos, BlockState state) { } public void turn(){ this.hasBeenTurned = true; }
  2. During testing I noticed it usually wasn't being called when I loaded in my TileEntity, so I'm assuming the client has to tell the server it needs the data, then the server calls read() and sends the data to the client?
  3. Ohhh ok that makes a lot of sense now. I didn't think I'd need to learn about packets so soon, but I guess I have no choice now. But there's one thing I'm still confused about. So I'm guessing write() is a function that is called serverside to save the NBT data whenever the server decides to save the chunk that the TileEntity is in. But when is read() called? When I was testing, it was called at seemingly random times and I'm still confused where it fits in.
  4. So you're saying that the NBT data is being written and the server has it, but the client for some reason isn't receiving it when the chunk is loaded? If so, how do I make sure that the client and server are synchronized?
  5. My bad, I can tell it's no longer there because I have an IBlockColor class setting the color of one of the submodels of the TileEntity, and the color depends on data within my custom TileEntity class. When I reload the chunk, the color goes back to its default blue and the TileEntity accepts 4 ingredients again even though it should be full. Also here is my custom IBlockColor class in case this helps: package com.jipthechip.fermentationmod.Blocks; import com.jipthechip.fermentationmod.Entities.MasherBowlTileEntity; import net.minecraft.block.BlockState; import net.minecraft.block.material.MaterialColor; import net.minecraft.client.renderer.color.IBlockColor; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockDisplayReader; import javax.annotation.Nullable; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import net.minecraft.world.World; import static com.jipthechip.fermentationmod.Entities.MasherBowlTileEntity.FoodType; public class MasherWaterColor implements IBlockColor { private final Map<FoodType, Integer> foodColors = Stream.of(new Object[][] { {FoodType.apple, 0xffffe063}, {FoodType.baked_potato, 0xfffff8ad}, {FoodType.beetroot, 0xffa4272b}, {FoodType.bread, 0xffe8d697}, {FoodType.carrot, 0xffff8e09}, {FoodType.chorus_fruit, 0xff8E678D}, {FoodType.dried_kelp, 0xff3C3324}, {FoodType.kelp, 0xff5C8332}, {FoodType.honey_bottle, 0xffFFD32D}, {FoodType.melon_slice, 0xffBF3123}, {FoodType.potato, 0xfffff8ad}, {FoodType.poisonous_potato, 0xffefffad}, {FoodType.pumpkin, 0xffE38A1D}, {FoodType.sweet_berries, 0xffDF467E}, {FoodType.nothing, MaterialColor.WATER.colorValue} }).collect(Collectors.toMap(data -> (FoodType) data[0], data -> (Integer) data[1])); @Override public int getColor(BlockState state, @Nullable IBlockDisplayReader blockDisplayReader, @Nullable BlockPos pos, int tintIndex) { assert blockDisplayReader != null; assert pos != null; MasherBowlTileEntity tileEntity = (MasherBowlTileEntity) blockDisplayReader.getTileEntity(pos); assert tileEntity != null; // mix the colors of the 4 ingredients together int ingredients = mixColors(1, foodColors.get(tileEntity.getIngredient(0)), mixColors(1, foodColors.get(tileEntity.getIngredient(1)), mixColors(1, foodColors.get(tileEntity.getIngredient(2)), foodColors.get(tileEntity.getIngredient(3))))); return mixColors(10-state.get(MasherBowlBlock.STIR_PROGRESS), MaterialColor.WATER.colorValue, ingredients); } private int mixColors(int weight, int color1, int color2){ if(weight == 0){ return color2; } int color1_a = (color1 & 0xff000000) >> 24; int color1_r = (color1 & 0x00ff0000) >> 16; int color1_g = (color1 & 0x0000ff00) >> 8; int color1_b = color1 & 0x000000ff; int color2_a = (color2 & 0xff000000) >> 24; int color2_r = (color2 & 0x00ff0000) >> 16; int color2_g = (color2 & 0x0000ff00) >> 8; int color2_b = color2 & 0x000000ff; int result_a = color2_a; int result_r = color2_r; int result_g = color2_g; int result_b = color2_b; for(int i = 0; i < weight; i++){ result_a = (result_a + color1_a)/2; result_r = (result_r + color1_r)/2; result_g = (result_g + color1_g)/2; result_b = (result_b + color1_b)/2; } result_a = result_a << 24; result_r = result_r << 16; result_g = result_g << 8; return result_a + result_r + result_g + result_b; } }
  6. I'm trying to save the data of a custom TileEntity, but it doesn't seem to be working properly because after unloading and reloading the chunk, the data is no longer there. Here is my TileEntity class: package com.jipthechip.fermentationmod.Entities; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IStringSerializable; import java.util.Arrays; @MethodsReturnNonnullByDefault public class MasherBowlTileEntity extends TileEntity { public enum FoodType implements IStringSerializable { apple, baked_potato, beetroot, bread, carrot, chorus_fruit, dried_kelp, kelp, honey_bottle, melon_slice, potato, poisonous_potato, pumpkin, sweet_berries, nothing; @Override public String getString() { return this.name(); } } private FoodType[] ingredients = new FoodType[4]; public MasherBowlTileEntity(){ super(TileEntitiesList.masher_bowl); clearFoods(); } @Override public void read(BlockState state, CompoundNBT compound) { super.read(state, compound); int [] arr = compound.getIntArray("foodarr"); if(arr.length == 0) System.out.println("no ingredients read!"); else System.out.print("reading ingredients: "+ arr[0] + "," + arr[1]+ "," + arr[2]+ "," + arr[3]+ "\n"); for(int i = 0; i < arr.length; i++){ ingredients[i] = FoodType.values()[arr[i]]; } } private int[] foodToIntArray(FoodType[] arr){ int[] result = new int[arr.length]; for(int i = 0; i < arr.length; i++){ result[i] = arr[i].ordinal(); } return result; } @Override public CompoundNBT write(CompoundNBT compound) { super.write(compound); int [] arr = foodToIntArray(ingredients); compound.putIntArray("foodarr", arr); System.out.print("writing ingredients: "+ arr[0] + "," + arr[1]+ "," + arr[2]+ "," + arr[3]+ "\n"); return compound; } public boolean addFood(FoodType food){ for(int i = 0; i < ingredients.length; i++){ if(ingredients[i] == FoodType.nothing){ markDirty(); ingredients[i] = food; return true; } } return false; } public void clearFoods(){ markDirty(); Arrays.fill(ingredients, FoodType.nothing); } public FoodType getIngredient(int index) { return ingredients[index]; } } In order to have TileEntity data saved to the world, you use the read() and write() methods of the TileEntity class to read and write NBT's, correct? And when exactly are read() and write() called?
  7. My registration class: @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class RegisterBlocks { @SubscribeEvent public static void registerBlocks(final RegistryEvent.Register<Block> event){ event.getRegistry().registerAll( BlocksList.masher_bowl = new MasherBowlBlock(Block.Properties.create(Material.IRON)) .setRegistryName(new ResourceLocation(MOD_ID, "masher_bowl")) } @SubscribeEvent public static void registerTE(RegistryEvent.Register<TileEntityType<?>> event) { event.getRegistry().registerAll( TileEntitiesList.masher_bowl = TileEntityType.Builder.create(MasherBowlTileEntity::new, BlocksList.masher_bowl).build(null) .setRegistryName(MOD_ID, "masher_bowl") ); } } My Block class: public class MasherBowlBlock extends Block { public static final DirectionProperty FACING = HorizontalBlock.HORIZONTAL_FACING; public static final BooleanProperty CONTAINS_ROD = BooleanProperty.create("contains_rod"); public static final DirectionProperty ROD_FACING = DirectionProperty.create("rod_facing", Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); public static final BooleanProperty CONTAINS_WATER = BooleanProperty.create("contains_water"); public static final IntegerProperty STIR_PROGRESS = IntegerProperty.create("stir_progress", 0,10); public MasherBowlBlock(Properties properties) { super(properties.notSolid()); this.setDefaultState(this.getStateContainer().getBaseState() .with(FACING, Direction.NORTH) .with(CONTAINS_ROD, false) .with(ROD_FACING, Direction.NORTH) .with(CONTAINS_WATER, false) .with(STIR_PROGRESS, 0) ); } @Override public BlockState getStateForPlacement(BlockItemUseContext context){ return this.getDefaultState() .with(FACING, context.getPlacementHorizontalFacing().getOpposite()) .with(CONTAINS_ROD, false) .with(ROD_FACING, context.getPlacementHorizontalFacing().getOpposite()) .with(CONTAINS_WATER, false) .with(STIR_PROGRESS, 0); } @Override protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) { builder.add(FACING, CONTAINS_ROD, ROD_FACING, CONTAINS_WATER, STIR_PROGRESS); } @Override public boolean hasTileEntity(BlockState state) { return true; } @Nullable @Override public TileEntity createTileEntity(BlockState state, IBlockReader world) { return new MasherBowlTileEntity(); } @Override public BlockState rotate(BlockState state, Rotation rot) { return state.with(FACING, rot.rotate(state.get(FACING))); } @Override public BlockState mirror(BlockState state, Mirror mirrorIn) { return state.rotate(mirrorIn.toRotation(state.get(FACING))); } @Override public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { ItemStack heldItem = player.getHeldItem(handIn); String itemRegistryName = Objects.requireNonNull(heldItem.getItem().getRegistryName()).toString(); System.out.println(itemRegistryName); switch(itemRegistryName){ case MOD_ID+":masher_rod_item": if(!player.isCreative()) { heldItem.setCount(heldItem.getCount() - 1); } player.sendBreakAnimation(handIn); worldIn.setBlockState(pos, state.with(CONTAINS_ROD, true)); return ActionResultType.SUCCESS; case "minecraft:water_bucket": if(!state.get(CONTAINS_WATER)){ if(!player.isCreative()){ ItemStack bucket = new ItemStack(Items.BUCKET); player.setHeldItem(handIn, bucket); } worldIn.playSound(player, pos, SoundEvents.ITEM_BUCKET_EMPTY, SoundCategory.BLOCKS, 10.0f, 1.0f); worldIn.setBlockState(pos, state.with(CONTAINS_WATER, true)); return ActionResultType.SUCCESS; } break; case "minecraft:bucket": if(state.get(CONTAINS_WATER)){ if(!player.isCreative()){ ItemStack water_bucket = new ItemStack(Items.WATER_BUCKET); player.setHeldItem(handIn, water_bucket); } worldIn.playSound(player, pos, SoundEvents.ITEM_BUCKET_FILL, SoundCategory.BLOCKS, 10.0f, 1.0f); worldIn.setBlockState(pos, state.with(CONTAINS_WATER, false) .with(STIR_PROGRESS, 0)); return ActionResultType.SUCCESS; } break; } // check if the item is one of the valid foods String path = itemRegistryName.split(":")[1]; if(EnumUtils.isValidEnum(FoodType.class, path) && state.get(CONTAINS_WATER)) { FoodType food = EnumUtils.getEnum(FoodType.class, path); MasherBowlTileEntity tileEntity = (MasherBowlTileEntity)worldIn.getTileEntity(pos); assert tileEntity != null; if(tileEntity.addFood(food)) { return ActionResultType.SUCCESS; } } return ActionResultType.PASS; } } I also have 2 classes that store registered blocks and tile entities: public class TileEntitiesList { public static TileEntityType<?> masher_bowl; } public class BlocksList { public static Block masher_bowl; }
  8. Oh ok, that makes sense. I was just concerned because I noticed that it wasn't calling my write function before the chunk was unloaded, and then I'd reload the chunk and my data would be gone. But now I think this is simply due to the fact that my write function isn't properly writing data to the NBT, or I'm not properly reading somehow. I added the super call to my read and write and the problem persists. Looking at some other TileEntities, I assume you need to add the super call to TileEntity#read as well? I updated my code at the top. I could just remember to add new entries to the end, but if I'm gonna be adding a lot, which I may have to if I want to integrate with other mods, that might get messy. But it may be worth it because it's reading/writing less data.
  9. Here is my TileEntity class: import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IStringSerializable; import java.util.Arrays; public class MasherBowlTileEntity extends TileEntity { public enum FoodType implements IStringSerializable { apple, baked_potato, beetroot, bread, carrot, chorus_fruit, dried_kelp, kelp, honey_bottle, melon_slice, potato, poisonous_potato, pumpkin, sweet_berries, nothing; @Override public String getName() { return this.name(); } } private FoodType[] ingredients = new FoodType[4]; public MasherBowlTileEntity(){ super(TileEntitiesList.masher_bowl); clearFoods(); } @Override public void read(CompoundNBT compound) { super.read(compound); int [] arr = compound.getIntArray("ingredients"); System.out.print("reading ingredients: "+ arr[0] + "," + arr[1]+ "," + arr[2]+ "," + arr[3]+ "\n"); for(int i = 0; i < arr.length; i++){ ingredients[i] = FoodType.values()[arr[i]]; } } private int[] foodToIntArray(FoodType[] arr){ int[] result = new int[arr.length]; for(int i = 0; i < arr.length; i++){ result[i] = arr[i].ordinal(); } return result; } @Override public CompoundNBT write(CompoundNBT compound) { super.write(compound); int [] arr = foodToIntArray(ingredients); compound.putIntArray("ingredients", arr); System.out.print("writing ingredients: "+ arr[0] + "," + arr[1]+ "," + arr[2]+ "," + arr[3]+ "\n"); return compound; } public boolean addFood(FoodType food){ for(int i = 0; i < ingredients.length; i++){ if(ingredients[i] == FoodType.nothing){ markDirty(); ingredients[i] = food; return true; } } return false; } public void clearFoods(){ markDirty(); Arrays.fill(ingredients, FoodType.nothing); } public FoodType getIngredient(int index) { return ingredients[index]; } } I'm having 2 issues: 1. I can only get write() to be called by pausing the game, despite me calling markDirty() whenever data is updated. 2. Even if write() was called beforehand, the array gotten in read() is of length 0, which I assume means it couldn't find an NBT matching the key. I know that the array write() is attempting to write has the correct information because the System.out.print call prints the correct information, and the key is correct.
  10. My code was just this assert lightReader != null; assert pos != null; if(lightReader instanceof World){ // misc code never reached }else{ return MaterialColor.WATER.colorValue; } Like I said, not casting the ILightReader worked just fine. I was just curious if it could be cast to a World, and it doesn't seem like it can.
  11. I did that, and it just ended up never getting to the code I wanted it to.
  12. Not casting it worked, but I tried casting it anyway just to see what would happen and it crashed. It gave the error: java.lang.ClassCastException: net.minecraft.client.renderer.chunk.ChunkRenderCache cannot be cast to net.minecraft.world.World
  13. If you're playing a FTB pack, they have their own launcher at https://www.feed-the-beast.com/
  14. My BlockState became too complicated for the values I wanted to feed into my IBlockColor#getColor() implementation. Is there any alternative to getting values from the BlockState, or will I have to use a TER/TESR?
×
×
  • Create New...

Important Information

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