Jump to content

Recommended Posts

Posted (edited)

I have a quick question concerning mob spawners I am generating in "dungeon"-type structures within my mod.

 

   I have created a skeleton spawner in a mod-generated dungeon, and then when I run the code, for some reason the skeletons my mod generates don't ever seem to have supplied random armor, or randomly enchanted bows? I only get "standard" skeletons, with normal, un-enchanted bows.

 

   Do I need to tell my mod's skeleton spawner(s) to do the random armor / enchanted bow generation? I thought this would simply occur automatically, simply due to the way Minecraft handles any such spawners (ie.sometimes  a spawned skeleton would be given an automatic, randomly generated set of gear, NOT the same as the previously generated skeleton).

 

   And, moreover, if in fact I do need to set this up myself (using an / several NBT tag(s), I would imagine?), what do I need to do to produce this random gear effect?

 

   I'm just a little bit confused as to how this works, I guess (sorry if it seems a bit of a noob question :-}

 

   Any help greatly appreciated!

 

   ZTagre.

Edited by ZTagre
Solved / issue closed
Posted

Thanks for the reply, diesieben07!

 

  My code? Okay, but you just might be reading more into my "problem" than I intended!

 

   In my mod, once I have finished generating a dungeon, I have a "list" of locations x,y,z that I wish to place chests, spawners, etc. Suppose that I have the following coord. picked out for just such a generated skeleton spawner:

 

                 int x, y, z;
                String mobName;
                
                // Using the following as a template, you can generate
                // all "on-the-fly" mob spawners with this method!
                // You simply set the x, y and z coords. to the desired
                // world coords. for the spawner, and then call utility
                // method StructureUtils.setSpawnerInWorld(...) with
                // the world, x, y, z, and mob_name params.! - ARG.
                
                x = -179;
                y = 17;
                z = 209;
                mobName = "Skeleton";
                StructureUtils.setSpawnerInWorld(world, x, y, z, mobName);

 

   Now, whether or not the code below is considered good "practice" for placing a spawner into my world or not, this is what I use:

 

    public static void setSpawnerInWorld(World world, int x, int y, int z, String entity_name)
    // **************************************************************
    // A method developed because of the need to generate spawners of
    // specific mobs within our test worlds during Mod development,
    // we found it useful enough to add it to our utility library!
    //
    // More or less "self-explanatory", the method will generate a
    // mob spawner of the mob whose "name string" is passed as the
    // single String param., at the given coords. in the world
    // specified by the "world" param.
    //
    // Some possible mob "name strings":
    //  Blaze
    //  Skeleton
    //  Zombie
    //  Spider
    //  Ozelot
    //  Wolf
    // (just look up the rest - they're easy to find online or in
    // the vanilla MC source...) - ARG.
    // **************************************************************
    {

           BlockHelper.setBlock(world, x, y + 1, z, Blocks.MOB_SPAWNER);
            
           BlockPos pos0 = new BlockPos(x, y + 1, z);
           TileEntityMobSpawner spawner = (TileEntityMobSpawner) world.getTileEntity(pos0);
                                    
           if (spawner != null)
               spawner.getSpawnerBaseLogic().setEntityName(entity_name);
        
    }

 

 

   Please do note that I have used this code VERBATIM to produce skeleton, zombie, and enderman spawners into my maps that all behave exactly as they should! The skeletons actually occasionally generating armor and sometimes enchanted items as well!

 

   But, this time, I am trying to place a spawner into a slightly different surroundings - a tower (of sorts).

 

   The top of the tower is actually at normal ground level (y = 64, I believe), and the tower "body" actually extends DOWN into the ground (a sort of 20-block deep "pit", if you will...). So you would actually be underground when you "discover" this tower that contains both treasure and generated mods. Skeletons are one of the "key" mobs within this structure.
 

   However, like I said in my posted question - this time, for some strange reason, my skeleton spawner will NOT, EVER generate anything but vanilla skeletons, with no armor, and no enchanted items! I just don't understand what has happened here! This exact same code, when it places a skeleton spawner in a different environment, works perfectly well!

 

   So, yeah, I'm just a bit confused here! Same world, same game difficulty! In some cases, "normal" random skeleton generation by the placed spawner, and, in THIS CASE, only "vanilla" skeletons!

 

   I have even manipulated the size of the rooms at the top of the tower, as well as the position of the placed spawner (from inside the stone ground (inset) to suspended above the ground (hanging from the ceiling). The light level (for all rights and purposes) is exactly the same. Nothing changes!

 

   Anything?

 

   ZTagre.

Posted

Wow - so this is a wee bit of a mystery, then eh? I know I'm pretty confused, and so I was hoping that someone just might have had the same experience / problem!

 

   So, we'll break out the old debugger, and take a gander at what's going on, then!

 

   Thanks for giving your time, diesieben07! I as always am much appreciative, and I'll keep you and others up to date on what I find out...

 

   ZTagre.

Posted

Update:

 

   What I'm going to relate here might just seem a bit crazy, but let me just tell you what I found out!

 

   In early development, as I was creating my dungeon (call it my "development" version), I placed it fairly close to my base (which is also just a stone's throw away from my initial spawn point in this world...(sound familiar?).

 

   This dungeon was then used to test all subsequent development. So this was also used to test my mob spawner placement within this dungeon. And, as I have already stated, everything appeared to work "normally" (nothing out of the ordinary). My generated skeleton spawner(s) always functioned as expected (within Minecraft "norms"...).

 

   But, lately, I have begun to generate dungeons that are at a relatively FAR DISTANCE from my base, so that I could make said dungeons both larger, and more realistic. However, this distance also makes it very hard to get back and forth from my base during testing, so I routinely utilize a mod that has both WAYPOINTS and TELEPORTATION. And now, here's the "rub"...

 

   If I place the spawner within the dungeon, and then then quit and save AT MY BASE LOCATION, and then subsequently re-load the saved game, to get back to that dungeon I use teleportation (via this mod I mentioned previously). When I do this, the skeleton spawner behaves badly (as per the problem I have brought up here in this posting...).

 

   BUT, if I quit and save while in the relative location of the dungeon, and do not require teleportation to the dungeon site upon re-load of the game, then the spawner behaves exactly as it should!!!

 

   So, to reiterate: When I quit and save in a location outside the relative location of the dungeon / spawner in question, and then subsequently use a teleporation mod to get back to the dungeon site, the spawner does not behave correctly!  But saving and re-loading while in the general vicinity of the dungeon has the placed spawner(s) working as per design!

 

   While I don't yet understand fully just what is actually causing the problem yet, I know that it is NOT (at least, not entirely) the spawner's fault!

 

   I seems to have something to do with my "overuse" of this teleportation system and the mod that supplies it!

 

   So, for now, this case is closed!

 

   Thanks again, diesieben07!

 

   ZTagre.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • https://mclo.gs/9y5ciD2 anyone ever had this issue?  Internal exception illegal argument exception: unable to fit 3194354 into 3
    • Hoffman Law Recovery helped me recovered my lost funds
    • Hi! I'm trying to add my custom models/textures renderer like this: public class PonyPlayerWrapperRenderer extends EntityRenderer<Player> { // wrapper class under my LivingEntityRenderer class implementation private final PonyPlayerRenderer innerRenderer; private final PonyPlayerRenderer innerSlimRenderer; public PonyPlayerWrapperRenderer(final EntityRendererProvider.Context context) { super(context); System.out.println("creating new PonyPlayerWrapperRenderer"); this.innerRenderer = new PonyPlayerRenderer(context, false); this.innerSlimRenderer = new PonyPlayerRenderer(context, true); } @Override public void render(final Player entity, final float yaw, final float partialTicks, final PoseStack poseStack, final MultiBufferSource bufferSource, final int packedLight) { System.out.println("PonyPlayerWrapperRenderer render: " + entity.toString()); if (entity instanceof AbstractClientPlayer clientPlayer) { if (clientPlayer.getModelName().contains("slim")) { innerSlimRenderer.render(clientPlayer, yaw, partialTicks, poseStack, bufferSource, packedLight); } else { innerRenderer.render(clientPlayer, yaw, partialTicks, poseStack, bufferSource, packedLight); } } } @Override public ResourceLocation getTextureLocation(final Player player) { System.out.println("PonyPlayerWrapperRenderer getTextureLocation"); if (player instanceof AbstractClientPlayer clientPlayer) { return clientPlayer.getSkinTextureLocation(); } System.out.println("player instanceof AbstractClientPlayer is false"); return getDefaultSkin(player.getUUID()); } } public class PonyPlayerRenderer extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> { private final PlayerModel<AbstractClientPlayer> earthModel; private final PlayerModel<AbstractClientPlayer> pegasusModel; private final PlayerModel<AbstractClientPlayer> unicornModel; public PonyPlayerRenderer(final EntityRendererProvider.Context context, final boolean slim) { super( context, slim ? new PonyModelSlim(context.bakeLayer(PonyModelSlim.LAYER_LOCATION)) : new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)), 0.5f ); System.out.println("creating new PonyPlayerRenderer"); this.earthModel = slim ? new PonyModelSlim(context.bakeLayer(PonyModelSlim.LAYER_LOCATION)) : new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)); this.pegasusModel = new PegasusModel(context.bakeLayer(PegasusModel.LAYER_LOCATION)); this.unicornModel = new UnicornModel(context.bakeLayer(UnicornModel.LAYER_LOCATION)); } @Override public void render(final AbstractClientPlayer player, final float entityYaw, final float partialTicks, final PoseStack poseStack, final MultiBufferSource buffer, final int packedLight) { final PonyRace race = player.getCapability(PONY_DATA) .map(data -> ofNullable(data.getRace()).orElse(PonyRace.EARTH)) .orElse(PonyRace.EARTH); this.model = switch (race) { case PEGASUS -> pegasusModel; case UNICORN -> unicornModel; case EARTH -> earthModel; }; super.render(player, entityYaw, partialTicks, poseStack, buffer, packedLight); } @Override public ResourceLocation getTextureLocation(final AbstractClientPlayer player) { final PonyRace race = player.getCapability(PONY_DATA) .map(data -> ofNullable(data.getRace()).orElse(PonyRace.EARTH)) .orElse(PonyRace.EARTH); return switch (race) { case EARTH -> fromNamespaceAndPath(MODID, "textures/entity/earth_pony.png"); case PEGASUS -> fromNamespaceAndPath(MODID, "textures/entity/pegasus.png"); case UNICORN -> fromNamespaceAndPath(MODID, "textures/entity/unicorn.png"); }; } } @Mod.EventBusSubscriber(modid = MODID, bus = MOD, value = CLIENT) public class ClientRenderers { // mod bus render registration config @SubscribeEvent public static void onRegisterLayerDefinitions(final EntityRenderersEvent.RegisterLayerDefinitions event) { event.registerLayerDefinition(PonyModel.LAYER_LOCATION, PonyModel::createBodyLayer); event.registerLayerDefinition(PonyModelSlim.LAYER_LOCATION, PonyModelSlim::createBodyLayer); event.registerLayerDefinition(PegasusModel.LAYER_LOCATION, PegasusModel::createBodyLayer); event.registerLayerDefinition(UnicornModel.LAYER_LOCATION, UnicornModel::createBodyLayer); event.registerLayerDefinition(InnerPonyArmorModel.LAYER_LOCATION, InnerPonyArmorModel::createBodyLayer); event.registerLayerDefinition(OuterPonyArmorModel.LAYER_LOCATION, OuterPonyArmorModel::createBodyLayer); } @SubscribeEvent public static void onRegisterRenderers(final EntityRenderersEvent.RegisterRenderers event) { event.registerEntityRenderer(EntityType.PLAYER, PonyPlayerWrapperRenderer::new); System.out.println("onRegisterRenderers end"); } } Method onRegisterRenderers() is called and I can see it being logged. But when I enter the world, my PonyWrapperRenderer render() method doesn't ever seem to be called. I also tried to put my renderer to EntityRenderDispatcher's playerRenderers via reflection: @Mod.EventBusSubscriber(modid = MODID, bus = MOD, value = CLIENT) public class ClientRenderers { @SubscribeEvent public static void onRegisterLayerDefinitions(final EntityRenderersEvent.RegisterLayerDefinitions event) { event.registerLayerDefinition(PonyModel.LAYER_LOCATION, PonyModel::createBodyLayer); event.registerLayerDefinition(PonyModelSlim.LAYER_LOCATION, PonyModelSlim::createBodyLayer); event.registerLayerDefinition(PegasusModel.LAYER_LOCATION, PegasusModel::createBodyLayer); event.registerLayerDefinition(UnicornModel.LAYER_LOCATION, UnicornModel::createBodyLayer); event.registerLayerDefinition(InnerPonyArmorModel.LAYER_LOCATION, InnerPonyArmorModel::createBodyLayer); event.registerLayerDefinition(OuterPonyArmorModel.LAYER_LOCATION, OuterPonyArmorModel::createBodyLayer); } @SubscribeEvent public static void onClientSetup(final FMLClientSetupEvent event) { event.enqueueWork(() -> { try { final EntityRenderDispatcher dispatcher = Minecraft.getInstance().getEntityRenderDispatcher(); final Field renderersField = getEntityRenderDispatcherField("playerRenderers"); final Field itemInHandRenderer = getEntityRenderDispatcherField("itemInHandRenderer"); @SuppressWarnings("unchecked") final Map<String, EntityRenderer<? extends Player>> playerRenderers = (Map<String, EntityRenderer<? extends Player>>)renderersField.get(dispatcher); final PonyPlayerWrapperRenderer renderer = new PonyPlayerWrapperRenderer( new EntityRendererProvider.Context( dispatcher, Minecraft.getInstance().getItemRenderer(), Minecraft.getInstance().getBlockRenderer(), (ItemInHandRenderer)itemInHandRenderer.get(dispatcher), Minecraft.getInstance().getResourceManager(), Minecraft.getInstance().getEntityModels(), Minecraft.getInstance().font ) ); playerRenderers.put("default", renderer); playerRenderers.put("slim", renderer); System.out.println("Player renderers replaced"); } catch (final Exception e) { throw new RuntimeException("Failed to replace player renderers", e); } }); } private static Field getEntityRenderDispatcherField(final String fieldName) throws NoSuchFieldException { final Field field = EntityRenderDispatcher.class.getDeclaredField(fieldName); field.setAccessible(true); return field; } } But I receive the error before Minecraft Client appears (RuntimeException: Failed to replace player renderers - from ClientRenderers onClientSetup() method - and its cause below): java.lang.IllegalArgumentException: No model for layer anotherlittlepony:earth_pony#main at net.minecraft.client.model.geom.EntityModelSet.bakeLayer(EntityModelSet.java:18) ~[forge-1.20.1-47.4.0_mapped_official_1.20.1-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.renderer.entity.EntityRendererProvider$Context.bakeLayer(EntityRendererProvider.java:69) ~[forge-1.20.1-47.4.0_mapped_official_1.20.1-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at com.thuggeelya.anotherlittlepony.client.renderer.pony.PonyPlayerRenderer.<init>(PonyPlayerRenderer.java:32) ~[main/:?] {re:classloading} at com.thuggeelya.anotherlittlepony.client.renderer.pony.PonyPlayerWrapperRenderer.<init>(PonyPlayerWrapperRenderer.java:24) ~[main/:?] {re:classloading} at com.thuggeelya.anotherlittlepony.client.renderer.ClientRenderers.lambda$onClientSetup$0(ClientRenderers.java:79) ~[main/:?] {re:classloading} ... 33 more Problem appears when EntityRendererProvider context tries to bakeLayer with my model layer location: new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)); // PonyPlayerRenderer.java:32 public class PonyModel extends PlayerModel<AbstractClientPlayer> { // the model class itself public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation( ResourceLocation.fromNamespaceAndPath(MODID, "earth_pony"), "main" ); public PonyModel(final ModelPart root) { super(root, false); } public static LayerDefinition createBodyLayer() { // some CubeListBuilder stuff for model appearance } } Textures PNGs are placed at: resources/assets/[my mod id]/textures/entity. My forge version is 1.20.1. Would appreciate any help.
    • Well, a bit more information about what you're trying to do would be helpful. e.g. why you're trying to use "INVOKE_ASSIGN" instead of "INVOKE". "INVOKE_ASSIGN" calls your code after the "target" is called and its value is stored, if applicable. "INVOKE" calls your code before the target is called. "target" expects a fully qualified name, as per the SpongePowered docs, if that name is going to be remapped (which it will be if your injecting into Minecraft itself and not another mod). For more information on fully qualified names versus canonical names, see the Java specifications. Here's an example of a working "@At" from my own code that targets the "getClosestsVulnerablePlayerToEntity" call inside a mob's logic: @At(value = "INVOKE_ASSIGN", target = "net.minecraft.world.World.getClosestVulnerablePlayerToEntity(Lnet/minecraft/entity/Entity;D)Lnet/minecraft/entity/player/EntityPlayer;") Hope this helps!
    • Ran it one more time just to check, and there's no errors this time on the log??? Log : https://mclo.gs/LnuaAiu I tried allocating more memory to the modpack, around 8000MB and it's still the same; stopping at "LOAD_REGISTRIES". Are some of the mods clashing, maybe? I have no clue what to do LOL
  • Topics

×
×
  • Create New...

Important Information

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