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


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by JimiIT92

  1. I'm facing a strange issue with custom biomes in Forge 1.18. Essentially they do not seem to be generated or be registered at all... This is how I'm registering a biome @Mod.EventBusSubscriber(modid = "test", bus = Mod.EventBusSubscriber.Bus.MOD) public class CommonModEvents { @SubscribeEvent public static void registerOres(FMLCommonSetupEvent event) { event.enqueueWork(BiomeGeneration::registerBiomes); } } public class BiomeGeneration { public static final ResourceKey<Biome> TEST_BIOME = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("test", "test_biome")); public static void registerBiomes() { BiomeDictionary.addTypes(TEST_BIOME, BiomeDictionary.Type.FOREST); BiomeManager.addAdditionalOverworldBiomes(TEST_BIOME); } } And this is the Biome json file. Nothing crazy here, just a Birch Forest json file without Birch trees (just to see if it actually spawns) { "effects": { "mood_sound": { "sound": "minecraft:ambient.cave", "tick_delay": 6000, "block_search_extent": 8, "offset": 2.0 }, "sky_color": 8037887, "fog_color": 12638463, "water_color": 4159204, "water_fog_color": 329011 }, "carvers": { "air": [ "minecraft:cave", "minecraft:cave_extra_underground", "minecraft:canyon" ] }, "features": [ [], [ "minecraft:lake_lava_underground", "minecraft:lake_lava_surface" ], [ "minecraft:amethyst_geode" ], [ "minecraft:monster_room", "minecraft:monster_room_deep" ], [], [], [ "minecraft:ore_dirt", "minecraft:ore_gravel", "minecraft:ore_granite_upper", "minecraft:ore_granite_lower", "minecraft:ore_diorite_upper", "minecraft:ore_diorite_lower", "minecraft:ore_andesite_upper", "minecraft:ore_andesite_lower", "minecraft:ore_tuff", "minecraft:ore_coal_upper", "minecraft:ore_coal_lower", "minecraft:ore_iron_upper", "minecraft:ore_iron_middle", "minecraft:ore_iron_small", "minecraft:ore_gold", "minecraft:ore_gold_lower", "minecraft:ore_redstone", "minecraft:ore_redstone_lower", "minecraft:ore_diamond", "minecraft:ore_diamond_large", "minecraft:ore_diamond_buried", "minecraft:ore_lapis", "minecraft:ore_lapis_buried", "minecraft:ore_copper", "minecraft:underwater_magma", "minecraft:disk_sand", "minecraft:disk_clay", "minecraft:disk_gravel" ], [], [ "minecraft:spring_water", "minecraft:spring_lava" ], [ "minecraft:glow_lichen", "minecraft:forest_flowers", "minecraft:flower_default", "minecraft:patch_grass_forest", "minecraft:brown_mushroom_normal", "minecraft:red_mushroom_normal", "minecraft:patch_sugar_cane", "minecraft:patch_pumpkin" ], [ "minecraft:freeze_top_layer" ] ], "spawners": { "monster": [ { "type": "minecraft:spider", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:zombie", "weight": 95, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:zombie_villager", "weight": 5, "minCount": 1, "maxCount": 1 }, { "type": "minecraft:skeleton", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:creeper", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:slime", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:enderman", "weight": 10, "minCount": 1, "maxCount": 4 }, { "type": "minecraft:witch", "weight": 5, "minCount": 1, "maxCount": 1 } ], "creature": [ { "type": "minecraft:sheep", "weight": 12, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:pig", "weight": 10, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:chicken", "weight": 10, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:cow", "weight": 8, "minCount": 4, "maxCount": 4 } ], "ambient": [ { "type": "minecraft:bat", "weight": 10, "minCount": 8, "maxCount": 8 } ], "axolotls": [], "underground_water_creature": [ { "type": "minecraft:glow_squid", "weight": 10, "minCount": 4, "maxCount": 6 } ], "water_creature": [], "water_ambient": [], "misc": [] }, "spawn_costs": {}, "precipitation": "rain", "temperature": 0.6, "downfall": 0.6, "category": "forest" } If I try to locate the biome using the /locatebiome test:test_biome it says that it can't find the Biome. Also, if I try to generate a single biome world, the custom biome doesn't even show in the biomes list. What I noticed, in comparison to 1.17, is that the BiomeEntry class essentially is ignoring the weight parameter. This is the 1.17 BiomeEntry class public static class BiomeEntry extends WeighedRandom.WeighedRandomItem { private final ResourceKey<Biome> key; public BiomeEntry(ResourceKey<Biome> key, int weight) { super(weight); this.key = key; } public ResourceKey<Biome> getKey() { return this.key; } } And this is the 1.18 one public static class BiomeEntry { private final ResourceKey<Biome> key; public BiomeEntry(ResourceKey<Biome> key, int weight) { this.key = key; } public ResourceKey<Biome> getKey() { return this.key; } } Also, looking at the BiomeManager class, specifically the getAdditionalOverworldBiomes method, which should be used to attach the mod biomes to the vanilla ones, if you try to look for method usages, in 1.18 it appears that this method is unused. This is what IntelliJ shows if I run the "Find usages" command on this method https://imgur.com/a/r0Fvkjp Where in 1.17 this method is called by the OverworldBiomeSource constructor to attach the mod biomes to the already registered ones public OverworldBiomeSource(long p_48590_, boolean p_48591_, boolean p_48592_, Registry<Biome> p_48593_) { super(java.util.stream.Stream.concat(POSSIBLE_BIOMES.stream(), net.minecraftforge.common.BiomeManager.getAdditionalOverworldBiomes().stream()).map((p_48603_) -> { return () -> { return p_48593_.getOrThrow(p_48603_); }; })); //... } So, am I missing something during the creation of a Biome in 1.18 or there's still something missing on this?
  2. Aaah, I see! I saw that I also need to register the Layer inside the EntityRenderersEvent.RegisterLayers event. Now that I registered the layer and moved the listener to the Mod bus is finally showing ๐Ÿ˜ Thank for your tips
  3. Allright, so I got the correct event now, and I'm adding the layer like this @Mod.EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT) public final class LayerRenderSubscriber { @SubscribeEvent(priority = EventPriority.LOW) public static void renderPlayer(final EntityRenderersEvent.AddLayers event) { LivingEntityRenderer<Player, PlayerModel<Player>> renderer = event.getRenderer(EntityType.PLAYER); BlackElytraLayer<Player, PlayerModel<Player>> layer = new BlackElytraLayer<>(renderer, event.getEntityModels()); renderer.addLayer(layer); } } But the Layer doesn't render at all. Even worse, if I start the game in debug mode, a breakpoint into the event doesn't hit, so it seems like the event isn't even fired. Do I need to register something or do something else that I'm missing?
  4. Oh, I see. So I was listening to the wrong event. But now the problem is getting the first parameter correctly, the RenderLayerParent parameter, which I don't see being referenced by the event (sorry but I've never used this event so I don't know exactly where to look)
  5. I'm trying to add a custom layer to the vanilla player rendering. Specifically, I'm trying to create some custom Elytras. I've already extended the vanilla Elytra Layer, and tried to attach it inside the RenderPlayerEvent.Pre event (which I'm not sure if is the right place, I'm using a 1.16.x code base as reference) @SubscribeEvent public static void renderPlayer(final RenderPlayerEvent.Pre event) { Player player = event.getPlayer(); PlayerRenderer renderer = event.getRenderer(); renderer.addLayer(new BlackElytraLayer<>(renderer, ?)); //? is for the missing EntityModelSet parameter } However, the ElytraLayer requires an EntityModelSet as parameter, to bake the Elytra Model public ElytraLayer(RenderLayerParent<T, M> parent, EntityModelSet modelSet) { super(parent); this.elytraModel = new ElytraModel<>(modelSet.bakeLayer(ModelLayers.ELYTRA)); } But inside the event I see nothing that can get me an instance of this varaiable, leading me to bake the Elytra Model as well. So is there any way to get this or do I just have to recreate the entire Elytra model and use that in the custom layer?
  6. As the tile says, is there any way to add or edit requirements for Vanilla Advancements? For instance, let's say I add a new food to the game. I want that food to be counted into the "A balanced diet" advancement, but of course I want to avoid edit the vanilla json file. So is there any way to add this requirement to the advancement without editing it (similar to how you can add or modify Loot to LootTables using GlobalLootModifiers)?
  7. So essentially I need the RegistryObject just for overworld biomes? For instance, if I have a custom dimension or want to add new Biomes to Nether/End I can just register the key and then handle everything via the Json? I assume this excludes features, so if I want my custom feature to be generated inside the Biome I still need to code it like I'm doing now, right? Just I won't need to add it through code in the BiomeLoadingEvent?
  8. Ok, so adding custom features during the BiomeLoadingEvent (essentialy what I already do for flowers/tree generation) solves the issue. However I'm curious to know more about the json Biomes. Where can I find some details about this system? Will this allow me to add biomes to the game without even writing code (so just the Json file)? I looked on the documentation but found nothing about it
  9. The point is that even without adding the CF to a custom Biome the game crashes However, here is how I create the Biome public static Biome volcanicWasteland() { MobSpawnSettings mobSpawnSettings = new MobSpawnSettings.Builder() .addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(EntityType.MAGMA_CUBE, 100, 2, 5)) .build(); BiomeGenerationSettings.Builder biomeBuilder = new BiomeGenerationSettings.Builder(); addDefaultOverworldUnderground(biomeBuilder); biomeBuilder.surfaceBuilder(MwConfiguredSurfaceBuilders.VOLCANIC_WASTELAND) .addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, Features.DELTA) .addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, Features.SPRING_LAVA_DOUBLE) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_DELTA) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.ORE_MAGMA) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_CLOSED_DOUBLE); //Add custom CF biomeBuilder.addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS); var temperature = 10.0F; var ashColor = 0x333333; return new Biome.BiomeBuilder() .precipitation(Biome.Precipitation.NONE) .biomeCategory(Biome.BiomeCategory.DESERT) .depth(0.25F) .scale(0.1F) .temperature(temperature) .downfall(0.0F) .specialEffects( new BiomeSpecialEffects.Builder() .waterColor(ashColor) .waterFogColor(ashColor) .fogColor(ashColor) .foliageColorOverride(ashColor) .grassColorOverride(ashColor) .skyColor(calculateSkyColor(temperature)) .ambientParticle(new AmbientParticleSettings(ParticleTypes.WHITE_ASH, 0.118093334F)) .ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS) .build()) .mobSpawnSettings(mobSpawnSettings) .generationSettings(biomeBuilder.build()) .build(); } which I register on the Biome Registry from the main mod constructor var eventBus = FMLJavaModLoadingContext.get().getModEventBus(); MOD_FEATURES.register(eventBus); MOD_BIOMES.register(eventBus); and here is were I store the Biomes //Registry public static final DeferredRegister<Biome> MOD_BIOMES = DeferredRegister.create(ForgeRegistries.BIOMES, MOD_ID); //Biomes public static final RegistryObject<Biome> VOLCANIC_WASTELAND = register("volcanic_wasteland", BiomeUtils::volcanicWasteland); //Register Biome public static RegistryObject<Biome> register(String name, Supplier<Biome> biomeSupplier) { return REGISTRY.register(name, biomeSupplier); } Finally, during FMLCommonSetupEvent I add the Biome to the BiomeDictionary @SubscribeEvent public static void onCommonSetup(final FMLCommonSetupEvent event) { ... event.enqueueWork(CommonSetupSubscriber::addVolcanicWastelandBiome); } private static void addVolcanicWastelandBiome() { var key = ResourceKey.create(ForgeRegistries.Keys.BIOMES, Objects.requireNonNull(ForgeRegistries.BIOMES).getKey(ModBiomes.VOLCANIC_WASTELAND.get())); BiomeDictionary.addTypes(key, BiomeDictionary.Type.HOT, BiomeDictionary.Type.DRY, BiomeDictionary.Type.WASTELAND, BiomeDictionary.Type.DEAD); BiomeManager.addBiome(BiomeManager.BiomeType.DESERT, new BiomeManager.BiomeEntry(key, 70)); } This is the full debug log I have. I noticed that error is actually thrown by another method (the appleForest method is used to create another mod biome). I guess is called when the Mod feature hasn't been registered yet, so it crashes?
  10. I'm having some troubles creating/attaching a ConfiguredFeature built on top of a modded feature in a modded biome. I had no issues using CF with vanilla features (like Flower placing or Tree placement with mod blocks, for example), however if I want to use my own Feature as well, I get some troubles. What I've done is this: I create the Feature like this // Deferred Register public static final DeferredRegister<Feature<?>> MOD_FEATURES = DeferredRegister.create(ForgeRegistries.FEATURES, MOD_ID); // Feature public static final RegistryObject<Feature<ColumnFeatureConfiguration>> LAVA_ROCK_COLUMNS = register("lava_rock_columns", () -> new LavaRockColumnsFeature(ColumnFeatureConfiguration.CODEC)); //LavaRockColumnsFeature is just a class that extends Feature<ColumnFeatureConfiguration> //to generate basalt columns but with a mod block instead // Register the Feature public static <T extends FeatureConfiguration> RegistryObject<Feature<T>> register(String name, Supplier<Feature<T>> featureSupplier) { return MOD_FEATURES.register(name, featureSupplier); } Then, from the main mod class constructor, I call the register method for the Feature registry var eventBus = FMLJavaModLoadingContext.get().getModEventBus(); MOD_FEATURES.register(eventBus); Next I create my ConfiguredFeatures like this //Generate "Anemone" flowers inside the World public static final ConfiguredFeature<?, ?> ANEMONE = Feature.FLOWER.configured( (new RandomPatchConfiguration.GrassConfigurationBuilder( new SimpleStateProvider(ModBlocks.ANEMONE.get().defaultBlockState()), SimpleBlockPlacer.INSTANCE) ).tries(2).build()) .decorated(Features.Decorators.HEIGHTMAP_SQUARE).count(1); //Generate "Small Lava Rock Columns" in a custom Biome public static final ConfiguredFeature<?, ?> SMALL_LAVA_ROCK_COLUMNS = ModFeatures.LAVA_ROCK_COLUMNS.get() .configured(new ColumnFeatureConfiguration(ConstantInt.of(1), UniformInt.of(1, 4))) .decorated(FeatureDecorator.COUNT_MULTILAYER.configured(new CountConfiguration(4))); Then I register this feature during the FMLCommonSetupEvent by doing this @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public final class CommonSetupSubscriber { @SubscribeEvent public static void onCommonSetup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { registerConfiguredFeatures(); }); } } private static void registerConfiguredFeatures() { Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "anemone"), ModConfiguredFeatures.ANEMONE); Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "small_lava_rock_columns"), ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS); } Even without adding the "Small lava rock" configured feature to the custom Biome, if I run the game, I get this error java.lang.NullPointerException: Registry Object not present: mod_id:lava_rock_columns So I guess the issue is that the ConfiguredFeature is trying to get the Feature from the Registry, but can't find it? So what should be the correct way to register the Feature and/or the Configured Feature?
  11. I've noticed something strange when using commands like /give or /setblock. Essentially the mod blocks and items are kinda ignored by these commands (these two are just an example, but this behaviour happens to all commands in the game). Let me explain: Let's say you have a block in your mod registered as mymod:my_cobblestone_block If you type /give Dev bble, the vanilla Cobblestone block shows in the suggestions list but not the mod blocks. This is because the suggestions look for blocks and items that contains the word you typed in (in this case minecraft:cobblestone contains the word bble) This system only works for mod blocks and items if you type the mod_id first. For example, typing /give Dev mymod:bble will make the my_cobblestone_block appear in the suggestions list. Is there any way to prevent this and make the mod blocks and items appear in the suggestions list even without typing the mod id first?
  12. Alright, so after a whole morning of tries, I finally got it working! Let's say I have this object inside my GLM json { "item": "minecraft:emerald", "chance": 0.0265, "functions": [ { "function": "minecraft:set_count", "count": { "type": "minecraft:uniform", "min": 2.0, "max": 7.0 }, "add": false } ] } where I am saying that the emerald has a 2.65% chacne of being inside the chest loot. But, I want that the stack, if any, must be between 2 and 7 items. Sure I can add my "min" and "max" parameters, but since we already have a function that does this, why not using it? So I added the vanilla set_count function, using the exact same syntax as any vanilla loot table. In the deserializer (the class that extends GlobalLootModifierSerializer) I can read the functions array by doing so var functionsArray = jsonObject.getAsJsonArray("functions"); if(functionsArray != null) { var functions = Deserializers.createFunctionSerializer().create().fromJson(functionsArray, LootItemFunction[].class); } This will return a LootItemFunction array that is the actual list of functions that are specified inside the JSON, correctly deserialized. So we can store these functions and use them when adding the ItemStack to the generated loot, by doing a simple for loop var stack = new ItemStack(item); if(functions != null && !functions.isEmpty()) { functions.forEach(function -> function.apply(stack, context)); } By doing that the function will be applied to the item of the GLM! Of course we are not limited by the set_count, but we can use any vanilla function as we want (I think even custom functions, but I'm not sure about this since I haven't any of these). To correctly serialize said functions, inside the write method, we can use this function Deserializers.createFunctionSerializer().create().toJsonTree(functions) assuming that functions is a variable containing all of the functions previously deserialized
  13. Hi everyone! As the title says, I am wondering if there is a way to use vanilla loot table functions inside a Global Loot Modifier. For instance: I want to add a Sword to the Mineshaft chests and I want this Sword to be randomly enchanted, kinda like vanilla does it to Desert Pyarmid chests or for End Cities. In the first case, this function is called minecraft:enchant_randomly while for End Cities is this one { "function": "minecraft:enchant_with_levels", "levels": { "type": "minecraft:uniform", "min": 20.0, "max": 39.0 }, "treasure": true } Either way, using these functions the Item can sometime be enchanted. How can I make so in a Loot Modifier I can use these functions as well, if is ever possible? I read the doc about Global Item Modifier and of course have seen the GitHub examples. This helped me setting up some Loot Modifiers, which has no issues adding custom items to Vanilla Loot Tables, however I can't seem to find any example or indication about the possibility to use functions inside Loot Modifiers (aside from inserting some custom keywords in the json that if parsed will manually trigger the said function)
  14. Can confirm, I update to the latest version (1.16.3-34.1.16) and it fires
  15. I was saying use the ClientChatReceivedEvent event, but I have a doubt: if a Player send the same exact message what would happen? How can you tell if the message has been sent from a player or not?
  16. Darn... so how would I catch this event to change what is shown? I tried the other sub events as well and they did not get catched as well
  17. I was going for the RenderTooltipEvent, but it looks like this event is not fired when I hover my mouse to an ItemStack. I have this event inside a class @SubscribeEvent public static void onRenderTooltip(final RenderTooltipEvent.Pre event) { if(BundleItemUtils.isBundle(event.getStack())) { //DO STUFF } } which I register during the FMLCommonSetupEvent like this MinecraftForge.EVENT_BUS.register(BundleEvents.class); Any idea on why this doesn't get called?
  18. Ok, I'm slowly understanding how this works. Unfortunately I've never maged the inventory directly for a case like this, where the item stack you are dragging around with you mouse will be modified when you click but not put into the inventory yet. Now I made it kinda work, by essentially doing the same operation both on the client and on the server. I already know this is bad, however I don't know how to optimize this. Plus for some reason is working fine only inside the Player container and Creative Container and other fews. If I am, for example, inside the Furnace Container and left click a Bundle, the Items will be taken out of the Bundle, but the Bundle itself won't be updated, leading to the situation where if you spam the left click you will dupe the items inside the Bundle. I've setup a GitHub repository so you can look up at what exactly is going on, from what I understand it has to do something with the fact that I'm setting the player inventory ItemStack (which is the item stack the player is dragging with its mouse) but if I remove entirely this then it doesn't get synced Here is the repository https://github.com/JimiIT92/BundlesMod Please I'm really lost into this
  19. Ok, so what I'm doing now is this. In the event handle, instead of calling the BundleItemUtils, I send a message to the server BundleResources.NETWORK.sendToServer(new BundleServerMessage(draggedItemStack, Math.max(slot.slotNumber, slot.getSlotIndex()), false)); Which when handled will do this private static void processMessage(BundleServerMessage message, ServerPlayerEntity playerEntity) { Container container = playerEntity.openContainer; Slot slot = container.getSlot(message.slotId); ItemStack slotStack = slot.getStack(); if(message.empty) { BundleItemUtils.emptyBundle(message.bundle, playerEntity, container); } else { BundleItemUtils.addItemStackToBundle(message.bundle, slotStack, playerEntity, container); slot.putStack(slotStack); playerEntity.inventory.setItemStack(message.bundle); } } But I'm still having some quarkiness where Items gets duped now. Do I need to send something to the Client? If so, what should I send to it?
  20. Yes, I've looked at how the renderTooltipFunction works and I was aware that I need to do that while catching the RenderTooltipEvent. What I specifically want to do is to create a custom component that I can then reuse for other Items as well, included vanilla ones, like for example the StringTextComponent. But looking at the classes I haven't seen a function related to how this component is rendered
  21. Ok, so right now I do this @SubscribeEvent(priority = EventPriority.HIGHEST) public static void onMouseReleased(final GuiScreenEvent.MouseReleasedEvent event) { if(!event.isCanceled() && event.getGui() instanceof ContainerScreen<?>) { ContainerScreen<?> containerScreen = (ContainerScreen<?>)event.getGui(); Slot slot = containerScreen.getSlotUnderMouse(); if(slot != null && !(slot instanceof CraftingResultSlot)) { PlayerEntity player = Minecraft.getInstance().player; if(player != null) { ItemStack draggedItemStack = player.inventory.getItemStack(); ItemStack slotStack = slot.getStack(); Container container = containerScreen.getContainer(); if(slot.canTakeStack(player) && slot.isEnabled() && container.canMergeSlot(draggedItemStack, slot) && slot.isItemValid(draggedItemStack) && slot.getHasStack() && event.getButton() == 0 && BundleItemUtils.isBundle(draggedItemStack) && BundleItemUtils.canAddItemStackToBundle(draggedItemStack, slotStack)) { BundleItemUtils.addItemStackToBundle(draggedItemStack, slotStack, player, container); event.setResult(Event.Result.DENY); event.setCanceled(true); } } } } } From what I understand, instead of calling directly BundleItemUtils I have to send a packet to the server with all the informations I need (draggedItemStack, slotStack, player and container) and then call the addItemStackToBundle while being on the server, am I right?
  22. During Minecraft Live we saw how the new Bundles have a new style of tooltip, where item textures are rendered inside the tooltip. So I wonder, is it currently possible to create a custom tooltip that can render the item textures (where the items are taken from the Bundle Item NBT Tags). And how would you create this tooltip and attach to the item, to make it show instead of the default one?
  23. I am attempting to create a mod that adds the new 1.17 Bundles. To do this I listen to the mouse click event on an Inventory slot. Now, inside the Player container everything works fine, if I am in creative mode. However if I use the Bundle when another container is open (for example a Chest), or if the player is just in survival mode, whatever changes I made to the inventory won't be reflected as soon as I close the container or update it somehow. For example, I have this survival inventory I then take the Bundle (the item near the crafting table) and click on the stack of 40 stone. When I click, only 32 items of the stack will go inside the bundle. The other items will remain inside the Inventory As you can see everything is right, but as soon as I click the Bundle again, I got this situation (if I close and open again the Inventory I still see the stone stack been shrinked to This is the method I use to add the Items to the Bundle public static void addItemStackToBundle(ItemStack bundle, ItemStack stack, PlayerEntity player, Container container) { if(!isBundle(bundle) || isFull(bundle) || isBundle(stack)) { return; } ItemStack stackToAdd = stack.copy(); int maxItemsToAdd = bundle.getMaxDamage() - getBundleItemsCount(bundle); stackToAdd.setCount(Math.min(getMaxStackSizeForBundleToInsert(stackToAdd), maxItemsToAdd)); CompoundNBT bundleTag = bundle.getOrCreateTag(); ListNBT items = bundleTag.getList(BundleResources.BUNDLE_ITEMS_LIST_NBT_RESOURCE_LOCATION, Constants.NBT.TAG_COMPOUND); CompoundNBT itemStackNbt = new CompoundNBT(); ItemStack stackFromBundle = getItemStackFor(bundle, stackToAdd.getItem()); int index = getItemStackIndex(bundle, stackFromBundle); if(!stackFromBundle.isEmpty()) { stackToAdd.setCount(Math.min(stackToAdd.getCount(), getMaxStackSizeForBundle(stack) - stackFromBundle.getCount())); } if(index != -1) { stackFromBundle.setCount(stackFromBundle.getCount() + stackToAdd.getCount()); stackFromBundle.write(itemStackNbt); items.remove(index); items.add(index, itemStackNbt); } else { stackToAdd.write(itemStackNbt); items.add(itemStackNbt); } bundleTag.put(BundleResources.BUNDLE_ITEMS_LIST_NBT_RESOURCE_LOCATION, items); bundle.setTag(bundleTag); stack.setCount(stack.getCount() - stackToAdd.getCount()); bundle.setDamage(bundle.getMaxDamage() - getBundleItemsCount(bundle)); container.detectAndSendChanges(); player.playSound(SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 1.0F, 1.0F); } I pass in the Container object for the slot that has been clicked and in the end call the detectAndSendChanges method, which should sync the inventory content between client and server (as the Click event is only fired client side, all I do here won't be visible to the server until I sync). Do I need to send a custom packet to the server to sync the inventory?
  24. Well, in the end I figured out I didn't even need a listener. All I need was to catch the ClickEvent ๐Ÿ˜…
  25. Yes, I know they are just a list. What I want to avoid is using reflection to prepend my listener ๐Ÿ˜…
  • Create New...

Important Information

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