9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-30 20:39:21 +00:00

Custom entity spawns

This commit is contained in:
Daniel Mills
2020-09-02 16:46:11 -04:00
parent 8bb01a2412
commit a478428721
16 changed files with 680 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.object;
import org.bukkit.attribute.Attributable;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.attribute.AttributeModifier.Operation;
@@ -60,6 +61,14 @@ public class IrisAttributeModifier
}
}
public void apply(RNG rng, Attributable meta)
{
if(rng.nextDouble() < getChance())
{
meta.getAttribute(getAttribute()).addModifier(new AttributeModifier(getName(), getAmount(rng), getOperation()));
}
}
public double getAmount(RNG rng)
{
return rng.d(getMinAmount(), getMaxAmount());

View File

@@ -42,6 +42,11 @@ public class IrisBiome extends IrisRegistrant implements IRare
@ArrayType(min = 1, type = IrisTextPlacement.class)
private KList<IrisTextPlacement> text = new KList<>();
@DontObfuscate
@Desc("Entity spawns to override or add to this biome")
@ArrayType(min = 1, type = IrisEntitySpawn.class)
private KList<IrisEntitySpawn> entitySpawns = new KList<>();
@ArrayType(min = 1, type = IrisEffect.class)
@DontObfuscate
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.")

View File

@@ -51,6 +51,11 @@ public class IrisDimension extends IrisRegistrant
@ArrayType(min = 1, type = IrisTextPlacement.class)
private KList<IrisTextPlacement> text = new KList<>();
@DontObfuscate
@Desc("Entity spawns to override or add to this dimension")
@ArrayType(min = 1, type = IrisEntitySpawn.class)
private KList<IrisEntitySpawn> entitySpawns = new KList<>();
@DontObfuscate
@Desc("Reference loot tables in this area")
private IrisLootReference loot = new IrisLootReference();

View File

@@ -0,0 +1,270 @@
package com.volmit.iris.object;
import java.util.Collection;
import java.util.Random;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.attribute.Attributable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.Lootable;
import com.volmit.iris.Iris;
import com.volmit.iris.gen.IrisChunkGenerator;
import com.volmit.iris.util.ArrayType;
import com.volmit.iris.util.C;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.Required;
import lombok.Data;
import lombok.EqualsAndHashCode;
@DontObfuscate
@Desc("Represents an iris entity.")
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisEntity extends IrisRegistrant
{
@Required
@DontObfuscate
@Desc("The type of entity to spawn")
private EntityType type = EntityType.PIG;
@DontObfuscate
@Desc("The custom name of this entity")
private String customName = "";
@DontObfuscate
@Desc("Should the name on this entity be visible even if you arent looking at it.")
private boolean customNameVisible = false;
@DontObfuscate
@Desc("If this entity type is a mob, should it be aware of it's surroundings & interact with the world.")
private boolean aware = true;
@DontObfuscate
@Desc("If this entity type is a creature, should it have ai goals.")
private boolean ai = true;
@DontObfuscate
@Desc("Should this entity be glowing")
private boolean glowing = false;
@DontObfuscate
@Desc("Should gravity apply to this entity")
private boolean gravity = true;
@DontObfuscate
@Desc("When an entity is invulnerable it can only be damaged by players increative mode.")
private boolean invulnerable = false;
@DontObfuscate
@Desc("When an entity is silent it will not produce any sound.")
private boolean silent = false;
@DontObfuscate
@Desc("Should this entity be allowed to pickup items")
private boolean pickupItems = false;
@DontObfuscate
@Desc("Should this entity be removed when far away")
private boolean removable = true;
@DontObfuscate
@Desc("Entity helmet equipment")
private IrisLoot helmet = null;
@DontObfuscate
@Desc("Entity chestplate equipment")
private IrisLoot chestplate = null;
@DontObfuscate
@Desc("Entity boots equipment")
private IrisLoot boots = null;
@DontObfuscate
@Desc("Entity leggings equipment")
private IrisLoot leggings = null;
@DontObfuscate
@Desc("Entity main hand equipment")
private IrisLoot mainHand = null;
@DontObfuscate
@Desc("Entity off hand equipment")
private IrisLoot offHand = null;
@DontObfuscate
@Desc("Make other entities ride this entity")
@ArrayType(min = 1, type = IrisEntity.class)
private KList<IrisEntity> passengers = new KList<>();
@DontObfuscate
@Desc("Attribute modifiers for this entity")
@ArrayType(min = 1, type = IrisAttributeModifier.class)
private KList<IrisAttributeModifier> attributes = new KList<>();
@DontObfuscate
@Desc("Loot tables for drops")
private IrisLootReference loot = new IrisLootReference();
@DontObfuscate
@Desc("Potion effects to add to this entity")
@ArrayType(min = 1, type = IrisPotionEffect.class)
private KList<IrisPotionEffect> potionEffects = new KList<>();
@DontObfuscate
@Desc("If specified, this entity will be leashed by this entity. I.e. THIS ENTITY Leashed by SPECIFIED. This has no effect on EnderDragons, Withers, Players, or Bats.Non-living entities excluding leashes will not persist as leashholders.")
private IrisEntity leashHolder = null;
public Entity spawn(IrisChunkGenerator gen, Location at)
{
return spawn(gen, at, new RNG(at.hashCode()));
}
public Entity spawn(IrisChunkGenerator gen, Location at, RNG rng)
{
Entity e = at.getWorld().spawnEntity(at, getType());
e.setCustomName(getCustomName() != null ? C.translateAlternateColorCodes('&', getCustomName()) : null);
e.setCustomNameVisible(isCustomNameVisible());
e.setGlowing(isGlowing());
e.setGravity(isGravity());
e.setInvulnerable(isInvulnerable());
e.setSilent(isSilent());
int gg = 0;
for(IrisEntity i : passengers)
{
e.addPassenger(i.spawn(gen, at, rng.nextParallelRNG(234858 + gg++)));
}
if(e instanceof Attributable)
{
Attributable a = (Attributable) e;
for(IrisAttributeModifier i : getAttributes())
{
i.apply(rng, a);
}
}
if(e instanceof Lootable)
{
Lootable l = (Lootable) e;
if(getLoot().getTables().isNotEmpty())
{
l.setLootTable(new LootTable()
{
@Override
public NamespacedKey getKey()
{
return new NamespacedKey(Iris.instance, "loot-" + IrisEntity.this.hashCode());
}
@Override
public Collection<ItemStack> populateLoot(Random random, LootContext context)
{
KList<ItemStack> items = new KList<>();
for(int t = 0; t < gen.getDimension().getLootTries(); t++)
{
int b = 4;
for(String fi : getLoot().getTables())
{
IrisLootTable i = gen.getData().getLootLoader().load(fi);
b++;
items.addAll(i.getLoot(gen.isDev(), rng.nextParallelRNG(345911 * -t), InventorySlotType.STORAGE, at.getBlockX(), at.getBlockY(), at.getBlockZ(), t + b + b, b));
}
}
return items;
}
@Override
public void fillInventory(Inventory inventory, Random random, LootContext context)
{
for(ItemStack i : populateLoot(random, context))
{
inventory.addItem(i);
}
gen.getGlUpdate().scramble(inventory, rng);
}
});
}
}
if(e instanceof LivingEntity)
{
LivingEntity l = (LivingEntity) e;
l.setAI(isAi());
l.setCanPickupItems(isPickupItems());
if(getLeashHolder() != null)
{
l.setLeashHolder(getLeashHolder().spawn(gen, at, rng.nextParallelRNG(234548)));
}
l.setRemoveWhenFarAway(isRemovable());
for(IrisPotionEffect i : getPotionEffects())
{
i.apply(l);
}
if(getHelmet() != null && rng.i(1, getHelmet().getRarity()) == 1)
{
l.getEquipment().setHelmet(getHelmet().get(gen.isDev(), rng));
}
if(getChestplate() != null && rng.i(1, getChestplate().getRarity()) == 1)
{
l.getEquipment().setChestplate(getChestplate().get(gen.isDev(), rng));
}
if(getLeggings() != null && rng.i(1, getLeggings().getRarity()) == 1)
{
l.getEquipment().setLeggings(getLeggings().get(gen.isDev(), rng));
}
if(getBoots() != null && rng.i(1, getBoots().getRarity()) == 1)
{
l.getEquipment().setBoots(getBoots().get(gen.isDev(), rng));
}
if(getMainHand() != null && rng.i(1, getMainHand().getRarity()) == 1)
{
l.getEquipment().setItemInMainHand(getMainHand().get(gen.isDev(), rng));
}
if(getOffHand() != null && rng.i(1, getOffHand().getRarity()) == 1)
{
l.getEquipment().setItemInOffHand(getOffHand().get(gen.isDev(), rng));
}
}
if(e instanceof Mob)
{
Mob m = (Mob) e;
m.setAware(isAware());
}
return e;
}
public IrisEntity()
{
}
}

View File

@@ -0,0 +1,91 @@
package com.volmit.iris.object;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.EntitySpawnEvent;
import com.volmit.iris.gen.IrisChunkGenerator;
import com.volmit.iris.gen.atomics.AtomicCache;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListEntity;
import com.volmit.iris.util.Required;
import lombok.Data;
@Desc("Represents an entity spawn")
@Data
public class IrisEntitySpawn
{
@RegistryListEntity
@Required
@DontObfuscate
@Desc("The entity")
private String entity = "";
@Required
@DontObfuscate
@Desc("If the following entity type spawns, spawn this entity. Set to unknown for any entity spawn")
private EntityType trigger = EntityType.UNKNOWN;
@DontObfuscate
@Desc("If the source is triggered, cancel spawning the original entity instead of ADDING a new entity.")
private boolean cancelSourceSpawn = false;
@MinNumber(1)
@DontObfuscate
@Desc("The 1 in RARITY chance for this entity to spawn")
private int rarity = 1;
private AtomicCache<RNG> rng = new AtomicCache<>();
private AtomicCache<IrisEntity> ent = new AtomicCache<>();
public Entity on(IrisChunkGenerator g, Location at, EntityType t, EntitySpawnEvent ee)
{
if(!trigger.equals(EntityType.UNKNOWN))
{
if(!trigger.equals(t))
{
return null;
}
}
Entity e = spawn(g, at);
if(e != null && isCancelSourceSpawn())
{
ee.setCancelled(true);
ee.getEntity().remove();
}
return e;
}
public IrisEntity getRealEntity(IrisChunkGenerator g)
{
return ent.aquire(() -> g.getData().getEntityLoader().load(getEntity()));
}
public Entity spawn(IrisChunkGenerator g, Location at)
{
if(getRealEntity(g) == null)
{
return null;
}
if(rng.aquire(() -> new RNG(g.getWorld().getSeed() + 4)).i(1, getRarity()) == 1)
{
return getRealEntity(g).spawn(g, at, rng.aquire(() -> new RNG(g.getWorld().getSeed() + 4)));
}
return null;
}
public IrisEntitySpawn()
{
}
}

View File

@@ -1,10 +1,15 @@
package com.volmit.iris.object;
import java.awt.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.material.Colorable;
import com.volmit.iris.Iris;
import com.volmit.iris.gen.atomics.AtomicCache;
@@ -96,6 +101,14 @@ public class IrisLoot
@Desc("This is the item or block type. Does not accept minecraft:*. Only materials such as DIAMOND_SWORD or DIRT.")
private String type = "";
@DontObfuscate
@Desc("The dye color")
private DyeColor dyeColor = null;
@DontObfuscate
@Desc("The leather armor color")
private String leatherColor = null;
private transient AtomicCache<CNG> chance = new AtomicCache<>();
public IrisLoot()
@@ -171,6 +184,18 @@ public class IrisLoot
}
m.setLore(lore);
if(getLeatherColor() != null && m instanceof LeatherArmorMeta)
{
Color c = Color.decode(getLeatherColor());
((LeatherArmorMeta) m).setColor(org.bukkit.Color.fromRGB(c.getRed(), c.getGreen(), c.getBlue()));
}
if(getDyeColor() != null && m instanceof Colorable)
{
((Colorable) m).setColor(getDyeColor());
}
is.setItemMeta(m);
return is;
}

View File

@@ -0,0 +1,107 @@
package com.volmit.iris.object;
import org.bukkit.entity.LivingEntity;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.volmit.iris.Iris;
import com.volmit.iris.gen.atomics.AtomicCache;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.Required;
import lombok.Data;
@Desc("An iris potion effect")
@Data
public class IrisPotionEffect
{
@Required
@DontObfuscate
@Desc("The potion effect to apply in this area")
private String potionEffect = "";
@Required
@MinNumber(-1)
@MaxNumber(1024)
@DontObfuscate
@Desc("The Potion Strength or -1 to disable")
private int strength = -1;
@Required
@MinNumber(1)
@DontObfuscate
@Desc("The time the potion will last for")
private int ticks = 200;
@DontObfuscate
@Desc("Is the effect ambient")
private boolean ambient = false;
@DontObfuscate
@Desc("Is the effect showing particles")
private boolean particles = true;
private transient AtomicCache<PotionEffectType> pt = new AtomicCache<>();
public IrisPotionEffect()
{
}
public PotionEffectType getRealType()
{
return pt.aquire(() ->
{
PotionEffectType t = PotionEffectType.LUCK;
if(getPotionEffect().isEmpty())
{
return t;
}
try
{
for(PotionEffectType i : PotionEffectType.values())
{
if(i.getName().toUpperCase().replaceAll("\\Q \\E", "_").equals(getPotionEffect()))
{
t = i;
return t;
}
}
}
catch(Throwable e)
{
}
Iris.warn("Unknown Potion Effect Type: " + getPotionEffect());
return t;
});
}
public void apply(LivingEntity p)
{
if(strength > -1)
{
if(p.hasPotionEffect(getRealType()))
{
PotionEffect e = p.getPotionEffect(getRealType());
if(e.getAmplifier() > strength)
{
return;
}
p.removePotionEffect(getRealType());
}
p.addPotionEffect(new PotionEffect(getRealType(), ticks, strength, ambient, particles, false));
}
}
}

View File

@@ -35,7 +35,12 @@ public class IrisRegion extends IrisRegistrant implements IRare
@DontObfuscate
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.")
private KList<IrisEffect> effects = new KList<>();
@DontObfuscate
@Desc("Entity spawns to override or add to this region")
@ArrayType(min = 1, type = IrisEntitySpawn.class)
private KList<IrisEntitySpawn> entitySpawns = new KList<>();
@MinNumber(1)
@MaxNumber(256)
@DontObfuscate

View File

@@ -27,6 +27,11 @@ public class IrisStructure extends IrisRegistrant
@Desc("This is the human readable name for this structure. Such as Red Dungeon or Tropical Village.")
private String name = "A Structure Type";
@DontObfuscate
@Desc("Entity spawns to override or add to this structure")
@ArrayType(min = 1, type = IrisEntitySpawn.class)
private KList<IrisEntitySpawn> entitySpawns = new KList<>();
@DontObfuscate
@Desc("Wall style noise")
private IrisGeneratorStyle wallStyle = NoiseStyle.STATIC.style();

View File

@@ -24,6 +24,11 @@ public class IrisStructureTile
@Desc("Reference loot tables in this area")
private IrisLootReference loot = new IrisLootReference();
@DontObfuscate
@Desc("Entity spawns to override or add to this structure tile")
@ArrayType(min = 1, type = IrisEntitySpawn.class)
private KList<IrisEntitySpawn> entitySpawns = new KList<>();
@DontObfuscate
@Desc("The place mode for this tile")
private ObjectPlaceMode placeMode = ObjectPlaceMode.CENTER_HEIGHT;