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

urbanxx001

Members
  • Posts

    181
  • Joined

  • Last visited

Posts posted by urbanxx001

  1. 1 hour ago, Draco18s said:

    Why does your custom condition live in the vanilla namespace?

    For some reason I was under the impression it would only work there, but you're right it works under the mod space. I did some more testing and it seems it's a problem with the modifier itself after changing something last minute. I'll mark the thread as finished for now. Thanks for the advice though.

    Edit: I'm an idiot the modifier works I completely forgot I added a condition where certain items were required to make the tools function. I'm losing it lol

  2. As the title says, everything runs perfectly in dev, but after building the mod and running it, my global loot modifiers don't work. No errors show in the log so I'm not sure what the issue is. I'm certain it's not my custom loot conditions (registered under the minecraft namespace), since I use vanilla conditions as well and those don't work. My global_loot_modifier is located in data/forge/loot_modifiers/(file):

    Spoiler
    {
      "replace": false,
      "entries": [
        "mod_id:my_modifier1",
        "mod_id:my_modifier2",
        "mod_id:my_modifier3"
      ]
    }

    And the modifiers are in data/mod_id/loot_modifiers/(file):

    Spoiler
    {
      "type": "mod_id:my_modifier",
      "conditions": [
        {
          "condition": "minecraft:match_tool_and_entity", //custom condition
          "item": {
            "tag": "mod_id:my_tools"
          },
          "entity": "this"
        }
      ]
    }

    Any help is appreciated.

  3. I have a loot modifier that updates all loot tables to drop specific items when using certain tools. Or at least I thought it did. It works on blocks, but not for entities. However I've tested it with the condition "killed_by_player" and that works for entities, the problem is testing these conditions together fails:

    Spoiler
    {
      "type": "mod_id:my_modifier",
      "conditions": [
        {
          "condition": "minecraft:match_tool",
          "predicate": {
            "tag": "mod_id:my_tools"
          }
        },
        {
          "condition": "minecraft:killed_by_player"
        }
      ]
    }

    So then I tried creating a custom ILootCondition, which registered fine but still failed:

    Spoiler
    public class MatchToolKilledByPlayer implements ILootCondition {
        private final ItemPredicate predicate;
    
        public MatchToolKilledByPlayer(ItemPredicate predicate) {
            this.predicate = predicate;
        }
    
        public LootConditionType getType() {
            return new LootConditionType(new MatchToolKilledByPlayer.Serializer());
        }
    
        public Set<LootParameter<?>> getReferencedContextParams() {
            return ImmutableSet.of(LootParameters.TOOL, LootParameters.LAST_DAMAGE_PLAYER);
        }
    
        public boolean test(LootContext p_test_1_) {
            ItemStack itemstack = p_test_1_.getParamOrNull(LootParameters.TOOL);
            return itemstack != null && this.predicate.matches(itemstack) && p_test_1_.hasParam(LootParameters.LAST_DAMAGE_PLAYER);
        }
    
        public static class Serializer implements ILootSerializer<MatchToolKilledByPlayer> {
            public void serialize(JsonObject p_230424_1_, MatchToolKilledByPlayer p_230424_2_, JsonSerializationContext p_230424_3_) {
                p_230424_1_.add("predicate", p_230424_2_.predicate.serializeToJson());
            }
    
            public MatchToolKilledByPlayer deserialize(JsonObject p_230423_1_, JsonDeserializationContext p_230423_2_) {
                ItemPredicate predicate = ItemPredicate.fromJson(p_230423_1_.get("predicate"));
                return new MatchToolKilledByPlayer(predicate);
            }
        }
    }

     

    If anyone has advice I'd be very appreciative.

  4. As the title says, I was wondering what the updated method/process for addScheduledTask is. I need this for an event similar to:

    @SubscribeEvent
    public void onEntityJoin(final EntityJoinWorldEvent event) {
    	Minecraft.getInstance() //(not recognized)--> .addScheduledTask(new Runnable() {
    	    @Override
    	    public void run() { }
    	});
    }

    For the FML setup event I've used:

    event.enqueueWork(() -> { }

    But I'm not sure what's required for a simple event. The context for this is collecting what language the client is using and then sending a packet to sync with the server. But the packet must be delayed or it fails in this event.

    Edit: Actually I can do the same thing when the player loads a container needing it. So the event's probably unnecessary

  5. 41 minutes ago, 8iggy said:

    Thanks! I'm going to test this but I'm still having some errors with other stuff. If it's ok with you can I send a message here if I have anymore issues?

    Of course this is your thread and we're here to help you.

    If the place you're trying to access the items is a part of the inventory object (the block, tile entity, container, etc. classes) then it's easier. But if you're still in the process of creating your inventory, I'd suggest any of the following:

    -Forge docs on Tile Entities

    -Minecraft By Example topics. 

    -Examine the source code for objects like Chests.

    38 minutes ago, 8iggy said:

     I figured out how to do it all but don't know how to get an instance of a server menu/inventory.

    Outside of block/TE/container, an easy way is the player's containerMenu value that I mentioned before, which is whatever menu is currently open:

    Container container = player.containerMenu
  6. 15 hours ago, 8iggy said:

    Thanks! In The ModPacketHandler Class. What Is Main? If It's My Main Class getLocation Isn't A Method In It.

    Sorry, yes Luis is right it's just a helper function for resourcelocation:

    public static ResourceLocation getLocation(String name) {
            return new ResourceLocation(MOD_ID, name);
        }

    As he and diesieben said though, if it's a simple problem like calling openGui and registering the screen, then packets are unnecessary, but you need to describe it in more detail. 

  7. 42 minutes ago, 8iggy said:

    So I put It into my code and it seems like the class PacketBuffer doesn't have a method called write/readUtf. I'm currently using 1.16.5 forge. And I also don't know how to use the class.

    The inputs are just a template- in this case it's two strings, but they can be ints, chars, etc. or none at all, depending if you need to initially send info across sides. I'd suggest reading Forge's documentation on packets first if you haven't used them before: 
    Forge Docs Networking

    You usually send the packet by invoking handler methods:

    ModPacketHandler.sendToServer(new C2SPacketForContainer(input1, input2));

    Where the handler class has packet registration and the methods:

    Spoiler
    public class ModPacketHandler {
        public static int networkId = 0;
    
        private static final String NETWORK_PROTOCOL_VERSION = "1";
        public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel(
                Main.getLocation("main"),
                () -> NETWORK_PROTOCOL_VERSION,
                NETWORK_PROTOCOL_VERSION::equals,
                NETWORK_PROTOCOL_VERSION::equals
        );
    
        public static void registerC2SPackets() {
            CHANNEL.registerMessage(networkId++,
                    C2SPacketForContainer.class,
                    C2SPacketForContainer::encode,
                    C2SPacketForContainer::decode,
                    C2SPacketForContainer::handle,
                    Optional.of(NetworkDirection.PLAY_TO_SERVER)
            );
        }
    
        public static void registerS2CPackets() {
            CHANNEL.registerMessage(networkId++,
                    S2CPacketForContainer.class,
                    S2CPacketForContainer::encode,
                    S2CPacketForContainer::decode,
                    S2CPacketForContainer::handle,
                    Optional.of(NetworkDirection.PLAY_TO_CLIENT)
            );
        };
    
    	// The only C2S Method
    
        /**
         * Sends a packet to the server
         * @param msg  Packet to send
         */
        public static void sendToServer(Object msg) {
            CHANNEL.sendToServer(msg);
        }
    
    	// Multiple S2C Methods
    
        /**
         * Sends a packet to a player
         * @param msg     Packet to send
         * @param player  Player to send to
         */
        public static void sendToClient(Object msg, ServerPlayerEntity player) {
            if (!(player instanceof FakePlayer)) {
                CHANNEL.sendTo(msg, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
            }
        }
    
        /**
         * Sends a packet to players tracking an entity. For tile entities, use chunk or all method instead.
         * @param msg     Packet to send
         * @param entity  Entity being tracked
         */
        public static void sendToClientsTrackingEntity(Object msg, Entity entity) {
            CHANNEL.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), msg);
        }
    
        /**
         * Sends a packet to the sender and players tracking an entity. For tile entities, use chunk or all method instead.
         * @param msg     Packet to send
         * @param entity  Entity being tracked
         */
        public static void sendToClientAndClientsTrackingEntity(Object msg, Entity entity) {
            CHANNEL.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity), msg);
        }
    
        /**
         * Sends a packet to players within a chunk at a position
         * @param msg          Packet to send
         * @param serverWorld  World instance
         * @param pos          Position within chunk
         */
        public static void sendToClientsTrackingChunk(Object msg, ServerWorld serverWorld, BlockPos pos) {
            Chunk chunk = serverWorld.getChunkAt(pos);
            CHANNEL.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), msg);
        }
    
        /**
         * Sends a packet to all players
         * @param msg  Packet to send
         */
        public static void sendToAllClients(Object msg) {
            CHANNEL.send(PacketDistributor.ALL.noArg(), msg);
        }
    
    }

     

    The register methods are called in common setup.

    Spoiler
     private static void commonSetup(FMLCommonSetupEvent event) {
            event.enqueueWork(() -> {
                ModPacketHandler.registerC2SPackets();
                ModPacketHandler.registerS2CPackets();
            });
    }

     

  8. To begin where are you trying to access info for the container? From the server or client? If it's the latter you'll need to send a C2S packet. Then the easiest way to collect info is when the player opens the inventory, since they have a containerMenu variable. The packet would look something like:

     Spoiler
    public class C2SPacketForContainer {
        private final String input1;
        private final String input2;
    
        public C2SPacketForContainer(String input1, String input2) {
            this.input1 = input1;
            this.input2 = input2;
        }
        public C2SPacketForContainer(PacketBuffer packetBuffer) {
            input1 = packetBuffer.readUtf();
            input2 = packetBuffer.readUtf();
        }
    
        public void encode(PacketBuffer packetBuffer) {
            packetBuffer.writeUtf(input1);
            packetBuffer.writeUtf(input2);
        }
    
        public static C2SPacketForContainer decode(PacketBuffer packetBuffer) {
            return new C2SPacketForContainer(packetBuffer.readUtf(), packetBuffer.readUtf());
        }
    
        public void handle(Supplier<NetworkEvent.Context> supplier) {
            NetworkEvent.Context context = supplier.get();
            context.enqueueWork(() -> {
                ServerPlayerEntity player = context.getSender();
                if (player != null) {
                    Container container = player.containerMenu;
                    if (container instanceof MyContainer) {
                        MyContainer menu = (MyContainer) container;
                        (do stuff)
                    }
                }
            });
            context.setPacketHandled(true);
        }
    }

     

  9. So I'm nearly finished with a version of my mod and, although I haven't done mapping changes in awhile, I'm confident that I have the correct MCP name so that an instance of reflection runs properly. However, the new method name isn't recognized during load in the real environment (I'm aware it needs to be changed back to run in dev). I cross-referenced both the output.srg as well as a Discord bot and they tell me that:

    func_221052_a    in     PointOfInterestType.class       should be       registerBlockStates

    Attached is the relevant class and log file. Any help is appreciated.

    Loading Output Log

    Villager Util class:

    Spoiler
    import com.google.common.collect.ImmutableSet;
    import net.minecraft.block.*;
    import net.minecraft.entity.merchant.villager.VillagerProfession;
    import net.minecraft.item.Item;
    import net.minecraft.util.SoundEvent;
    import net.minecraft.village.PointOfInterestType;
    import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
    
    import javax.annotation.Nullable;
    import java.lang.reflect.*;
    import java.util.Set;
    
    public class VillagerUtil {
        private static Method blockStatesInjector;
        
        static {
            VillagerUtil.blockStatesInjector = ObfuscationReflectionHelper.findMethod(PointOfInterestType.class, "registerBlockStates", PointOfInterestType.class);
        }
        //func_221052_a should be registerBlockStates?
        
        public static Set<BlockState> getAllStates(Block block) {
            return ImmutableSet.copyOf(block.getStateDefinition().getPossibleStates());
        }
        
        public static void fixPOITypeBlockStates(PointOfInterestType poiType) {
            try {
                VillagerUtil.blockStatesInjector.invoke(null, poiType);
            }
            catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        
        public static PointOfInterestType pointOfInterestType(String p1, Set<BlockState> p2, int p3, int p4) {
            try {
                //Constructor<PointOfInterestType> c = (Constructor<PointOfInterestType>)PointOfInterestType.class.getDeclaredConstructors()[1];
                Constructor<PointOfInterestType> c = PointOfInterestType.class.getDeclaredConstructor(String.class, Set.class, Integer.TYPE, Integer.TYPE);
                c.setAccessible(true);
                return c.newInstance(p1, p2, p3, p4);
            }
            catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        public static VillagerProfession villagerProfession(String p1, PointOfInterestType p2, ImmutableSet<Item> p3, ImmutableSet<Block> p4, @Nullable SoundEvent p5) {
            try {
                Constructor<VillagerProfession> c = VillagerProfession.class.getDeclaredConstructor(String.class, PointOfInterestType.class, ImmutableSet.class, ImmutableSet.class, SoundEvent.class);
                c.setAccessible(true);
                return c.newInstance(p1, p2, p3, p4, p5);
            }
            catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

     

     

  10. 1 minute ago, vemerion said:

    You can't really have an instance field like extraArmor in item classes, since items are singleton and every stack will share the same item. This means that for example if one player uses the item and changes the extraArmor field, it will also change for all other players that also have that item.

    Ah ok. So I should store it in NBT instead?

  11. Here's the class for attempt 1. For attempt 2 I've also tried assigning random UUID's and/or random modifier names for each item instance, but they still remain linked.

    Spoiler
    
    
    
    package com.author.my_mod.group.items;
    
    import com.google.common.collect.*;
    import net.minecraft.entity.ai.attributes.*;
    import net.minecraft.entity.player.PlayerEntity;
    import net.minecraft.inventory.EquipmentSlotType;
    import net.minecraft.item.*;
    import net.minecraft.util.*;
    import net.minecraft.world.World;
    import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
    
    import java.util.*;
    
    public class MyItem extends ArmorItem {
    	private final EquipmentSlotType slot;
    	public int extraArmor = 0;
    
    	public MyItem(IArmorMaterial material, EquipmentSlotType slot, Properties properties) {
    		super(material, slot, properties);
    		this.slot = slot;
    	}
    
    	public static<K, V> ListMultimap<K, V> toMutableMultimap(Multimap<K, V> original) {
    		ListMultimap<K, V> copy = ArrayListMultimap.create();
    		copy.putAll(original);
    		return copy;
    	}
    
    	public static<K, V> ImmutableMultimap<K, V> toImmutableMultimap(ListMultimap<K, V> original) {
    		return new ImmutableMultimap.Builder<K, V>().putAll(original).build();
    	}
    
    	@Override
    	public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack) {
    		Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack);
    		ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap);
    
    		Item item = stack.getItem();
    		if (item instanceof MyItem && slot == this.slot) {
    			UUID[] uuid_arr = ObfuscationReflectionHelper.getPrivateValue(ArmorItem.class, (ArmorItem) item, "ARMOR_MODIFIER_UUID_PER_SLOT");
    			if (uuid_arr != null) {
    				MyItem myItem = (MyItem) item;
    				UUID uuid = uuid_arr[slot.getIndex()];
    				this.replaceModifier(mutableMultimap, Attributes.ARMOR, uuid, myItem.extraArmor);
    			}
    		}
    		return toImmutableMultimap(mutableMultimap);
    	}
    
    	private void replaceModifier(ListMultimap<Attribute, AttributeModifier> multimap, Attribute attribute, UUID id, double newValue) {
    		final Collection<AttributeModifier> modifiers = multimap.get(attribute);
    		final Optional<AttributeModifier> modifierOptional = modifiers.stream().filter(attributeModifier -> attributeModifier.getId().equals(id)).findFirst();
    
    		if (modifierOptional.isPresent()) {
    			final AttributeModifier modifier = modifierOptional.get();
    			modifiers.remove(modifier);
    			modifiers.add(new AttributeModifier(modifier.getId(), modifier.getName(), modifier.getAmount() + newValue, modifier.getOperation()));
    		}
    	}
    
    	@Override
    	public ActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
    		final ItemStack stack = player.getItemInHand(hand);
    		if (!world.isClientSide()) {
    			this.extraArmor++;
    			if (this.extraArmor > 3) {
    				this.extraArmor = 0;
    			}
    		}
    		return new ActionResult<>(ActionResultType.CONSUME, stack);
    	}
    
    }

     

     

  12. On 7/2/2021 at 2:46 PM, Mad Alchemist said:

     Hi! I am trying to make my own zombie apocalypse mod, and I want to make my zombies look different.

    Hi MadAlchemist, if you open the AbstractZombieModel class, you can see that the following controls the arms-out zombie pose:

    public void setupAnim(T p_225597_1_, float p_225597_2_, float p_225597_3_, float p_225597_4_, float p_225597_5_, float p_225597_6_) {
          super.setupAnim(p_225597_1_, p_225597_2_, p_225597_3_, p_225597_4_, p_225597_5_, p_225597_6_);
          ModelHelper.animateZombieArms(this.leftArm, this.rightArm, this.isAggressive(p_225597_1_), this.attackTime, p_225597_4_);
    }
    
    public abstract boolean isAggressive(T p_212850_1_);

    So the easiest way to apply this to a player model is copy the AbstractZombieModel class, but have it extend PlayerModel rather than BipedModel. You may need to add another animateZombieArms line that takes in this.leftSleeve and this.rightSleeve from PlayerModel. Finally you'll want your entity renderer to copy the AbstractZombieRenderer class (and add a CapeLayer from PlayerRenderer to your constructor if certain players have capes). Then player skins should fit your custom zombie.

  13. 1) For this your best bet is to create a LivingAttackEvent and/or LivingDamageEvent to check the damage received, and also check if the player is wearing your armor. Both events have values for source and amount that can help you determine what to do from a "lethal" attack.

    2) What you describe would most easily be enacted as a repair item for your armor, like how the phantom membrane restores elytra. Then each time the durability (or a special durability) is repaired by anvil or crafting, you can increment an NBT value to count how many times it's been repaired.

    3) I would take a look at the BipedArmorLayer class for how vanilla armor is rendered. You can then specify that model in the item class with: 

    @Nullable
    @Override
    public <A extends BipedModel<?>> A getArmorModel(LivingEntity entityLiving, ItemStack itemStack, EquipmentSlotType armorSlot, A _default) {
    	return (A) new MyArmorModel();
    }

    and then the texture with something such as:

    @Nullable
    @Override
    public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlotType slot, String type) {
    	if(!"overlay".equals(type))
    		return "mod_id:textures/models/armor/my_armor.png";
    	else {
    		return "mod_id:textures/models/armor/my_armor_overlay.png";
    	}
    }

    Hope this helps

  14. From this post, I've modified the original armor attribute of my custom item. The biggest change between that post and now is that the attribute multimap is immutable, so it needs to be copied to a mutable map, adjusted, and then copied to an immutable one again. Normally it would be easier to create a new armor material, however the value I need depends on a variable (extraArmor) in the item class. The armor value changes correctly, but only when one instance of the item is present in the inventory. If another one is there, then the armor of the newest instance overwrites the previous item(s). I've tired alternatives such as adding a new armor modifier (Attempt 2) or using an ItemAttributeModifierEvent instead of getAttributeModifiers, but they all face the same problem. I'm not sure why they would change since the extraArmor value isn't static and isn't called or updated statically as far as I'm aware. If anyone can help I'd be grateful.

    Attempt 1: Edit original values

    Spoiler
    
    
    	public static<K, V> ListMultimap<K, V> toMutableMultimap(Multimap<K, V> original) {
    		ListMultimap<K, V> copy = ArrayListMultimap.create();
    		copy.putAll(original);
    		return copy;
    	}
    
    	public static<K, V> ImmutableMultimap<K, V> toImmutableMultimap(ListMultimap<K, V> original) {
    		return new ImmutableMultimap.Builder<K, V>().putAll(original).build();
    	}
    
    	@Override
    	public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack) {
    		Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack);
    		ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap);
    		final Collection<AttributeModifier> modifiers = mutableMultimap.get(Attributes.ARMOR);
          
    		Item item = stack.getItem();
    		if (item instanceof MyItem && slot == this.slot) {
    			ArmorItem armorItem = (ArmorItem) item;
    			MyItem myItem = (MyItem) item;
    
    			UUID[] uuid_arr = ObfuscationReflectionHelper.getPrivateValue(ArmorItem.class, armorItem, "ARMOR_MODIFIER_UUID_PER_SLOT");
    			if (uuid_arr != null) {
    				UUID uuid = uuid_arr[slot.getIndex()];
    				this.replaceModifier(mutableMultimap, Attributes.ARMOR, uuid, myItem.extraArmor);
    			}
    		}
    		return toImmutableMultimap(mutableMultimap);
    	}
    
    	private void replaceModifier(ListMultimap<Attribute, AttributeModifier> multimap, Attribute attribute, UUID id, double newValue) {
    		final Collection<AttributeModifier> modifiers = multimap.get(attribute);
    		final Optional<AttributeModifier> modifierOptional = 
          modifiers.stream().filter(attributeModifier -> attributeModifier.getId().equals(id)).findFirst();
    
    		if (modifierOptional.isPresent()) {
    			final AttributeModifier modifier = modifierOptional.get();
    			modifiers.remove(modifier);
    			modifiers.add(new AttributeModifier(modifier.getId(), modifier.getName(), modifier.getAmount() + newValue, 	modifier.getOperation()));
    		}
    	}

     

     

    Attempt 2: Add unique modifier

    Spoiler
    
    
    	public static UUID MY_ITEM_ARMOR_UUID = UUID.fromString("b5ba8c15-4e13-437b-9d3a-d80f2849362f");
    	public AttributeModifier MY_ITEM_ARMOR_MODIFIER = new AttributeModifier(MY_ITEM_ARMOR_UUID, "My item armor modifier", this.extraArmor, AttributeModifier.Operation.ADDITION);
    
    	@Override
    	public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack) {
    		Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack);
    		ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap);
    		final Collection<AttributeModifier> modifiers = mutableMultimap.get(Attributes.ARMOR);
          
    		final Optional<AttributeModifier> modifierOptional = modifiers.stream()
          	.filter(attributeModifier -> attributeModifier.getId().equals(MY_ITEM_ARMOR_UUID)).findFirst();
    
    		if (!modifierOptional.isPresent() && item instanceof MyItem && slot == this.slot) {
    			modifiers.add(MY_ITEM_ARMOR_MODIFIER);
    		}
    		return toImmutableMultimap(mutableMultimap);
    	}

     

     

  15. 22 hours ago, lupicus said:

    is returning entities with spawn costs, which only 2 nether biomes have them for enderman.

    Ah ok, thanks. Iterating over spawners vs entity types makes more sense. I've modified the event to mirror mincount, maxcount etc. as well:

    Spoiler
    
    
     @SubscribeEvent
        public static void onBiomeLoad(BiomeLoadingEvent event) {
            EntityType<EndermanEntity> entityToFind = EntityType.ENDERMAN;
            EntityType<MyEntity> entityToAdd = ModEntities.MY_ENTITY;
    
            MobSpawnInfoBuilder spawnInfo = event.getSpawns();
            List<MobSpawnInfo.Spawners> spawnersForFind = spawnInfo.getSpawner(entityToFind.getCategory());
            MobSpawnInfo.Spawners spawnerToAdd = null;
            for (MobSpawnInfo.Spawners spawner : spawnersForFind) {
                if (spawner.type == entityToFind) {
                    spawnerToAdd = new MobSpawnInfo.Spawners(entityToAdd, spawner.weight, spawner.minCount, spawner.maxCount);
                }
            }
            if (spawnerToAdd != null) {
                List<MobSpawnInfo.Spawners> spawnersForAdd = spawnInfo.getSpawner(entityToAdd.getCategory());
                spawnersForAdd.add(spawnerToAdd);
            }
        }

     

    Although the entity is still refusing to spawn lol. I've debugged the event to see if the custom mob is being added to the spawns, and it is. I've tried registering the spawns outright vs adding on biome load, but it doesn't make a difference. I think the problem lies somewhere in the actual entity class that's preventing it, I'll take a thorough look tomorrow. I appreciate your help.

  16. 3 hours ago, onVoid said:

    Are there mappings for parameter names yet? Or does every modder just have to deal with typing in an auto-generated string when referencing a parameter.

    These are SRG names, which are semi-obfuscated. In your PizzaItem constructor you can rename p_i48487_1_ to "properties" or whatever you wish. Any input parameters like this can be renamed, it's only when you're referencing actual variable or method names from the source that you can't rename them. 

  17.  

    6 hours ago, CaiGuyCrafter said:

    So, I've made a procedure for activating an aura around the player when they hit a certain key.

    I'm only quoting so that you receive a notification, because normally replies don't notify for some reason.

    Anyway Your best bet to create an aura would be a render overlay like how the player is on fire, and activate it from a RenderLivingEvent: 

    @Mod.EventBusSubscriber(modid = Main.MOD_ID)
    public class ForgeSubscribeEvents {
    
      @SubscribeEvent
      public void onRenderEntity(RenderLivingEvent.Post event) {
          //code here
      }
    }

    In the event you'll handle pushing and popping the render matrix stack, which is what the post on greyminecraftcoder is talking about, despite being a bit outdated. I've tried tackling it here in 1.16.X but with little success. 

    It might be easier to go the particle route if you still want to do that though. This would be handled by a LivingUpdateEvent which you've probably already done:

    @SubscribeEvent
    public static void onLivingUpdate(final LivingEvent.LivingUpdateEvent event) {
    	//code here
    }

    However bending which way the particles face as per the link so that they're concentric to the player would still likely involve the matrix stack. 

×
×
  • Create New...

Important Information

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