Jump to content

izofar

Members
  • Posts

    52
  • Joined

  • Last visited

Everything posted by izofar

  1. To remove vanilla potion recipes
  2. I am trying to modify the private static final potion brewing recipe list PotionBrewing.POTION_MIXES with access transformers. MCP bot on discord gave me: !mcp -c moj field_185213_a forge-bot BOT — Today at 4:42 PM List of MCP -> Mojmap Mappings (Page 1/1): MC 1.16.5: net/minecraft/world/item/alchemy/PotionBrewing.POTION_MIXES Name: a => field_185213_a => POTION_MIXES Side: BOTH AT: public net.minecraft.potion.PotionBrewing field_185213_a # POTION_MIXES Type: java/util/List Great. So I add public-f net.minecraft.world.item.alchemy.PotionBrewing field_185213_a # POTION_MIXES Then I refresh my gradle project, and the field is still private according to my IDE. Then I notice, the mcp bot gave the field for net.minecraft.potion.PotionBrewing for version 1.16.5, which makes sense since that's where it was before. How do I get the obfuscated fields for 1.18? Do these change each version?
  3. I got this from the link above, which says: If these are not the valid names, then what are?
  4. In 1.16, LootModifierManager#deserializeModifier read: private IGlobalLootModifier deserializeModifier(ResourceLocation location, JsonElement element) { if (!element.isJsonObject()) return null; JsonObject object = element.getAsJsonObject(); ILootCondition[] lootConditions = GSON_INSTANCE.fromJson(object.get("conditions"), ILootCondition[].class); // For backward compatibility with the initial implementation, fall back to using the location as the type. // TODO: Remove fallback in 1.16 ResourceLocation serializer = location; if (object.has("type")) { serializer = new ResourceLocation(JSONUtils.getAsString(object, "type")); } return ForgeRegistries.LOOT_MODIFIER_SERIALIZERS.getValue(serializer).read(location, object, lootConditions); } Note the if(object.has(type")){} block, which is lacking from the 1.18 version of the class: private IGlobalLootModifier deserializeModifier(ResourceLocation location, JsonElement element) { if (!element.isJsonObject()) return null; JsonObject object = element.getAsJsonObject(); LootItemCondition[] lootConditions = GSON_INSTANCE.fromJson(object.get("conditions"), LootItemCondition[].class); ResourceLocation serializer = new ResourceLocation(GsonHelper.getAsString(object, "type")); return ForgeRegistries.LOOT_MODIFIER_SERIALIZERS.getValue(serializer).read(location, object, lootConditions); } So, the "value" tag is required now for loot modifiers... fine. I added this to my loot modifer json files when I kept getting NullPointerExceptions. But when I use a valid "value" tag I get: [15:27:02] [Render thread/ERROR]: Couldn't parse loot modifier examplemod:add_structure_loot java.lang.NullPointerException: Cannot invoke "net.minecraftforge.common.loot.GlobalLootModifierSerializer.read(net.minecraft.resources.ResourceLocation, com.google.gson.JsonObject, net.minecraft.world.level.storage.loot.predicates.LootItemCondition[])" because the return value of "net.minecraftforge.registries.IForgeRegistry.getValue(net.minecraft.resources.ResourceLocation)" is null at net.minecraftforge.common.loot.LootModifierManager.deserializeModifier(LootModifierManager.java:133) ~[forge-1.18-38.0.14_mapped_official_1.18-recomp.jar%2376%2382!:?] at net.minecraftforge.common.loot.LootModifierManager.lambda$apply$0(LootModifierManager.java:115) ~[forge-1.18-38.0.14_mapped_official_1.18-recomp.jar%2376%2382!:?] at java.util.ArrayList.forEach(ArrayList.java:1511) ~[?:?] at net.minecraftforge.common.loot.LootModifierManager.apply(LootModifierManager.java:113) ~[forge-1.18-38.0.14_mapped_official_1.18-recomp.jar%2376%2382!:?] at net.minecraftforge.common.loot.LootModifierManager.apply(LootModifierManager.java:54) ~[forge-1.18-38.0.14_mapped_official_1.18-recomp.jar%2376%2382!:?] My json file is: { "type": "chest", "conditions": [ { "condition": "forge:loot_table_id", "loot_table_id": "examplemod:chests/modstructure" } ] } I tried printing the contents of ForgeRegistries.LOOT_MODIFIER_SERIALIZERS to know which keys I can use, but got: [15:26:13] [modloading-worker-0/INFO]: Printing LOOT_MODIFER_SERIALIZERS [15:26:13] [modloading-worker-0/INFO]: Printed LOOT_MODIFER_SERIALIZERS Is this a bug, given 1.18 is new, or am I not using these classes right?
  5. I have the following subscribe event in my StructureSpawnHandler.java: @SubscribeEvent public static void onStructureSpawnListGather(StructureSpawnListGatherEvent event) { if(event.getStructure() instanceof ShipwreckStructure) { ExampleMod.LOGGER.info("\n======\n Found Shipwreck, Adding Drowned\n======\n"); event.addEntitySpawn(EntityClassification.MONSTER, new MobSpawnInfo.Spawners(EntityType.DROWNED, 100, 4, 4)); } } And I register it as follows in a static block, with my other subscribe class registers: MinecraftForge.EVENT_BUS.register(StructureSpawnHandler.class); However, Drowned's do not appear to spawn in shipwrecks when I load new worlds. Why might this be? I've read the Forge classes regarding the StructureSpawnListGatherEvent class, and the above should achieve my desired behavior.
  6. Since all I'm basically doing with the subclass is storing a "health" field, is storing this as an NBT in the spawner TE that already exists feasible (using special spawn events and getting the spawner TE that way)?
  7. Thank you both... as for overriding spawners, if I want each spawner to have its own health, how can I make my modded spawner TE a subclass of the vanilla spawner TE, but maintain the mappings by passing the modded TE type through to the TileEntity super-superclass?
  8. Currently, I have a init package with my ModBlocks, ModItems, ModEntityTypes, etc. abstract classes that initialize the registry objects as class fields. Does it suffice to use @ObjectHolder("modid") above the class name in each class? My runClient has worked so far without these annotations... are these necessary for build, then? All of my registry objects are currently public static. Should I use final on all objects? Also, regarding the original topic, I updated my last post with the inheritance issue I am running into.
  9. Check your entity renderer. Did you make a custom model? Did you properly place your textures in the resources?
  10. I plan to move to deferred registries when I port to 1.17, but I am currently working with the registry events approach. My declaration is: public static TileEntityType<LimitedMobSpawnerTileEntity> LIMITED_MOB_SPAWNER = (TileEntityType<LimitedMobSpawnerTileEntity>)TileEntityType.Builder.of(LimitedMobSpawnerTileEntity::new, ModBlocks.LIMITED_SPAWNER).build(null).setRegistryName("mob_spawner"); In which I register it here: @SubscribeEvent public static void onTileEntitiesRegistry(final RegistryEvent.Register<TileEntityType<?>> tileEntityRegistryEvent) { tileEntityRegistryEvent.getRegistry().registerAll( ModTileEntityTypes.LIMITED_MOB_SPAWNER ); } EDIT: Using the above code, I just get a bunch of empty spawners. When I change the TE registration to "minecraft:mob_spawner" then I get the mapping error again. I think this is closer to what I want, but I may be missing a step. Looking at the mapping error I get, I traced it to my TileEntity#save override, in which the error comes from the check: private CompoundNBT saveMetadata(CompoundNBT p_189516_1_) { ResourceLocation resourcelocation = TileEntityType.getKey(this.getType()); if (resourcelocation == null) { throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!"); } else { ... return p_189516_1_; } } The TileEntityType.getKey method uses depreciated methods, so I'm not sure how to bug fix that, but I believe it is just looking for the name to which I registered the TE. EDIT: I figured out that because my LimitedSpawnerTileEntity was extending SpawnerTileEntity, that the constructor was passing TileEntityType.MOB_SPAWNER to TileEntity through super, even thought I should have passed ModTileEntityType.LIMITED_MOB_SPAWNER. Once I did that, and removed the SpawnerTileEntity extension and extended TileEntity directly, the mapping was resolved. I still have an issue with modifying the existing spawner behavior, because now when dungeons feature checks if the spawner is an instance of SpawnerTileEntity, it returns false. I know that Java inheritence doesn't allow for a way to access the super of the super (intending to pass the modded TE type instead), how else should I best do this?
  11. You're in luck! Kaupenjoe just made an entity tutorial today! Entity Spawn Eggs (13:23) Entities Spawning in World (20:49)
  12. Update: I resolved the mapping issue by registering with .setRegistryName("mob_spawner") instead of .setRegistryName("minecraft", "mob_spawner"). I still get the following errors, and the spawner blocks that spawn are empty: [15:26:03] [Render thread/WARN] [minecraft/ClientPlayNetHandler]: Received passengers for unknown entity [15:26:03] [Server thread/WARN] [minecraft/TileEntity]: Block entity invalid: minecraft:mob_spawner @ BlockPos{x=651, y=69, z=-10735} I've tracked down that the TileEntity messages comes from isValid(), which checks if it is in the Set of valid blocks, determined by: public TileEntityType(Supplier<? extends T> p_i51497_1_, Set<Block> p_i51497_2_, Type<?> p_i51497_3_) { this.factory = p_i51497_1_; this.validBlocks = p_i51497_2_; this.dataType = p_i51497_3_; } But, shouldn't this be handled by the TileEntityType registry?
  13. I've created my own spawner block, called LimitedSpawnerBlock (extending SpawnerBlock), which returns a LimitedMobSpawnerTileEntity (extending MobSpawnerTileEntity) upon calling the overriden LimitedSpawnerBlock#createTileEntity, which owns a LimitedAbstractSpawner (extending AbstractSpawner)--- set up just like the Vanilla code... My goal is for the spawner block to break after so many spawns (like how RLCraft spawners have health). The LimitedMobSpawnerTileEntity stores health, which decrements on spawn, and calls for the LimitedSpawnerBlock to be deleted from the world when health reaches zero. I've registered the LimitedSpawnerBlock as "minecraft:spawner" and the TileEntityType<LimitedMobSpawnerTileEntity> as "minecraft:mob_spawner". I've read the docs on tile entities and yet get this error, crashing my game when I place a spawner, and not loading chunks that should have a spawner: This is my LimitedMobSpawnerTileEntity class: I'm not sure what is wrong with the mapping?
  14. I am making a modded armor item that replaces itself with another tier of armor on break. The replacement tier is used to craft the modded armor. I want the replacement armor to have the same durability as the ingredient did when it was used in crafting the modded armor. Is there a way to get the damage value in the json? Do I have to mod my own recipe class? Where would I store this damage value, in preparation for break, a modded itemstack class? In addition, I want the durability of the armor on crafting to be proportional to that of the durability of of the ingredient. Currently, the modded armor has less durability, but is stronger than the ingredient. So, crafting with an almost-broken ingredient gives negative durability to the modded armor. Not sure the best way to approach this, thanks!
  15. I may have posted this prematurely... I came across the WorldTickEvent hook through which I can access the ServerWorld. I'd still appreciate any feedback from more knowledgeable modders... would my implementation with WorldTickEvent be equivalent according to my specification in my original post? Otherwise, I hope this is useful reference to anyone experiencing the same problem.
  16. So I am trying to invoke a custom siege (rather than a zombie siege). I want this event to be independent of zombie sieges (ruling out cancelling the zombie siege event hook). The following code in ServerWorld#tickCustomSpawners loops through the ISpecialSpawners, one of which is a net.minecraft.village.VillageSiege: public void tickCustomSpawners(boolean p_241123_1_, boolean p_241123_2_) { for(ISpecialSpawner ispecialspawner : this.customSpawners) { ispecialspawner.tick(this, p_241123_1_, p_241123_2_); } } I've written my own Siege class... almost identical to VillageSiege for now... and I want it to tick on the ServerWorld with siegeObject.tick(serverWorld, bool1, bool2). However, I can't access the ServerWorld of a ServerTickEvent. Is there a static ServerWorld I can access for my purposes? Or is there a better event hook I can use that will offer up the ServerWorld object?
  17. The Chunk#isLoaded seems to be depreciated, nor is there a ChunkLoader#chunkExists (my research)... what's the new way of doing this? The Chunk#loaded field is private, and the Chunk#getStatus method always returns ChunkStatus.FULL... I can get the chunk with entity.level.getChunk(entity.getBlockPosition()), but what then? Must I use reflection for this? Surely there's a cleaner way. What was previously isChunkLoaded (which Jabelar said World#isAreaLoaded utilizes) seems to be hasChunksAt, which is marked depreciated. Any guidance on this?
  18. Is there an easier way to do this? How would the iron golem have spawned in the first place without chunk deadlocks? Is it easier to modify the villager behavior to spawn the modded entity instead?
  19. Goal My goal is to replace naturally spawning iron golems with my modded clay golems, but still allowing for players to build their own iron golems. I have the following SubscribeEvent: Code @SubscribeEvent public static void onIronGolemJoinWorld(EntityJoinWorldEvent event) { if(event.getEntity() instanceof IronGolemEntity) { if(event.getWorld() instanceof ServerWorld) { IronGolemEntity entity = (IronGolemEntity) event.getEntity(); ServerWorld world = (ServerWorld)event.getWorld(); if(!entity.isPlayerCreated()) { ExampleMod.LOGGER.info("Iron Golem Found!"); ModEntities.CLAY_GOLEM.spawn(world, null, null, entity.blockPosition(), SpawnReason.MOB_SUMMONED, false, false); ExampleMod.LOGGER.info("Spawned Clay Golem"); } } event.setCanceled(true); ExampleMod.LOGGER.info("Removed Iron Golem"); } } Context I Hope This Isn't a Duplicate Question, I have read the link but still do not understand what I've done wrong. I have read the vanilla code and understand that in order to call the private World#addEntity, I must call ServerWorld#addFreshEntity (true for spawning golems with pumpkins, and silverfish blocks, etc.). Alternatively, spawn eggs call EntityType<?>#spawn, but check that the world parameter is a ServerWorld. The result of the code above is the same as when I use: ClayGolemEntity claygolementity = ModEntities.CLAY_GOLEM.create(world); ExampleMod.LOGGER.info("Created Clay Golem"); claygolementity.moveTo(entity.position()); ExampleMod.LOGGER.info("Moved Clay Golem"); world.addFreshEntity(claygolementity); ExampleMod.LOGGER.info("Spawned Clay Golem"); Results My issue is that the following occurs: (1) using /summon examplemod:iron_golem spawns in a clay golem. Not ideal, but I'm fine with this at the moment. (2) Constructing Iron Golems constructs and iron golem, as intended (3) Any naturally spawning golems in villages lags out the game to the point of needing to force quit. (4) using /summon to spawn an iron golem (with the event.canceled(true) commented out) and then reloading the world lags out as well. The last print statement is either "Iron Golem Found" as in the first code example, or "Moved Clay Golem" as in the second code example. I appreciate the help. I haven't yet been able to spawn an entity in the world in code yet.
  20. The IForgeItem method ends up being called in the following snippet by makesPiglingsNeutral: public static boolean isWearingGold(LivingEntity p_234460_0_) { for(ItemStack itemstack : p_234460_0_.getArmorSlots()) { Item item = itemstack.getItem(); if (itemstack.makesPiglinsNeutral(p_234460_0_)) { return true; } } return false; } And the default IForgeItemStack method is: default boolean makesPiglinsNeutral(LivingEntity wearer) { return getStack().getItem().makesPiglinsNeutral(getStack(), wearer); } Will getItem().makesPiglingsNeutral return my overridden method? Or the default, since getItem() will return type Item rather than my ModdedArmorItem class?
  21. Part 1) I want to add an armor material that piglins won't attack. I've traced a single line of code... if only I could modify! In IForgeItem#makesPiglinsNeutral, the input is checked that it is of gold material. How do I add my custom Armor material to this? Do I need reflection, or does forge allow an easier way to achieve/override this? This method is called by IForgeItemStack#makesPiglinsNeutral, which is called by entity.monster.piglin.PiglinTasks#isWearingGold, called by PiglinMobSensor#doTick to update MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD Part 2) I want to extend this behavior to piglin brutes. This likely requires an exponentially more difficult workaround. Any insight to this, and generally overriding vanilla mob features that aren't represented in Forge events?
  22. I'm familiar with generics, just not its use in function definitions. I appreciate your patience. I at first failed to notice that this is a Java-specific concept not attributable to Forge. I apologize for the Java questions. Thank you for your help.
×
×
  • Create New...

Important Information

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