From 932d4ed039cfe927b5e8107264a8638f3816ca1c Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 Jan 2020 20:49:09 +0100 Subject: [PATCH] fixed the server and brought back the chunk loader! --- .../java/de/ellpeck/naturesaura/Helper.java | 2 +- .../naturesaura/blocks/BlockChunkLoader.java | 27 +- .../blocks/tiles/TileEntityChunkLoader.java | 98 ++- .../ellpeck/naturesaura/items/AuraBottle.java | 62 +- .../naturesaura/items/BirthSpirit.java | 32 +- .../naturesaura/items/RangeVisualizer.java | 31 +- .../naturesaura/items/tools/Armor.java | 29 +- .../naturesaura/packet/PacketAuraChunk.java | 1 - .../naturesaura/packet/PacketClient.java | 24 +- .../packet/PacketParticleStream.java | 1 - .../naturesaura/packet/PacketParticles.java | 720 +++++++++--------- .../renderers/PlayerLayerTrinkets.java | 4 + .../renderers/SupporterFancyHandler.java | 2 +- .../models/block/chunk_loader.json | 15 +- 14 files changed, 532 insertions(+), 516 deletions(-) diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index 9c0df454..2e377d1a 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -63,7 +63,7 @@ public final class Helper { if (chunk != null) { for (BlockPos tilePos : chunk.getTileEntitiesPos()) { if (tilePos.distanceSq(pos) <= radius * radius) - if (consumer.apply(world.getTileEntity(tilePos))) + if (consumer.apply(chunk.getTileEntity(tilePos))) return true; } } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java index 272fca81..5a09d528 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java @@ -27,14 +27,6 @@ public class BlockChunkLoader extends BlockContainerImpl implements IVisualizabl super("chunk_loader", TileEntityChunkLoader::new, ModBlocks.prop(Material.ROCK).hardnessAndResistance(3F).sound(SoundType.STONE)); } - /* TODO Chunk Loading - @Override - public void onInit(FMLInitializationEvent event) { - super.onInit(event); - ForgeChunkManager.setForcedChunkLoadingCallback(NaturesAura.instance, new ChunkLoadingCallback()); - } - */ - @Override @OnlyIn(Dist.CLIENT) public AxisAlignedBB getVisualizationBounds(World world, BlockPos pos) { @@ -78,22 +70,5 @@ public class BlockChunkLoader extends BlockContainerImpl implements IVisualizabl public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { return SHAPE; } - - // TODO chunk loading - /*public static class ChunkLoadingCallback implements ForgeChunkManager.LoadingCallback { - - @Override - public void ticketsLoaded(List tickets, World world) { - for (Ticket ticket : tickets) { - CompoundNBT data = ticket.getModData(); - BlockPos pos = BlockPos.fromLong(data.getLong("pos")); - TileEntity tile = world.getTileEntity(pos); - if (!(tile instanceof TileEntityChunkLoader)) - continue; - TileEntityChunkLoader loader = (TileEntityChunkLoader) tile; - loader.updateTicket(ticket); - loader.loadChunks(); - } - } - }*/ + } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java index 645c4fcc..e0c67d1f 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java @@ -1,73 +1,84 @@ package de.ellpeck.naturesaura.blocks.tiles; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.world.server.ServerWorld; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; -// TODO chunk loader public class TileEntityChunkLoader extends TileEntityImpl implements ITickableTileEntity { + + private final List forcedChunks = new ArrayList<>(); + public TileEntityChunkLoader() { super(ModTileEntities.CHUNK_LOADER); } - //private Ticket ticket; -/* @Override public void validate() { super.validate(); - if (!this.world.isRemote && this.ticket == null) { - Ticket ticket = ForgeChunkManager.requestTicket(NaturesAura.instance, this.world, Type.NORMAL); - this.updateTicket(ticket); - ticket.getModData().setLong("pos", this.pos.toLong()); - } + this.loadChunks(false); } @Override - public void invalidate() { - super.invalidate(); - if (!this.world.isRemote) - this.updateTicket(null); + public void remove() { + super.remove(); + this.loadChunks(true); } @Override public void onRedstonePowerChange(int newPower) { super.onRedstonePowerChange(newPower); if (!this.world.isRemote) { - this.loadChunks(); + this.loadChunks(false); this.sendToClients(); } - }*/ + } public int range() { return this.redstonePower * 2; } - /*public void updateTicket(Ticket ticket) { - if (this.ticket != null) - ForgeChunkManager.releaseTicket(this.ticket); - this.ticket = ticket; - } - - public void loadChunks() { - if (this.ticket == null) + private void loadChunks(boolean unload) { + if (this.world.isRemote) return; - Set before = new HashSet<>(this.ticket.getChunkList()); - int range = this.range(); - if (range > 0) { - for (int x = (this.pos.getX() - range) >> 4; x <= (this.pos.getX() + range) >> 4; x++) { - for (int z = (this.pos.getZ() - range) >> 4; z <= (this.pos.getZ() + range) >> 4; z++) { - ChunkPos pos = new ChunkPos(x, z); - if (!before.contains(pos)) - ForgeChunkManager.forceChunk(this.ticket, pos); - else - before.remove(pos); + ServerWorld world = (ServerWorld) this.world; + + List shouldBeForced = new ArrayList<>(); + if (!unload) { + int range = this.range(); + if (range > 0) { + for (int x = (this.pos.getX() - range) >> 4; x <= (this.pos.getX() + range) >> 4; x++) { + for (int z = (this.pos.getZ() - range) >> 4; z <= (this.pos.getZ() + range) >> 4; z++) { + ChunkPos pos = new ChunkPos(x, z); + // Only force chunks that we're already forcing or that nobody else is forcing + if (this.forcedChunks.contains(pos) || !world.getForcedChunks().contains(pos.asLong())) + shouldBeForced.add(pos); + } } } } - for (ChunkPos pos : before) - ForgeChunkManager.unforceChunk(this.ticket, pos); - }*/ + + // Unforce all of the chunks that shouldn't be forced anymore + for (ChunkPos pos : this.forcedChunks) { + if (!shouldBeForced.contains(pos)) + world.forceChunk(pos.x, pos.z, false); + } + this.forcedChunks.clear(); + + // Force all chunks that should be forced + for (ChunkPos pos : shouldBeForced) { + world.forceChunk(pos.x, pos.z, true); + this.forcedChunks.add(pos); + } + } @Override public void tick() { @@ -81,4 +92,21 @@ public class TileEntityChunkLoader extends TileEntityImpl implements ITickableTi } } } + + @Override + public void writeNBT(CompoundNBT compound, SaveType type) { + super.writeNBT(compound, type); + if (type == SaveType.TILE) + compound.putLongArray("forced_chunks", this.forcedChunks.stream().map(ChunkPos::asLong).collect(Collectors.toList())); + } + + @Override + public void readNBT(CompoundNBT compound, SaveType type) { + super.readNBT(compound, type); + + if (type == SaveType.TILE) { + this.forcedChunks.clear(); + Arrays.stream(compound.getLongArray("forced_chunks")).mapToObj(ChunkPos::new).forEach(this.forcedChunks::add); + } + } } diff --git a/src/main/java/de/ellpeck/naturesaura/items/AuraBottle.java b/src/main/java/de/ellpeck/naturesaura/items/AuraBottle.java index ab869333..e8c9ea4d 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/AuraBottle.java +++ b/src/main/java/de/ellpeck/naturesaura/items/AuraBottle.java @@ -31,7 +31,7 @@ public class AuraBottle extends ItemImpl implements IColorProvidingItem { public AuraBottle(Item emptyBottle) { super("aura_bottle", new Properties().group(NaturesAura.CREATIVE_TAB)); - MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new EventHandler()); DispenserBlock.registerDispenseBehavior(emptyBottle, (source, stack) -> { World world = source.getWorld(); @@ -55,34 +55,6 @@ public class AuraBottle extends ItemImpl implements IColorProvidingItem { }); } - @SubscribeEvent - public void onRightClick(PlayerInteractEvent.RightClickItem event) { - ItemStack held = event.getItemStack(); - if (held.isEmpty() || held.getItem() != ModItems.BOTTLE_TWO_THE_REBOTTLING) - return; - PlayerEntity player = event.getPlayer(); - RayTraceResult ray = rayTrace(player.world, player, RayTraceContext.FluidMode.NONE); - if (ray.getType() == RayTraceResult.Type.BLOCK) - return; - BlockPos pos = player.getPosition(); - if (IAuraChunk.getAuraInArea(player.world, pos, 30) < 100000) - return; - - if (!player.world.isRemote) { - held.shrink(1); - - player.inventory.addItemStackToInventory( - setType(new ItemStack(this), IAuraType.forWorld(player.world))); - - BlockPos spot = IAuraChunk.getHighestSpot(player.world, pos, 30, pos); - IAuraChunk.getAuraChunk(player.world, spot).drainAura(spot, 20000); - - player.world.playSound(null, player.posX, player.posY, player.posZ, - SoundEvents.ITEM_BOTTLE_FILL_DRAGONBREATH, SoundCategory.PLAYERS, 1F, 1F); - } - player.swingArm(event.getHand()); - } - @Override public void fillItemGroup(ItemGroup tab, NonNullList items) { if (this.isInGroup(tab)) { @@ -118,4 +90,36 @@ public class AuraBottle extends ItemImpl implements IColorProvidingItem { public IItemColor getItemColor() { return (stack, tintIndex) -> tintIndex > 0 ? getType(stack).getColor() : 0xFFFFFF; } + + private class EventHandler { + + @SubscribeEvent + public void onRightClick(PlayerInteractEvent.RightClickItem event) { + ItemStack held = event.getItemStack(); + if (held.isEmpty() || held.getItem() != ModItems.BOTTLE_TWO_THE_REBOTTLING) + return; + PlayerEntity player = event.getPlayer(); + RayTraceResult ray = rayTrace(player.world, player, RayTraceContext.FluidMode.NONE); + if (ray.getType() == RayTraceResult.Type.BLOCK) + return; + BlockPos pos = player.getPosition(); + if (IAuraChunk.getAuraInArea(player.world, pos, 30) < 100000) + return; + + if (!player.world.isRemote) { + held.shrink(1); + + player.inventory.addItemStackToInventory( + setType(new ItemStack(AuraBottle.this), IAuraType.forWorld(player.world))); + + BlockPos spot = IAuraChunk.getHighestSpot(player.world, pos, 30, pos); + IAuraChunk.getAuraChunk(player.world, spot).drainAura(spot, 20000); + + player.world.playSound(null, player.posX, player.posY, player.posZ, + SoundEvents.ITEM_BOTTLE_FILL_DRAGONBREATH, SoundCategory.PLAYERS, 1F, 1F); + } + player.swingArm(event.getHand()); + } + + } } diff --git a/src/main/java/de/ellpeck/naturesaura/items/BirthSpirit.java b/src/main/java/de/ellpeck/naturesaura/items/BirthSpirit.java index 1878f6e8..ac6a9cac 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/BirthSpirit.java +++ b/src/main/java/de/ellpeck/naturesaura/items/BirthSpirit.java @@ -12,25 +12,27 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; public class BirthSpirit extends Glowing { public BirthSpirit() { super("birth_spirit"); - MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new EventHandler()); } - @SubscribeEvent - public void onBabyBorn(BabyEntitySpawnEvent event) { - LivingEntity parent = event.getParentA(); - if (!parent.world.isRemote && event.getCausedByPlayer() != null) { - BlockPos pos = parent.getPosition(); - int aura = IAuraChunk.getAuraInArea(parent.world, pos, 30); - if (aura < 1200000) - return; + private static class EventHandler { + @SubscribeEvent + public void onBabyBorn(BabyEntitySpawnEvent event) { + LivingEntity parent = event.getParentA(); + if (!parent.world.isRemote && event.getCausedByPlayer() != null) { + BlockPos pos = parent.getPosition(); + int aura = IAuraChunk.getAuraInArea(parent.world, pos, 30); + if (aura < 1200000) + return; - int amount = parent.world.rand.nextInt(3) + 1; - ItemEntity item = new ItemEntity(parent.world, parent.posX, parent.posY, parent.posZ, - new ItemStack(ModItems.BIRTH_SPIRIT, amount)); - parent.world.addEntity(item); + int amount = parent.world.rand.nextInt(3) + 1; + ItemEntity item = new ItemEntity(parent.world, parent.posX, parent.posY, parent.posZ, + new ItemStack(ModItems.BIRTH_SPIRIT, amount)); + parent.world.addEntity(item); - BlockPos spot = IAuraChunk.getHighestSpot(parent.world, pos, 30, pos); - IAuraChunk.getAuraChunk(parent.world, spot).drainAura(spot, 800 * amount); + BlockPos spot = IAuraChunk.getHighestSpot(parent.world, pos, 30, pos); + IAuraChunk.getAuraChunk(parent.world, spot).drainAura(spot, 800 * amount); + } } } } diff --git a/src/main/java/de/ellpeck/naturesaura/items/RangeVisualizer.java b/src/main/java/de/ellpeck/naturesaura/items/RangeVisualizer.java index cc76c840..b56e48d1 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/RangeVisualizer.java +++ b/src/main/java/de/ellpeck/naturesaura/items/RangeVisualizer.java @@ -29,7 +29,7 @@ public class RangeVisualizer extends ItemImpl { public RangeVisualizer() { super("range_visualizer", new Properties().maxStackSize(1).group(NaturesAura.CREATIVE_TAB)); - MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new EventHandler()); } @Override @@ -76,20 +76,23 @@ public class RangeVisualizer extends ItemImpl { } } - @SubscribeEvent - public void onInteract(PlayerInteractEvent.EntityInteractSpecific event) { - ItemStack stack = event.getItemStack(); - if (stack.isEmpty() || stack.getItem() != this) - return; - Entity entity = event.getTarget(); - if (entity instanceof IVisualizable) { - if (entity.world.isRemote) { - DimensionType dim = entity.world.getDimension().getType(); - visualize(event.getPlayer(), VISUALIZED_ENTITIES, dim, entity); + public class EventHandler { + + @SubscribeEvent + public void onInteract(PlayerInteractEvent.EntityInteractSpecific event) { + ItemStack stack = event.getItemStack(); + if (stack.isEmpty() || stack.getItem() != RangeVisualizer.this) + return; + Entity entity = event.getTarget(); + if (entity instanceof IVisualizable) { + if (entity.world.isRemote) { + DimensionType dim = entity.world.getDimension().getType(); + visualize(event.getPlayer(), VISUALIZED_ENTITIES, dim, entity); + } + event.getPlayer().swingArm(event.getHand()); + event.setCancellationResult(ActionResultType.SUCCESS); + event.setCanceled(true); } - event.getPlayer().swingArm(event.getHand()); - event.setCancellationResult(ActionResultType.SUCCESS); - event.setCanceled(true); } } } diff --git a/src/main/java/de/ellpeck/naturesaura/items/tools/Armor.java b/src/main/java/de/ellpeck/naturesaura/items/tools/Armor.java index ff17d743..1c4f59dd 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/tools/Armor.java +++ b/src/main/java/de/ellpeck/naturesaura/items/tools/Armor.java @@ -33,22 +33,10 @@ public class Armor extends ArmorItem implements IModItem, IModelProvider { public Armor(String baseName, IArmorMaterial materialIn, EquipmentSlotType equipmentSlotIn) { super(materialIn, equipmentSlotIn, new Properties().group(NaturesAura.CREATIVE_TAB)); this.baseName = baseName; - MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new EventHandler()); ModRegistry.add(this); } - @SubscribeEvent - public void onAttack(LivingAttackEvent event) { - LivingEntity entity = event.getEntityLiving(); - if (!entity.world.isRemote) { - if (!isFullSetEquipped(entity, 0)) - return; - Entity source = event.getSource().getTrueSource(); - if (source instanceof LivingEntity) - ((LivingEntity) source).addPotionEffect(new EffectInstance(Effects.WITHER, 40)); - } - } - @Override public String getBaseName() { return this.baseName; @@ -75,4 +63,19 @@ public class Armor extends ArmorItem implements IModItem, IModelProvider { } return true; } + + private static class EventHandler { + + @SubscribeEvent + public void onAttack(LivingAttackEvent event) { + LivingEntity entity = event.getEntityLiving(); + if (!entity.world.isRemote) { + if (!isFullSetEquipped(entity, 0)) + return; + Entity source = event.getSource().getTrueSource(); + if (source instanceof LivingEntity) + ((LivingEntity) source).addPotionEffect(new EffectInstance(Effects.WITHER, 40)); + } + } + } } diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketAuraChunk.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketAuraChunk.java index 053522ab..7193af12 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketAuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketAuraChunk.java @@ -70,7 +70,6 @@ public class PacketAuraChunk { return true; } - @OnlyIn(Dist.CLIENT) public static void onMessage(PacketAuraChunk message, Supplier ctx) { ctx.get().enqueueWork(() -> ClientEvents.PENDING_AURA_CHUNKS.add(message)); ctx.get().setPacketHandled(true); diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketClient.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketClient.java index ae2ed7ea..ceb4554d 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketClient.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketClient.java @@ -5,8 +5,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; import net.minecraft.world.dimension.DimensionType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.network.NetworkEvent; import java.util.function.Supplier; @@ -41,16 +39,20 @@ public class PacketClient { buf.writeInt(i); } - @OnlyIn(Dist.CLIENT) + // lambda causes classloading issues on a server here + @SuppressWarnings("Convert2Lambda") public static void onMessage(PacketClient message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - Minecraft mc = Minecraft.getInstance(); - if (mc.world != null) { - switch (message.type) { - case 0: // dimension rail visualization - int goalDim = message.data[0]; - BlockPos goalPos = new BlockPos(message.data[1], message.data[2], message.data[3]); - RangeVisualizer.visualize(mc.player, RangeVisualizer.VISUALIZED_RAILS, DimensionType.getById(goalDim), goalPos); + ctx.get().enqueueWork(new Runnable() { + @Override + public void run() { + Minecraft mc = Minecraft.getInstance(); + if (mc.world != null) { + switch (message.type) { + case 0: // dimension rail visualization + int goalDim = message.data[0]; + BlockPos goalPos = new BlockPos(message.data[1], message.data[2], message.data[3]); + RangeVisualizer.visualize(mc.player, RangeVisualizer.VISUALIZED_RAILS, DimensionType.getById(goalDim), goalPos); + } } } }); diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java index b5b25895..17ab842a 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java @@ -65,7 +65,6 @@ public class PacketParticleStream { buf.writeFloat(packet.scale); } - @OnlyIn(Dist.CLIENT) public static void onMessage(PacketParticleStream message, Supplier ctx) { ctx.get().enqueueWork(() -> NaturesAuraAPI.instance().spawnParticleStream( message.startX, message.startY, message.startZ, diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index f2c6b428..ffd7a528 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -12,8 +12,6 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeColors; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.network.NetworkEvent; import java.util.function.Supplier; @@ -65,373 +63,377 @@ public class PacketParticles { } } - @OnlyIn(Dist.CLIENT) + // lambda causes classloading issues on a server here + @SuppressWarnings("Convert2Lambda") public static void onMessage(PacketParticles message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - World world = Minecraft.getInstance().world; - if (world != null) { - switch (message.type) { - case 0: // Tree ritual: Gold powder - BlockPos pos = new BlockPos(message.posX, message.posY, message.posZ); - Multiblocks.TREE_RITUAL.forEach(pos, 'G', (dustPos, matcher) -> { - BlockState state = world.getBlockState(dustPos); - AxisAlignedBB box = state.getShape(world, dustPos).getBoundingBox(); - NaturesAuraAPI.instance().spawnMagicParticle( - dustPos.getX() + box.minX + (box.maxX - box.minX) * world.rand.nextFloat(), - dustPos.getY() + 0.1F, - dustPos.getZ() + box.minZ + (box.maxZ - box.minZ) * world.rand.nextFloat(), - (float) world.rand.nextGaussian() * 0.02F, - world.rand.nextFloat() * 0.01F + 0.02F, - (float) world.rand.nextGaussian() * 0.02F, - 0xf4cb42, 2F, 50, 0F, false, true); - return true; - }); - break; - case 1: // Tree ritual: Consuming item - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.5F, message.posY + 0.9F, message.posZ + 0.5F, - (float) world.rand.nextGaussian() * 0.04F, world.rand.nextFloat() * 0.04F, (float) world.rand.nextGaussian() * 0.04F, - 0x89cc37, 1.5F, 25, 0F, false, true); - } - break; - case 2: // Tree ritual: Tree disappearing - for (int i = world.rand.nextInt(5) + 3; i >= 0; i--) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat(), message.posY + world.rand.nextFloat(), message.posZ + world.rand.nextFloat(), - 0F, 0F, 0F, - 0x33FF33, 1F, 50, 0F, false, true); - } - break; - case 3: // Tree ritual: Spawn result item - for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY, message.posZ, - world.rand.nextGaussian() * 0.1F, world.rand.nextGaussian() * 0.1F, world.rand.nextGaussian() * 0.1F, - 0x89cc37, 2F, 100, 0F, true, true); - } - break; - case 4: // Nature altar: Conversion - for (int i = world.rand.nextInt(5) + 2; i >= 0; i--) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.25F + world.rand.nextFloat() * 0.5F, - message.posY + 0.9F + 0.25F * world.rand.nextFloat(), - message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.02F, world.rand.nextFloat() * 0.02F, world.rand.nextGaussian() * 0.02F, - 0x00FF00, world.rand.nextFloat() * 1.5F + 0.75F, 20, 0F, false, true); - } - break; - case 5: // Potion generator - int color = message.data[0]; - boolean releaseAura = message.data[1] > 0; - for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat(), - message.posY + 1.1F, - message.posZ + world.rand.nextFloat(), - world.rand.nextGaussian() * 0.01F, world.rand.nextFloat() * 0.1F, world.rand.nextGaussian() * 0.01F, - color, 2F + world.rand.nextFloat(), 40, 0F, true, true); + ctx.get().enqueueWork(new Runnable() { + @Override + public void run() { + World world = Minecraft.getInstance().world; + if (world != null) { + switch (message.type) { + case 0: // Tree ritual: Gold powder + BlockPos pos = new BlockPos(message.posX, message.posY, message.posZ); + Multiblocks.TREE_RITUAL.forEach(pos, 'G', (dustPos, matcher) -> { + BlockState state = world.getBlockState(dustPos); + AxisAlignedBB box = state.getShape(world, dustPos).getBoundingBox(); + NaturesAuraAPI.instance().spawnMagicParticle( + dustPos.getX() + box.minX + (box.maxX - box.minX) * world.rand.nextFloat(), + dustPos.getY() + 0.1F, + dustPos.getZ() + box.minZ + (box.maxZ - box.minZ) * world.rand.nextFloat(), + (float) world.rand.nextGaussian() * 0.02F, + world.rand.nextFloat() * 0.01F + 0.02F, + (float) world.rand.nextGaussian() * 0.02F, + 0xf4cb42, 2F, 50, 0F, false, true); + return true; + }); + break; + case 1: // Tree ritual: Consuming item + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.5F, message.posY + 0.9F, message.posZ + 0.5F, + (float) world.rand.nextGaussian() * 0.04F, world.rand.nextFloat() * 0.04F, (float) world.rand.nextGaussian() * 0.04F, + 0x89cc37, 1.5F, 25, 0F, false, true); + } + break; + case 2: // Tree ritual: Tree disappearing + for (int i = world.rand.nextInt(5) + 3; i >= 0; i--) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), message.posY + world.rand.nextFloat(), message.posZ + world.rand.nextFloat(), + 0F, 0F, 0F, + 0x33FF33, 1F, 50, 0F, false, true); + } + break; + case 3: // Tree ritual: Spawn result item + for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY, message.posZ, + world.rand.nextGaussian() * 0.1F, world.rand.nextGaussian() * 0.1F, world.rand.nextGaussian() * 0.1F, + 0x89cc37, 2F, 100, 0F, true, true); + } + break; + case 4: // Nature altar: Conversion + for (int i = world.rand.nextInt(5) + 2; i >= 0; i--) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.25F + world.rand.nextFloat() * 0.5F, + message.posY + 0.9F + 0.25F * world.rand.nextFloat(), + message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.02F, world.rand.nextFloat() * 0.02F, world.rand.nextGaussian() * 0.02F, + 0x00FF00, world.rand.nextFloat() * 1.5F + 0.75F, 20, 0F, false, true); + } + break; + case 5: // Potion generator + int color = message.data[0]; + boolean releaseAura = message.data[1] > 0; + for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), + message.posY + 1.1F, + message.posZ + world.rand.nextFloat(), + world.rand.nextGaussian() * 0.01F, world.rand.nextFloat() * 0.1F, world.rand.nextGaussian() * 0.01F, + color, 2F + world.rand.nextFloat(), 40, 0F, true, true); - if (releaseAura) - for (int x = -1; x <= 1; x += 2) - for (int z = -1; z <= 1; z += 2) { - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + x * 3 + 0.5F, - message.posY + 2.5, - message.posZ + z * 3 + 0.5F, - world.rand.nextGaussian() * 0.02F, - world.rand.nextFloat() * 0.04F, - world.rand.nextGaussian() * 0.02F, - 0xd6340c, 1F + world.rand.nextFloat() * 2F, 75, 0F, true, true); - } - } - break; - case 6: // Plant boost effect - for (int i = world.rand.nextInt(20) + 15; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat(), - message.posY + 0.25F + world.rand.nextFloat() * 0.5F, - message.posZ + world.rand.nextFloat(), - 0F, world.rand.nextFloat() * 0.02F, 0F, - 0x5ccc30, 1F + world.rand.nextFloat() * 2F, 50, 0F, false, true); + if (releaseAura) + for (int x = -1; x <= 1; x += 2) + for (int z = -1; z <= 1; z += 2) { + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + x * 3 + 0.5F, + message.posY + 2.5, + message.posZ + z * 3 + 0.5F, + world.rand.nextGaussian() * 0.02F, + world.rand.nextFloat() * 0.04F, + world.rand.nextGaussian() * 0.02F, + 0xd6340c, 1F + world.rand.nextFloat() * 2F, 75, 0F, true, true); + } + } + break; + case 6: // Plant boost effect + for (int i = world.rand.nextInt(20) + 15; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), + message.posY + 0.25F + world.rand.nextFloat() * 0.5F, + message.posZ + world.rand.nextFloat(), + 0F, world.rand.nextFloat() * 0.02F, 0F, + 0x5ccc30, 1F + world.rand.nextFloat() * 2F, 50, 0F, false, true); - break; - case 7: // Flower generator consumation - color = message.data[0]; - for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.25F + world.rand.nextFloat() * 0.5F, - message.posY + 0.25F + world.rand.nextFloat() * 0.5F, - message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.02F, - world.rand.nextGaussian() * 0.02F, - world.rand.nextGaussian() * 0.02F, - color, world.rand.nextFloat() * 2F + 1F, 25, 0F, false, true); - break; - case 8: // Flower generator, firework generator aura creation - for (int i = world.rand.nextInt(10) + 5; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.25F + world.rand.nextFloat() * 0.5F, - message.posY + 1.01F, - message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.04F + 0.02F, - world.rand.nextGaussian() * 0.01F, - 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); - break; - case 9: // Placer placing - for (int i = world.rand.nextInt(20) + 20; i >= 0; i--) { - boolean side = world.rand.nextBoolean(); - float x = side ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); - float z = !side ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + x, message.posY + 0.1F + world.rand.nextFloat() * 0.98F, message.posZ + z, - 0F, 0F, 0F, - 0xad7a37, world.rand.nextFloat() + 1F, 50, 0F, true, true); - } - break; - case 10: // Hopper upgrade picking up - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.45F, message.posZ, - world.rand.nextGaussian() * 0.015F, - world.rand.nextGaussian() * 0.015F, - world.rand.nextGaussian() * 0.015F, - 0xdde7ff, world.rand.nextFloat() + 1F, 30, -0.06F, true, true); - break; - case 11: // Shockwave creator particles - for (int i = 0; i < 360; i += 2) { - double rad = Math.toRadians(i); - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.01F, message.posZ, - (float) Math.sin(rad) * 0.65F, - 0F, - (float) Math.cos(rad) * 0.65F, - 0x911b07, 3F, 10, 0F, false, true); - } - break; - case 12: // Oak generator - int sapX = message.data[0]; - int sapY = message.data[1]; - int sapZ = message.data[2]; - releaseAura = message.data[3] > 0; - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnParticleStream( - sapX + 0.5F + (float) world.rand.nextGaussian() * 3F, - sapY + 0.5F + world.rand.nextFloat() * 4F, - sapZ + 0.5F + (float) world.rand.nextGaussian() * 3F, - message.posX + 0.5F, - message.posY + 0.5F, - message.posZ + 0.5F, - 0.6F, BiomeColors.getFoliageColor(world, new BlockPos(sapX, sapY, sapZ)), 1.5F); - if (releaseAura) + break; + case 7: // Flower generator consumation + color = message.data[0]; for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.25F + world.rand.nextFloat() * 0.5F, + message.posY + 0.25F + world.rand.nextFloat() * 0.5F, + message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.02F, + world.rand.nextGaussian() * 0.02F, + world.rand.nextGaussian() * 0.02F, + color, world.rand.nextFloat() * 2F + 1F, 25, 0F, false, true); + break; + case 8: // Flower generator, firework generator aura creation + for (int i = world.rand.nextInt(10) + 5; i >= 0; i--) NaturesAuraAPI.instance().spawnMagicParticle( message.posX + 0.25F + world.rand.nextFloat() * 0.5F, message.posY + 1.01F, message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.03F, - world.rand.nextFloat() * 0.04F + 0.04F, - world.rand.nextGaussian() * 0.03F, - 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 60, 0F, false, true); - break; - case 13: // Offering table - int genX = message.data[0]; - int genY = message.data[1]; - int genZ = message.data[2]; - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.04F + 0.02F, + world.rand.nextGaussian() * 0.01F, + 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); + break; + case 9: // Placer placing + for (int i = world.rand.nextInt(20) + 20; i >= 0; i--) { + boolean side = world.rand.nextBoolean(); + float x = side ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); + float z = !side ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + x, message.posY + 0.1F + world.rand.nextFloat() * 0.98F, message.posZ + z, + 0F, 0F, 0F, + 0xad7a37, world.rand.nextFloat() + 1F, 50, 0F, true, true); + } + break; + case 10: // Hopper upgrade picking up + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY + 0.45F, message.posZ, + world.rand.nextGaussian() * 0.015F, + world.rand.nextGaussian() * 0.015F, + world.rand.nextGaussian() * 0.015F, + 0xdde7ff, world.rand.nextFloat() + 1F, 30, -0.06F, true, true); + break; + case 11: // Shockwave creator particles + for (int i = 0; i < 360; i += 2) { + double rad = Math.toRadians(i); + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY + 0.01F, message.posZ, + (float) Math.sin(rad) * 0.65F, + 0F, + (float) Math.cos(rad) * 0.65F, + 0x911b07, 3F, 10, 0F, false, true); + } + break; + case 12: // Oak generator + int sapX = message.data[0]; + int sapY = message.data[1]; + int sapZ = message.data[2]; + releaseAura = message.data[3] > 0; + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnParticleStream( + sapX + 0.5F + (float) world.rand.nextGaussian() * 3F, + sapY + 0.5F + world.rand.nextFloat() * 4F, + sapZ + 0.5F + (float) world.rand.nextGaussian() * 3F, + message.posX + 0.5F, + message.posY + 0.5F, + message.posZ + 0.5F, + 0.6F, BiomeColors.getFoliageColor(world, new BlockPos(sapX, sapY, sapZ)), 1.5F); + if (releaseAura) + for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.25F + world.rand.nextFloat() * 0.5F, + message.posY + 1.01F, + message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.03F, + world.rand.nextFloat() * 0.04F + 0.04F, + world.rand.nextGaussian() * 0.03F, + 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 60, 0F, false, true); + break; + case 13: // Offering table + int genX = message.data[0]; + int genY = message.data[1]; + int genZ = message.data[2]; + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY + 0.5F, message.posZ, + world.rand.nextGaussian() * 0.02F, + world.rand.nextFloat() * 0.25F, + world.rand.nextGaussian() * 0.02F, + 0xffadfd, 1.5F, 40, 0F, false, true); + for (int i = world.rand.nextInt(50) + 30; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + genX + 0.5F + world.rand.nextGaussian() * 2.5F, + genY + 0.1F, + genZ + 0.5F + world.rand.nextGaussian() * 2.5F, + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.01F, + world.rand.nextGaussian() * 0.01F, + 0xd3e4ff, 1.5F, 150, 0F, false, true); + break; + case 14: // Pickup stopper NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.5F, message.posZ, - world.rand.nextGaussian() * 0.02F, - world.rand.nextFloat() * 0.25F, - world.rand.nextGaussian() * 0.02F, - 0xffadfd, 1.5F, 40, 0F, false, true); - for (int i = world.rand.nextInt(50) + 30; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - genX + 0.5F + world.rand.nextGaussian() * 2.5F, - genY + 0.1F, - genZ + 0.5F + world.rand.nextGaussian() * 2.5F, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.01F, - world.rand.nextGaussian() * 0.01F, - 0xd3e4ff, 1.5F, 150, 0F, false, true); - break; - case 14: // Pickup stopper - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.4F, message.posZ, - world.rand.nextGaussian() * 0.005F, - world.rand.nextFloat() * 0.005F, - world.rand.nextGaussian() * 0.005F, - 0xcc3116, 1.5F, 40, 0F, false, true); - break; - case 15: // Spawn lamp - for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.3F + world.rand.nextFloat() * 0.4F, - message.posY + 0.15F + world.rand.nextFloat() * 0.5F, - message.posZ + 0.3F + world.rand.nextFloat() * 0.4F, - 0F, 0F, 0F, - 0xf4a142, 1F, 30, 0F, false, true); - break; - case 16: // Animal generator aura creation - for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + 0.25F + world.rand.nextFloat() * 0.5F, - message.posY + 1.01F, - message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.04F + 0.02F, - world.rand.nextGaussian() * 0.01F, - 0xd13308, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); - break; - case 17: // Animal generator consuming - boolean child = message.data[0] > 0; - float height = message.data[1] / 10F; - genX = message.data[2]; - genY = message.data[3]; - genZ = message.data[4]; - for (int i = (child ? world.rand.nextInt(10) + 10 : world.rand.nextInt(20) + 20); i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextGaussian() * 0.25F, - message.posY + height * 0.75F + world.rand.nextGaussian() * 0.25F, - message.posZ + world.rand.nextGaussian() * 0.25F, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.01F, - world.rand.nextGaussian() * 0.01F, - 0x42f4c8, world.rand.nextFloat() * (child ? 0.5F : 2F) + 1F, world.rand.nextInt(30) + 40, 0F, true, true); - NaturesAuraAPI.instance().spawnParticleStream( - message.posX, message.posY + height * 0.75F, message.posZ, - genX + 0.5F, genY + 0.5F, genZ + 0.5F, - 0.15F, 0x41c4f4, child ? 1.5F : 3F); - break; - case 18: // End flower decay - color = message.data[0]; - for (int i = world.rand.nextInt(10) + 20; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat(), - message.posY + world.rand.nextFloat(), - message.posZ + world.rand.nextFloat(), - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.01F, - world.rand.nextGaussian() * 0.01F, - color, 1.5F, 80, 0F, true, true); - break; - case 19: // Animal spawner, auto crafter - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.5F, message.posZ, - world.rand.nextGaussian() * 0.02F, - world.rand.nextFloat() * 0.02F, - world.rand.nextGaussian() * 0.02F, - 0x16b7b2, 1.5F, 40, 0F, false, true); - break; - case 20: // RF converter - for (int i = world.rand.nextInt(5) + 2; i >= 0; i--) - Multiblocks.RF_CONVERTER.forEach(new BlockPos(message.posX, message.posY, message.posZ), 'R', (blockPos, matcher) -> { - if (world.rand.nextFloat() < 0.35F) { - NaturesAuraAPI.instance().spawnParticleStream( - blockPos.getX() + world.rand.nextFloat(), - blockPos.getY() + world.rand.nextFloat(), - blockPos.getZ() + world.rand.nextFloat(), - message.posX + world.rand.nextFloat(), - message.posY + world.rand.nextFloat(), - message.posZ + world.rand.nextFloat(), - 0.05F, 0xff1a05, 1.5F); - } - return true; - }); - break; - case 21: // End flower item consuming - color = message.data[0]; - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX, message.posY + 0.5F, message.posZ, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.01F, - world.rand.nextGaussian() * 0.01F, - color, 1.5F, 40, 0F, false, true); - break; - case 22: // Mover cart - float motionX = message.data[0] / 100F; - float motionY = message.data[1] / 100F; - float motionZ = message.data[2] / 100F; - for (int i = world.rand.nextInt(60) + 30; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextGaussian() * 10F, - message.posY + world.rand.nextGaussian() * 10F, - message.posZ + world.rand.nextGaussian() * 10F, - motionX * 0.2F, motionY * 0.2F, motionZ * 0.2F, - IAuraType.forWorld(world).getColor(), 2F, 30, 0F, false, true); - break; - case 23: // Moss generator - for (int i = world.rand.nextInt(30) + 30; i >= 0; i--) { - int side = world.rand.nextInt(3); - float x = side != 0 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); - float y = side != 1 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); - float z = side != 2 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + x, - message.posY + y, - message.posZ + z, - 0F, 0F, 0F, - 0x184c0d, world.rand.nextFloat() + 1F, 30, 0F, true, true); - } - for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat(), - message.posY + 1F, - message.posZ + world.rand.nextFloat(), - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.04F + 0.02F, - world.rand.nextGaussian() * 0.01F, - 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, true, true); - break; - case 24: // Firework generator - int goalX = message.data[0]; - int goalY = message.data[1]; - int goalZ = message.data[2]; - NaturesAuraAPI.instance().setParticleSpawnRange(64); - for (int i = world.rand.nextInt(30) + 30; i >= 0; i--) + message.posX, message.posY + 0.4F, message.posZ, + world.rand.nextGaussian() * 0.005F, + world.rand.nextFloat() * 0.005F, + world.rand.nextGaussian() * 0.005F, + 0xcc3116, 1.5F, 40, 0F, false, true); + break; + case 15: // Spawn lamp + for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.3F + world.rand.nextFloat() * 0.4F, + message.posY + 0.15F + world.rand.nextFloat() * 0.5F, + message.posZ + 0.3F + world.rand.nextFloat() * 0.4F, + 0F, 0F, 0F, + 0xf4a142, 1F, 30, 0F, false, true); + break; + case 16: // Animal generator aura creation + for (int i = world.rand.nextInt(5) + 5; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.25F + world.rand.nextFloat() * 0.5F, + message.posY + 1.01F, + message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.04F + 0.02F, + world.rand.nextGaussian() * 0.01F, + 0xd13308, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); + break; + case 17: // Animal generator consuming + boolean child = message.data[0] > 0; + float height = message.data[1] / 10F; + genX = message.data[2]; + genY = message.data[3]; + genZ = message.data[4]; + for (int i = (child ? world.rand.nextInt(10) + 10 : world.rand.nextInt(20) + 20); i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextGaussian() * 0.25F, + message.posY + height * 0.75F + world.rand.nextGaussian() * 0.25F, + message.posZ + world.rand.nextGaussian() * 0.25F, + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.01F, + world.rand.nextGaussian() * 0.01F, + 0x42f4c8, world.rand.nextFloat() * (child ? 0.5F : 2F) + 1F, world.rand.nextInt(30) + 40, 0F, true, true); NaturesAuraAPI.instance().spawnParticleStream( - message.posX + (float) world.rand.nextGaussian(), - message.posY + (float) world.rand.nextGaussian(), - message.posZ + (float) world.rand.nextGaussian(), - goalX + 0.25F + world.rand.nextFloat() * 0.5F, - goalY + 0.25F + world.rand.nextFloat() * 0.5F, - goalZ + 0.25F + world.rand.nextFloat() * 0.5F, - 0.65F, message.data[3 + world.rand.nextInt(message.data.length - 3)], 1F); - NaturesAuraAPI.instance().setParticleSpawnRange(32); - break; - case 25: // Dimension rail - float width = message.data[0] / 100F; - height = message.data[1] / 100F; - float depth = message.data[2] / 100F; - for (int i = world.rand.nextInt(100) + 50; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - message.posX + world.rand.nextFloat() * width, - message.posY + world.rand.nextFloat() * height, - message.posZ + world.rand.nextFloat() * depth, - 0F, 0F, 0F, 0xd60cff, 1F + world.rand.nextFloat(), 60, 0F, false, true); - break; - case 26: // Projectile generator - int x = message.data[0]; - int y = message.data[1]; - int z = message.data[2]; - for (int i = world.rand.nextInt(10) + 5; i >= 0; i--) - NaturesAuraAPI.instance().spawnMagicParticle( - x + 0.25F + world.rand.nextFloat() * 0.5F, - y + 1.01F, - z + 0.25F + world.rand.nextFloat() * 0.5F, - world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.04F + 0.02F, - world.rand.nextGaussian() * 0.01F, - 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); - for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) - world.addParticle(ParticleTypes.FIREWORK, - message.posX, message.posY, message.posZ, - world.rand.nextGaussian() * 0.03F, - world.rand.nextGaussian() * 0.03F, - world.rand.nextGaussian() * 0.03F); + message.posX, message.posY + height * 0.75F, message.posZ, + genX + 0.5F, genY + 0.5F, genZ + 0.5F, + 0.15F, 0x41c4f4, child ? 1.5F : 3F); + break; + case 18: // End flower decay + color = message.data[0]; + for (int i = world.rand.nextInt(10) + 20; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), + message.posY + world.rand.nextFloat(), + message.posZ + world.rand.nextFloat(), + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.01F, + world.rand.nextGaussian() * 0.01F, + color, 1.5F, 80, 0F, true, true); + break; + case 19: // Animal spawner, auto crafter + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY + 0.5F, message.posZ, + world.rand.nextGaussian() * 0.02F, + world.rand.nextFloat() * 0.02F, + world.rand.nextGaussian() * 0.02F, + 0x16b7b2, 1.5F, 40, 0F, false, true); + break; + case 20: // RF converter + for (int i = world.rand.nextInt(5) + 2; i >= 0; i--) + Multiblocks.RF_CONVERTER.forEach(new BlockPos(message.posX, message.posY, message.posZ), 'R', (blockPos, matcher) -> { + if (world.rand.nextFloat() < 0.35F) { + NaturesAuraAPI.instance().spawnParticleStream( + blockPos.getX() + world.rand.nextFloat(), + blockPos.getY() + world.rand.nextFloat(), + blockPos.getZ() + world.rand.nextFloat(), + message.posX + world.rand.nextFloat(), + message.posY + world.rand.nextFloat(), + message.posZ + world.rand.nextFloat(), + 0.05F, 0xff1a05, 1.5F); + } + return true; + }); + break; + case 21: // End flower item consuming + color = message.data[0]; + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX, message.posY + 0.5F, message.posZ, + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.01F, + world.rand.nextGaussian() * 0.01F, + color, 1.5F, 40, 0F, false, true); + break; + case 22: // Mover cart + float motionX = message.data[0] / 100F; + float motionY = message.data[1] / 100F; + float motionZ = message.data[2] / 100F; + for (int i = world.rand.nextInt(60) + 30; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextGaussian() * 10F, + message.posY + world.rand.nextGaussian() * 10F, + message.posZ + world.rand.nextGaussian() * 10F, + motionX * 0.2F, motionY * 0.2F, motionZ * 0.2F, + IAuraType.forWorld(world).getColor(), 2F, 30, 0F, false, true); + break; + case 23: // Moss generator + for (int i = world.rand.nextInt(30) + 30; i >= 0; i--) { + int side = world.rand.nextInt(3); + float x = side != 0 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); + float y = side != 1 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); + float z = side != 2 ? world.rand.nextFloat() : (world.rand.nextBoolean() ? 1.1F : -0.1F); + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + x, + message.posY + y, + message.posZ + z, + 0F, 0F, 0F, + 0x184c0d, world.rand.nextFloat() + 1F, 30, 0F, true, true); + } + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), + message.posY + 1F, + message.posZ + world.rand.nextFloat(), + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.04F + 0.02F, + world.rand.nextGaussian() * 0.01F, + 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, true, true); + break; + case 24: // Firework generator + int goalX = message.data[0]; + int goalY = message.data[1]; + int goalZ = message.data[2]; + NaturesAuraAPI.instance().setParticleSpawnRange(64); + for (int i = world.rand.nextInt(30) + 30; i >= 0; i--) + NaturesAuraAPI.instance().spawnParticleStream( + message.posX + (float) world.rand.nextGaussian(), + message.posY + (float) world.rand.nextGaussian(), + message.posZ + (float) world.rand.nextGaussian(), + goalX + 0.25F + world.rand.nextFloat() * 0.5F, + goalY + 0.25F + world.rand.nextFloat() * 0.5F, + goalZ + 0.25F + world.rand.nextFloat() * 0.5F, + 0.65F, message.data[3 + world.rand.nextInt(message.data.length - 3)], 1F); + NaturesAuraAPI.instance().setParticleSpawnRange(32); + break; + case 25: // Dimension rail + float width = message.data[0] / 100F; + height = message.data[1] / 100F; + float depth = message.data[2] / 100F; + for (int i = world.rand.nextInt(100) + 50; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat() * width, + message.posY + world.rand.nextFloat() * height, + message.posZ + world.rand.nextFloat() * depth, + 0F, 0F, 0F, 0xd60cff, 1F + world.rand.nextFloat(), 60, 0F, false, true); + break; + case 26: // Projectile generator + int x = message.data[0]; + int y = message.data[1]; + int z = message.data[2]; + for (int i = world.rand.nextInt(10) + 5; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + x + 0.25F + world.rand.nextFloat() * 0.5F, + y + 1.01F, + z + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.04F + 0.02F, + world.rand.nextGaussian() * 0.01F, + 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 40, 0F, false, true); + for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) + world.addParticle(ParticleTypes.FIREWORK, + message.posX, message.posY, message.posZ, + world.rand.nextGaussian() * 0.03F, + world.rand.nextGaussian() * 0.03F, + world.rand.nextGaussian() * 0.03F); + } } } }); diff --git a/src/main/java/de/ellpeck/naturesaura/renderers/PlayerLayerTrinkets.java b/src/main/java/de/ellpeck/naturesaura/renderers/PlayerLayerTrinkets.java index 99149dd8..0f5b293b 100644 --- a/src/main/java/de/ellpeck/naturesaura/renderers/PlayerLayerTrinkets.java +++ b/src/main/java/de/ellpeck/naturesaura/renderers/PlayerLayerTrinkets.java @@ -36,6 +36,8 @@ public class PlayerLayerTrinkets extends LayerRenderer