Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion src/main/java/ladysnake/spawnercontrol/SpawnerEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
import net.minecraft.block.BlockMobSpawner;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.IMob;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
Expand All @@ -28,6 +31,7 @@
import net.minecraft.world.WorldServer;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.event.entity.living.LivingExperienceDropEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.event.world.BlockEvent;
Expand All @@ -37,6 +41,7 @@
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.relauncher.Side;

import java.util.*;
Expand Down Expand Up @@ -211,6 +216,57 @@ public static void onLivingExperienceDrop(LivingExperienceDropEvent event) {
}
}

@SubscribeEvent(priority = EventPriority.LOWEST)
public static void onLivingItemDrop(LivingDropsEvent event) {
EntityLivingBase livingBase = event.getEntityLiving();
SpawnerConfig cfg = SpawnerUtil.getConfig(livingBase.getEntityData().getTag(NBT_TAG_SPAWNER_POS));
if (cfg != null) {
try {
ResourceLocation rl = EntityList.getKey(event.getEntity());
if (rl != null) {
SpawnerConfig.MobLoot.MobLootEntry entry = cfg.mobLoot.lootEntries.get(rl);
List<EntityItem> drops = event.getDrops();
if (entry.removeAllItems) {
drops.clear();
} else {
for (EntityItem drop : drops.toArray(new EntityItem[0])) {
ItemStack stack = drop.getItem();
for (String s : entry.removedItems) {
String[] split = s.split(":");
if (stack.getUnlocalizedName().equals(split[0] + ":" + split[1])
&& (split.length < 3 || stack.getMetadata() == Integer.parseInt(split[2]))) {
drops.remove(drop);
}
}
}
}
World world = livingBase.world;
double x = livingBase.posX, y = livingBase.posY, z = livingBase.posZ;
for (String s : entry.addedItems)
{
String[] split = s.split(":");
if (split.length < 5 || world.rand.nextDouble() < Double.parseDouble(split[4])) {
ResourceLocation itemRL = new ResourceLocation(split[0], split[1]);
Item item = ForgeRegistries.ITEMS.getValue(itemRL);
if (item == null) {
item = Item.getItemFromBlock(ForgeRegistries.BLOCKS.getValue(itemRL));
}
if (item != Items.AIR) {
int quantity = split.length < 3 ? 1 : Integer.parseInt(split[2]);
int meta = split.length < 4 ? 0 : Integer.parseInt(split[3]);
drops.add(new EntityItem(world, x, y, z, new ItemStack(item, quantity, meta)));
} else {
SpawnerControl.LOGGER.error("Error while handling spawned item drops");
}
}
}
}
} catch (NumberFormatException | ExecutionException e) {
SpawnerControl.LOGGER.error("Error while handling spawned item drops", e);
}
}
}

/**
* Changes the amount of experience dropped by a spawner when broken.
* Drops from the mod's spawner are also handled here
Expand Down Expand Up @@ -256,7 +312,7 @@ else if (block instanceof BlockMobSpawner && MSCConfig.alterVanillaSpawner)
int count = split.length >= 3 ? Integer.parseInt(split[2]) : 1;
int meta = split.length >= 4 ? Integer.parseInt(split[3]) : 0;
// default chance is 1
if (split.length < 5 || event.getWorld().rand.nextFloat() < Double.parseDouble(split[4]))
if (split.length < 5 || event.getWorld().rand.nextDouble() < Double.parseDouble(split[4]))
drops.add(new ItemStack(item, count, meta));
}
} catch (NumberFormatException ignored) {
Expand Down
64 changes: 58 additions & 6 deletions src/main/java/ladysnake/spawnercontrol/config/SpawnerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.config.Config;

import java.util.Arrays;
import java.util.List;

public class SpawnerConfig {

@Config.Comment("Regroups config options aiming to alter mob spawners spawning conditions")
Expand Down Expand Up @@ -51,34 +54,75 @@ public static class SpawnConditions {

public static class MobLoot {

public MobLootEntry defaultValues = new MobLootEntry(1, 0);
public MobLootEntry defaultValues = new MobLootEntry(1, 0, false, new String[0], new String[0]);

@Config.Comment({"Individual xp drop multiplier configuration for mobs spawned by this spawner type", "Format: 'modid:entity:xpMultiplier(:flatXp)' (flatXp is optional)"})
public String[] xpMultipliers = new String[0];

@Config.Comment({"Individual item drop removal configuration for mobs spawned by this spawner type", "Format: 'modid:entity(,modid:item(:meta))(,modid:item(:meta))...'", "Anything in parenthesis is optional, and you can enter as many items as you want", "If don't enter any items, all item drops are removed from the mob (itemDropAdditions are added afterwards)"})
public String[] itemDropRemovals = new String[0];

@Config.Comment({"Individual item drop addition configuration for mobs spawned by this spawner type", "Format: 'modid:entity,modid:item(:count(:meta(:chance)))(,modid:item(:count(:meta(:chance))))...'", "Anything in parenthesis is optional, and you can enter as many items as you want", "Eg: minecraft:skeleton,minecraft:dye:100:15:0.5,minecraft:bone:1:1:1"})
public String[] itemDropAdditions = new String[0];

@Config.Ignore
public LoadingCache<ResourceLocation, MobLootEntry> lootEntries = CacheBuilder.newBuilder().build(CacheLoader.from(rl -> {
if (rl == null) return defaultValues;
float xpMultiplier = defaultValues.xpMultiplier;
int flatXpIncrease = defaultValues.flatXpIncrease;
boolean removeAllItems = defaultValues.removeAllItems;
List<String> removedItems = Arrays.asList(defaultValues.removedItems);
List<String> addedItems = Arrays.asList(defaultValues.addedItems);
for (String s : xpMultipliers) {
String[] split = s.split(":");
if (split[0].equals(rl.getResourcePath()) && split[1].equals(rl.getResourceDomain())) {
try {
float xpMultiplier = Float.parseFloat(split[2]);
int flatXpIncrease = split.length > 3 ? Integer.parseInt(split[3]) : defaultValues.flatXpIncrease;
return new MobLootEntry(xpMultiplier, flatXpIncrease);
xpMultiplier = Float.parseFloat(split[2]);
flatXpIncrease = split.length > 3 ? Integer.parseInt(split[3]) : defaultValues.flatXpIncrease;
} catch (NumberFormatException e) {
SpawnerControl.LOGGER.warn("Bad mob spawner loot config option : {}", s);
}
break;
}
}
for (String s : itemDropRemovals) {
String[] split = s.split(",");
String[] mobSplit = split[0].split(":");
if (mobSplit[0].equals(rl.getResourcePath()) && mobSplit[1].equals(rl.getResourceDomain())) {
try {
removedItems = Arrays.asList(split);
removedItems.remove(0);
removeAllItems = removedItems.size() == 0;
} catch (Exception e) {
SpawnerControl.LOGGER.warn("Bad mob spawner loot config option : {}", s);
}
break;
}
}
for (String s : itemDropAdditions) {
String[] split = s.split(":");
if (split[0].equals(rl.getResourcePath()) && split[1].equals(rl.getResourceDomain())) {
try {
addedItems = Arrays.asList(split);
addedItems.remove(0);
} catch (Exception e) {
SpawnerControl.LOGGER.warn("Bad mob spawner loot config option : {}", s);
}
break;
}
}
return defaultValues;
return new MobLootEntry(xpMultiplier, flatXpIncrease, removeAllItems, removedItems.toArray(new String[0]), addedItems.toArray(new String[0]));
}));

public static class MobLootEntry {

public MobLootEntry(float defaultXpMultiplier, int flatXpIncrease) {
public MobLootEntry(float defaultXpMultiplier, int flatXpIncrease, boolean removeAllItems, String[] removedItems, String[] addedItems) {
this.xpMultiplier = defaultXpMultiplier;
this.flatXpIncrease = flatXpIncrease;

this.removeAllItems = removeAllItems;
this.removedItems = removedItems;
this.addedItems = addedItems;
}

@Config.Comment("xp drop multiplier for mobs spawned by this spawner type")
Expand All @@ -87,6 +131,14 @@ public MobLootEntry(float defaultXpMultiplier, int flatXpIncrease) {
@Config.Comment("Flat xp modifier that will be added to mobs spawned by this spawner type")
public int flatXpIncrease;

@Config.Comment({"Remove all existing item drops from the mobs spawned by this spawner", "'Added Items' are added afterwards"})
public boolean removeAllItems;

@Config.Comment({"Which items to remove from the drops of the mobs spawned", "Format: 'modid:item(:meta)' (meta is optional)", "If 'Remove All Items' is true, this does nothing"})
public String[] removedItems;

@Config.Comment({"Which items to add to the drops of the mobs spawned", "Format: 'modid:item(:count(:meta(:chance)))' (count, meta and chance are optional)"})
public String[] addedItems;
}
}
}