ore spawn effect, part 1

This commit is contained in:
Ellpeck 2019-02-20 23:49:21 +01:00
parent 131b16ff28
commit 299eb72ec0
8 changed files with 294 additions and 22 deletions

View file

@ -11,6 +11,7 @@ import de.ellpeck.naturesaura.entities.EntityEffectInhibitor;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -23,6 +24,7 @@ import org.lwjgl.util.vector.Vector3f;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
@Override
@ -105,19 +107,31 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
}
@Override
public boolean isEffectPowderActive(World world, BlockPos pos, ResourceLocation name) {
public List<Tuple<BlockPos, Integer>> getActiveEffectPowders(World world, AxisAlignedBB area, ResourceLocation name) {
world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getActiveEffectPowders");
List<EntityEffectInhibitor> inhibitors = world.getEntitiesWithinAABB(
EntityEffectInhibitor.class,
new AxisAlignedBB(pos).grow(64),
entity -> {
if (!name.equals(entity.getInhibitedEffect()))
return false;
AxisAlignedBB bounds = new AxisAlignedBB(
entity.posX, entity.posY, entity.posZ,
entity.posX, entity.posY, entity.posZ).grow(entity.getAmount());
return bounds.contains(new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5));
});
return !inhibitors.isEmpty();
EntityEffectInhibitor.class, area,
entity -> name.equals(entity.getInhibitedEffect()));
List<Tuple<BlockPos, Integer>> tuples = inhibitors.stream()
.map(entity -> new Tuple<>(entity.getPosition(), entity.getAmount()))
.collect(Collectors.toList());
world.profiler.endSection();
return tuples;
}
@Override
public boolean isEffectPowderActive(World world, BlockPos pos, ResourceLocation name) {
world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":isEffectPowderActive");
List<Tuple<BlockPos, Integer>> powders = this.getActiveEffectPowders(world, new AxisAlignedBB(pos).grow(64), name);
for (Tuple<BlockPos, Integer> powder : powders) {
AxisAlignedBB bounds = new AxisAlignedBB(powder.getFirst()).grow(powder.getSecond());
if (bounds.contains(new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5))) {
world.profiler.endSection();
return true;
}
}
world.profiler.endSection();
return false;
}
@Override

View file

@ -3,6 +3,7 @@ package de.ellpeck.naturesaura;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.aura.type.BasicAuraType;
import de.ellpeck.naturesaura.api.aura.type.IAuraType;
import de.ellpeck.naturesaura.api.recipes.WeightedOre;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.DimensionType;
import net.minecraftforge.common.config.Config;
@ -27,6 +28,9 @@ public final class ModConfig {
@Comment("Additional dimensions that map to Aura types that should be present in them. This is useful if you have a modpack with custom dimensions that should have Aura act similarly to an existing dimension in them. Each entry needs to be formatted as dimension_name->aura_type, where aura_type can be any of naturesaura:overworld, naturesaura:nether and naturesaura:end.")
public String[] auraTypeOverrides = new String[0];
@Comment("Additional blocks that are recognized as generatable ores for the passive ore generation effect. Each entry needs to be formatted as oredictEntry:oreWeight:dimension where a higher weight makes the ore more likely to spawn with 5000 being the weight of coal, the default ore with the highest weight, and dimension being any of overworld and nether")
public String[] additionalOres = new String[0];
@Comment("The amount of blocks that can be between two Aura Field Creators for them to be connectable and work together")
public int fieldCreatorRange = 10;
@ -53,6 +57,8 @@ public final class ModConfig {
public boolean breathlessEffect = true;
@Comment("If the Aura Imbalance effect of farm animals being affected in positive ways if Aura levels are too high should occur")
public boolean animalEffect = true;
@Comment("If the Aura Imbalance effect of ores spawning in the area if Aura levels are too high should occur")
public boolean oreEffect = true;
}
public static class Client {
@ -104,6 +110,20 @@ public final class ModConfig {
} catch (Exception e) {
NaturesAura.LOGGER.warn("Error parsing auraTypeOverrides", e);
}
try {
for (String s : general.additionalOres) {
String[] split = s.split(":");
WeightedOre ore = new WeightedOre(split[0], Integer.parseInt(split[1]));
String dimension = split[2];
if ("nether".equalsIgnoreCase(dimension))
NaturesAuraAPI.NETHER_ORES.add(ore);
else
NaturesAuraAPI.OVERWORLD_ORES.add(ore);
}
} catch (Exception e) {
NaturesAura.LOGGER.warn("Error parsing additionalOres", e);
}
}
}
}

View file

@ -12,14 +12,13 @@ import de.ellpeck.naturesaura.api.internal.StubHooks;
import de.ellpeck.naturesaura.api.misc.IWorldData;
import de.ellpeck.naturesaura.api.multiblock.IMultiblock;
import de.ellpeck.naturesaura.api.multiblock.Matcher;
import de.ellpeck.naturesaura.api.recipes.AltarRecipe;
import de.ellpeck.naturesaura.api.recipes.AnimalSpawnerRecipe;
import de.ellpeck.naturesaura.api.recipes.OfferingRecipe;
import de.ellpeck.naturesaura.api.recipes.TreeRitualRecipe;
import de.ellpeck.naturesaura.api.recipes.*;
import net.minecraft.block.BlockFlower;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
@ -114,6 +113,16 @@ public final class NaturesAuraAPI {
* AnimalSpawnerRecipe#register()}.
*/
public static final Map<ResourceLocation, AnimalSpawnerRecipe> ANIMAL_SPAWNER_RECIPES = new HashMap<>();
/**
* A list of all {@link WeightedOre} objects that represent ores that can
* spawn inside of stone blocks in the overworld
*/
public static final List<WeightedOre> OVERWORLD_ORES = new ArrayList<>();
/**
* A list of all {@link WeightedOre} objects that represent ores that can
* spawn inside of netherrack blocks in the nether
*/
public static final List<WeightedOre> NETHER_ORES = new ArrayList<>();
/**
* The capability for any item or block that stores Aura in the form of an
@ -276,10 +285,24 @@ public final class NaturesAuraAPI {
*/
IMultiblock createMultiblock(ResourceLocation name, String[][] pattern, Object... rawMatchers);
/**
* Get all of the active effect powders in the given area and consume
* the position and the range that they have. To register a powder with
* the supplied name, use {@link #EFFECT_POWDERS}
*
* @param world The world
* @param area The area to find powders in
* @param name The registry name of the powder
* @return A list of powders' positions and ranges
*/
List<Tuple<BlockPos, Integer>> getActiveEffectPowders(World world, AxisAlignedBB area, ResourceLocation name);
/**
* Returns true if there is an effect powder entity active anywhere
* around the given position based on the radius it has. To register a
* powder with the supplied name, use {@link #EFFECT_POWDERS}
* around the given position based on the radius it has. This is a
* shorthand function of {@link #getActiveEffectPowders(World,
* AxisAlignedBB, ResourceLocation)} that returns true if the list is
* non-empty
*
* @param world The world
* @param pos The center position

View file

@ -5,9 +5,13 @@ import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
import de.ellpeck.naturesaura.api.multiblock.IMultiblock;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
public class StubHooks implements NaturesAuraAPI.IInternalHooks {
@ -46,6 +50,11 @@ public class StubHooks implements NaturesAuraAPI.IInternalHooks {
return new StubMultiblock();
}
@Override
public List<Tuple<BlockPos, Integer>> getActiveEffectPowders(World world, AxisAlignedBB area, ResourceLocation name) {
return Collections.emptyList();
}
@Override
public boolean isEffectPowderActive(World world, BlockPos pos, ResourceLocation name) {
return false;

View file

@ -0,0 +1,13 @@
package de.ellpeck.naturesaura.api.recipes;
import net.minecraft.util.WeightedRandom;
public class WeightedOre extends WeightedRandom.Item {
public final String name;
public WeightedOre(String name, int weight) {
super(weight);
this.name = name;
}
}

View file

@ -14,9 +14,11 @@ public final class DrainSpotEffects {
NaturesAuraAPI.DRAIN_SPOT_EFFECTS.put(SpreadEffect.NAME, SpreadEffect::new);
NaturesAuraAPI.DRAIN_SPOT_EFFECTS.put(CacheRechargeEffect.NAME, CacheRechargeEffect::new);
NaturesAuraAPI.DRAIN_SPOT_EFFECTS.put(AnimalEffect.NAME, AnimalEffect::new);
NaturesAuraAPI.DRAIN_SPOT_EFFECTS.put(OreSpawnEffect.NAME, OreSpawnEffect::new);
NaturesAuraAPI.EFFECT_POWDERS.put(PlantBoostEffect.NAME, 0xc2f442);
NaturesAuraAPI.EFFECT_POWDERS.put(CacheRechargeEffect.NAME, 0x1fb0d1);
NaturesAuraAPI.EFFECT_POWDERS.put(AnimalEffect.NAME, 0xc842f4);
NaturesAuraAPI.EFFECT_POWDERS.put(OreSpawnEffect.NAME, 0x74edd8);
}
}

View file

@ -0,0 +1,134 @@
package de.ellpeck.naturesaura.chunk.effect;
import de.ellpeck.naturesaura.ModConfig;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect;
import de.ellpeck.naturesaura.api.aura.type.IAuraType;
import de.ellpeck.naturesaura.api.recipes.WeightedOre;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Tuple;
import net.minecraft.util.WeightedRandom;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.oredict.OreDictionary;
import java.util.List;
public class OreSpawnEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "ore_spawn");
private int amount;
private int dist;
private boolean calcValues(World world, BlockPos pos, Integer spot) {
if (spot <= 0)
return false;
int aura = IAuraChunk.getAuraInArea(world, pos, 30);
if (aura <= 2000000)
return false;
this.amount = Math.min(20, MathHelper.ceil(Math.abs(aura) / 300000F / IAuraChunk.getSpotAmountInArea(world, pos, 30)));
if (this.amount <= 0)
return false;
this.dist = MathHelper.clamp(Math.abs(aura) / 150000, 5, 20);
return true;
}
@Override
public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (!this.calcValues(player.world, pos, spot))
return -1;
if (player.getDistanceSq(pos) > this.dist * this.dist)
return -1;
if (!NaturesAuraAPI.instance().isEffectPowderActive(player.world, player.getPosition(), NAME))
return 0;
return 1;
}
@Override
public ItemStack getDisplayIcon() {
return new ItemStack(Blocks.DIAMOND_ORE);
}
@Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (world.getTotalWorldTime() % 40 != 0)
return;
if (!this.calcValues(world, pos, spot))
return;
IAuraType type = auraChunk.getType();
Block requiredBlock;
List<WeightedOre> ores;
if (type.isSimilar(NaturesAuraAPI.TYPE_OVERWORLD)) {
requiredBlock = Blocks.STONE;
ores = NaturesAuraAPI.OVERWORLD_ORES;
} else {
requiredBlock = Blocks.NETHERRACK;
ores = NaturesAuraAPI.NETHER_ORES;
}
int totalWeight = WeightedRandom.getTotalWeight(ores);
List<Tuple<BlockPos, Integer>> powders = NaturesAuraAPI.instance().getActiveEffectPowders(world,
new AxisAlignedBB(pos).grow(this.dist), NAME);
if (powders.isEmpty())
return;
for (int i = 0; i < this.amount; i++) {
Tuple<BlockPos, Integer> powder = powders.get(i % powders.size());
BlockPos powderPos = powder.getFirst();
int range = powder.getSecond();
int x = MathHelper.floor(powderPos.getX() + world.rand.nextGaussian() * range);
int y = MathHelper.floor(powderPos.getY() + world.rand.nextGaussian() * range);
int z = MathHelper.floor(powderPos.getZ() + world.rand.nextGaussian() * range);
BlockPos orePos = new BlockPos(x, y, z);
if (orePos.distanceSq(powderPos) <= range * range && orePos.distanceSq(pos) <= this.dist * this.dist && world.isBlockLoaded(orePos)) {
IBlockState state = world.getBlockState(orePos);
Block block = state.getBlock();
if (block != requiredBlock)
continue;
while (true) {
WeightedOre ore = WeightedRandom.getRandomItem(world.rand, ores, totalWeight);
List<ItemStack> stacks = OreDictionary.getOres(ore.name, false);
for (ItemStack stack : stacks) {
if (stack.isEmpty())
continue;
Block toPlace = Block.getBlockFromItem(stack.getItem());
if (toPlace == Blocks.AIR)
continue;
IBlockState stateToPlace = toPlace.getDefaultState();
world.setBlockState(orePos, stateToPlace);
world.playEvent(2001, orePos, Block.getStateId(stateToPlace));
int toDrain = (20000 - ore.itemWeight * 2) * 2;
BlockPos highestSpot = IAuraChunk.getHighestSpot(world, orePos, 30, pos);
IAuraChunk.getAuraChunk(world, highestSpot).drainAura(highestSpot, toDrain);
return;
}
}
}
}
}
@Override
public boolean appliesHere(Chunk chunk, IAuraChunk auraChunk, IAuraType type) {
return ModConfig.enabledFeatures.oreEffect &&
(type.isSimilar(NaturesAuraAPI.TYPE_OVERWORLD) || type.isSimilar(NaturesAuraAPI.TYPE_NETHER));
}
@Override
public ResourceLocation getName() {
return NAME;
}
}

View file

@ -3,10 +3,7 @@ package de.ellpeck.naturesaura.recipes;
import de.ellpeck.naturesaura.Helper;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.recipes.AltarRecipe;
import de.ellpeck.naturesaura.api.recipes.AnimalSpawnerRecipe;
import de.ellpeck.naturesaura.api.recipes.OfferingRecipe;
import de.ellpeck.naturesaura.api.recipes.TreeRitualRecipe;
import de.ellpeck.naturesaura.api.recipes.*;
import de.ellpeck.naturesaura.api.recipes.ing.AmountIngredient;
import de.ellpeck.naturesaura.api.recipes.ing.NBTIngredient;
import de.ellpeck.naturesaura.blocks.ModBlocks;
@ -273,6 +270,66 @@ public final class ModRecipes {
spawner("wither_skeleton", "minecraft:wither_skeleton", 150000, 150, Ingredient.fromItem(Items.BONE), Helper.blockIng(Blocks.OBSIDIAN));
spawner("wolf", "minecraft:wolf", 50000, 60, Ingredient.fromItem(Items.LEATHER), Ingredient.fromItem(Items.BONE));
spawner("zombie", "minecraft:zombie", 100000, 100, Ingredient.fromItem(Items.ROTTEN_FLESH));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreCoal", 5000));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherCoal", 5000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreIron", 3000));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherIron", 3000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreGold", 500));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherGold", 500));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreDiamond", 50));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherDiamond", 50));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreLapis", 250));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherLapis", 250));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreRedstone", 200));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherRedstone", 200));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreEmerald", 30));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreQuartz", 3000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreCopper", 2000));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherCopper", 2000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreTin", 1800));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherTin", 1800));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreLead", 1500));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherLead", 1500));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreSilver", 1000));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherSilver", 1000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreNickel", 100));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherNickel", 100));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePlatinum", 20));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreNetherPlatinum", 20));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreAluminum", 1200));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreAluminium", 1200));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreOsmium", 1500));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreZinc", 1000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreYellorite", 1200));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreUranium", 400));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreCertusQuartz", 800));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreApatite", 700));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreQuartzBlack", 3000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreRuby", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePeridot", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreTopaz", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreTanzanite", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreMalachite", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreSapphire", 40));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreAmber", 150));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreResonating", 50));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreSulfur", 3000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreSaltpeter", 250));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreFirestone", 30));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreSalt", 2900));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("oreDraconium", 5));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorIron", 3000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorGold", 500));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorCopper", 2000));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorTin", 1800));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorLead", 1500));
NaturesAuraAPI.OVERWORLD_ORES.add(new WeightedOre("orePoorSilver", 1000));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreCobalt", 50));
NaturesAuraAPI.NETHER_ORES.add(new WeightedOre("oreArdite", 50));
}
private static void spawner(String name, String entity, int aura, int time, Ingredient... ings) {