diff --git a/README.md b/README.md
index ed04d270..02ca4b03 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
Avaritia Reforged is a Minecraft mod made for Minecraft Forge
@@ -16,14 +16,133 @@
简体中文
-This is a Minecraft 1.20.1 NeoForged mod.
-This mod adds all from Avaritia.
+
-## Authors
+
+
+
+## **📕Introduction:**
+* This mod adds all from Avaritia.
+* This mod is unofficial and have bugs!
+
+## ✏️Authors
- Programmer: `cnlimiter` `Asek3` `MikhailTapio`
-## License
+## 🔒License
- Code: [MIT](https://www.mit.edu/~amini/LICENSE.md)
- Assets: [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+
+## **📌Download official:**
+* [Avaritia (1.1x)](https://www.curseforge.com/minecraft/mc-mods/avaritia-1-10)
+* [Avaritia (official)](https://www.curseforge.com/minecraft/mc-mods/avaritia)
+* [AvaritiaLite](https://www.curseforge.com/minecraft/mc-mods/avaritia-lite)
+
+## **❗Attention:**
+* You DEFINITELY CAN add the mod to your modpack.
+* Recipe viewing is supported via JEI.
+* You can add singularity by using json!
+* You can add recipes by CraftTweaker!
+* You can add recipes by KubeJs!
+
+
+## **🔎Develop:**
+### **CraftTweaker:**
+```
+mods.avaritia.CompressionCrafting.addRecipe("name",input, inputCount, timeRequierd);
+mods.avaritia.CompressionCrafting.remove(output);
+mods.avaritia.ExtremeTableCrafting.addShaped("name",output, ingredients);
+mods.avaritia.ExtremeTableCrafting.addShapeless("name",output, ingredients);
+mods.avaritia.ExtremeTableCrafting.remove(output);
+```
+
+### **KubeJs:**
+```javascript
+//ExtremeCraft
+event.custom({
+ type: 'avaritia:shaped_extreme_craft',//Shaped Extreme Craft,Shapeless is avaritia:shapeless_extreme_craft
+ pattern: [
+ " II",
+ " III",
+ " III ",
+ " III ",
+ " C III ",
+ " CII ",
+ " NC ",
+ " N C ",
+ "X "
+ ],
+ key: {
+ C: [
+ Ingredient.of('avaritia:crystal_matrix_ingot').toJson()
+ ],
+ I: [
+ Ingredient.of('avaritia:infinity_ingot').toJson()
+ ],
+ N: [
+ Ingredient.of('avaritia:neutron_ingot').toJson()
+ ],
+ X: [
+ Ingredient.of('avaritia:infinity_catalyst').toJson()
+ ]
+ },
+ result: [
+ Ingredient.of('avaritia:infinity_sword').toJson()
+ ]
+})
+//Compressor
+event.custom({
+ type: 'avaritia:compressor',//Compressor Recipe
+ materialCount: 1000,
+ timeRequired: 240,
+ ingredients: [
+ Ingredient.of('#forge:ingots/bronze').toJson()
+ ],
+ result: [
+ Ingredient.of('avaritia:bronze_singularity').toJson()
+ ]
+})
+```
+### **InfinityCatalyst:**
+```json5
+{
+ "type": "avaritia:infinity_catalyst_craft",//Infinity Catalyst recipe type
+ "category": "misc",
+ "ingredients": [
+ {
+ "item": "minecraft:emerald_block"
+ },
+ {
+ "item": "avaritia:crystal_matrix_ingot"
+ },
+ {
+ "item": "avaritia:neutron_ingot"
+ },
+ {
+ "item": "avaritia:cosmic_meatballs"
+ },
+ {
+ "item": "avaritia:ultimate_stew"
+ },
+ {
+ "item": "avaritia:endest_pearl"
+ },
+ {
+ "item": "avaritia:record_fragment"
+ }
+ ],
+ "result": {
+ "item": "avaritia:infinity_catalyst"//Fixed products
+ }
+}
+```
+
+
+
diff --git a/src/main/java/committee/nova/mods/avaritia/Avaritia.java b/src/main/java/committee/nova/mods/avaritia/Avaritia.java
index 95ed535c..5f8d2c5e 100644
--- a/src/main/java/committee/nova/mods/avaritia/Avaritia.java
+++ b/src/main/java/committee/nova/mods/avaritia/Avaritia.java
@@ -1,5 +1,6 @@
package committee.nova.mods.avaritia;
+import committee.nova.mods.avaritia.client.shader.AvaritiaShaders;
import committee.nova.mods.avaritia.common.entity.EndestPearlEntity;
import committee.nova.mods.avaritia.init.config.ModConfig;
import committee.nova.mods.avaritia.init.data.ModDataGen;
@@ -44,6 +45,7 @@ public Avaritia() {
ModRecipeSerializers.SERIALIZERS.register(bus);
ModCreativeModeTabs.TABS.register(bus);
+ AvaritiaShaders.init();
ModConfig.register();
}
diff --git a/src/main/java/committee/nova/mods/avaritia/client/AvaritiaClient.java b/src/main/java/committee/nova/mods/avaritia/client/AvaritiaClient.java
index 913bc896..ec665ba3 100644
--- a/src/main/java/committee/nova/mods/avaritia/client/AvaritiaClient.java
+++ b/src/main/java/committee/nova/mods/avaritia/client/AvaritiaClient.java
@@ -3,6 +3,7 @@
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.api.iface.IColored;
import committee.nova.mods.avaritia.client.model.GapingVoidModel;
+import committee.nova.mods.avaritia.client.model.HaloItemModelLoader;
import committee.nova.mods.avaritia.client.model.WingModel;
import committee.nova.mods.avaritia.client.render.layer.EyeInfinityLayer;
import committee.nova.mods.avaritia.client.render.layer.WingInfinityLayer;
@@ -10,8 +11,10 @@
import committee.nova.mods.avaritia.util.ColorUtil;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
+import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
+import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.client.event.RegisterGuiOverlaysEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -43,7 +46,6 @@ public static void registerOverlays(RegisterGuiOverlaysEvent event) {
}
-
private static int getCurrentRainbowColor() {
var hue = (System.currentTimeMillis() % 18000) / 18000F;
return ColorUtil.hsbToRGB(hue, 1, 1);
diff --git a/src/main/java/committee/nova/mods/avaritia/client/model/HaloItemModelLoader.java b/src/main/java/committee/nova/mods/avaritia/client/model/HaloItemModelLoader.java
new file mode 100644
index 00000000..bb25a850
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/client/model/HaloItemModelLoader.java
@@ -0,0 +1,74 @@
+package committee.nova.mods.avaritia.client.model;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import it.unimi.dsi.fastutil.Pair;
+import it.unimi.dsi.fastutil.ints.IntList;
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import net.minecraft.client.renderer.block.model.BlockModel;
+import net.minecraft.client.renderer.block.model.ItemOverrides;
+import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.client.resources.model.*;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
+import net.minecraftforge.client.model.geometry.IGeometryLoader;
+import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.function.Function;
+
+/**
+ * Name: Avaritia-forge / HaloItemModelLoader
+ * Author: cnlimiter
+ * CreateTime: 2023/9/18 23:45
+ * Description:
+ */
+
+public class HaloItemModelLoader implements IGeometryLoader {
+
+
+
+ @Override
+ public HaloItemModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) throws JsonParseException {
+ return null;
+ }
+
+ public static class HaloItemModel implements IUnbakedGeometry{
+ private final BlockModel baseModel;
+ private final IntList layerColors;
+ private final String texture;
+ private final int color;
+ private final int size;
+ private final boolean pulse;
+ private Material haloMaterial;
+
+ public HaloItemModel(BlockModel baseModel, IntList layerColors, String texture, int color, int size, boolean pulse) {
+ this.baseModel = baseModel;
+ this.layerColors = layerColors;
+ this.texture = texture;
+ this.color = color;
+ this.size = size;
+ this.pulse = pulse;
+ }
+
+ @Override
+ public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) {
+ if (haloMaterial == null){
+ HashSet materials = new HashSet();
+ this.haloMaterial = context.getMaterial(this.texture);
+ materials.add(this.haloMaterial);
+// this.baseModel.resolveParents()
+// materials.addAll();
+ }
+
+
+ return null;
+ }
+
+
+
+ }
+}
diff --git a/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenArrowRender.java b/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenArrowRender.java
index e7e9e9b2..b0119670 100644
--- a/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenArrowRender.java
+++ b/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenArrowRender.java
@@ -1,7 +1,7 @@
package committee.nova.mods.avaritia.client.render.entity;
import committee.nova.mods.avaritia.Static;
-import committee.nova.mods.avaritia.common.entity.HeavenArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenArrowEntity;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
diff --git a/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenSubArrowRender.java b/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenSubArrowRender.java
index 337c42ca..7e681c12 100644
--- a/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenSubArrowRender.java
+++ b/src/main/java/committee/nova/mods/avaritia/client/render/entity/HeavenSubArrowRender.java
@@ -1,7 +1,7 @@
package committee.nova.mods.avaritia.client.render.entity;
import committee.nova.mods.avaritia.Static;
-import committee.nova.mods.avaritia.common.entity.HeavenSubArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenSubArrowEntity;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
diff --git a/src/main/java/committee/nova/mods/avaritia/client/render/entity/TracerArrowRender.java b/src/main/java/committee/nova/mods/avaritia/client/render/entity/TracerArrowRender.java
new file mode 100644
index 00000000..137bd35b
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/client/render/entity/TracerArrowRender.java
@@ -0,0 +1,35 @@
+package committee.nova.mods.avaritia.client.render.entity;
+
+import committee.nova.mods.avaritia.Static;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.TraceArrowEntity;
+import net.minecraft.client.renderer.entity.ArrowRenderer;
+import net.minecraft.client.renderer.entity.EntityRendererProvider;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Description:
+ * Author: cnlimiter
+ * Date: 2022/4/20 18:54
+ * Version: 1.0
+ */
+@OnlyIn(Dist.CLIENT)
+public class TracerArrowRender extends ArrowRenderer {
+
+ private static final ResourceLocation tex = new ResourceLocation(Static.MOD_ID, "textures/entity/heavenarrow.png");
+
+
+ public TracerArrowRender(EntityRendererProvider.Context p_174008_) {
+ super(p_174008_);
+ }
+
+ @Override
+ public @NotNull ResourceLocation getTextureLocation(@NotNull TraceArrowEntity entity) {
+ return tex;
+ }
+
+
+}
diff --git a/src/main/java/committee/nova/mods/avaritia/client/shader/AvaritiaShaders.java b/src/main/java/committee/nova/mods/avaritia/client/shader/AvaritiaShaders.java
new file mode 100644
index 00000000..a0bd8fe1
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/client/shader/AvaritiaShaders.java
@@ -0,0 +1,95 @@
+package committee.nova.mods.avaritia.client.shader;
+
+import com.mojang.blaze3d.shaders.Uniform;
+import com.mojang.blaze3d.vertex.DefaultVertexFormat;
+import com.mojang.blaze3d.vertex.VertexFormat;
+import committee.nova.mods.avaritia.Static;
+import committee.nova.mods.avaritia.util.client.SpriteRegistryHelper;
+import net.minecraft.client.renderer.RenderStateShard;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.ShaderInstance;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraftforge.client.event.RegisterShadersEvent;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Name: Avaritia-forge / AvaritiaShaders
+ * Author: cnlimiter
+ * CreateTime: 2023/9/18 1:37
+ * Description:
+ */
+
+public class AvaritiaShaders {
+ private static final float[] COSMIC_UVS = new float[40];
+ private static SpriteRegistryHelper SPRITE_HELPER;
+ private static int renderTime;
+ private static float renderFrame;
+ public static ShaderInstance cosmicShader;
+ public static Uniform cosmicTime;
+ public static Uniform cosmicYaw;
+ public static Uniform cosmicPitch;
+ public static Uniform cosmicExternalScale;
+ public static Uniform cosmicOpacity;
+ public static Uniform cosmicUVs;
+ public static RenderType COSMIC_RENDER_TYPE;
+
+ public static void init() {
+ var eventbus = FMLJavaModLoadingContext.get().getModEventBus();
+ SPRITE_HELPER = new SpriteRegistryHelper(eventbus);
+ eventbus.addListener(AvaritiaShaders::onRegisterShaders);
+ MinecraftForge.EVENT_BUS.addListener(AvaritiaShaders::onRenderTick);
+ MinecraftForge.EVENT_BUS.addListener(AvaritiaShaders::clientTick);
+ }
+
+ private static void onRegisterShaders(RegisterShadersEvent event){
+ try {
+ event.registerShader(new ShaderInstance(event.getResourceProvider(), new ResourceLocation(Static.MOD_ID, "cosmic"), DefaultVertexFormat.BLOCK), e -> {
+ cosmicShader = e;
+ cosmicTime = Objects.requireNonNull(cosmicShader.getUniform("time"));
+ cosmicYaw = Objects.requireNonNull(cosmicShader.getUniform("yaw"));
+ cosmicPitch = Objects.requireNonNull(cosmicShader.getUniform("pitch"));
+ cosmicExternalScale = Objects.requireNonNull(cosmicShader.getUniform("externalScale"));
+ cosmicOpacity = Objects.requireNonNull(cosmicShader.getUniform("opacity"));
+ cosmicUVs = Objects.requireNonNull(cosmicShader.getUniform("cosmicuvs"));
+ cosmicTime.set((float)renderTime + renderFrame);
+ cosmicShader.apply();
+ });
+ }catch (IOException ignore){
+
+ }
+
+ }
+
+ private static void onRenderTick(TickEvent.RenderTickEvent event) {
+ if (event.phase != TickEvent.Phase.START) return;
+ renderFrame = event.renderTickTime;
+ for (int i = 0; i < 10; ++i) {
+ TextureAtlasSprite sprite = SPRITE_HELPER.sprites.get(new ResourceLocation(Static.MOD_ID, "cosmic_" + i));
+ AvaritiaShaders.COSMIC_UVS[i * 4] = sprite.getU0();
+ AvaritiaShaders.COSMIC_UVS[i * 4 + 1] = sprite.getV0();
+ AvaritiaShaders.COSMIC_UVS[i * 4 + 2] = sprite.getU1();
+ AvaritiaShaders.COSMIC_UVS[i * 4 + 3] = sprite.getV1();
+ }
+ if (cosmicUVs != null) cosmicUVs.set(COSMIC_UVS);
+ }
+
+
+ private static void clientTick(TickEvent.ClientTickEvent event) {
+ if (event.phase == TickEvent.Phase.END) {
+ ++renderTime;
+ }
+ }
+
+
+ static {
+ COSMIC_RENDER_TYPE = RenderType.create(new ResourceLocation(Static.MOD_ID , "cosmic").toString() , DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS, 2097152, true, false, RenderType.CompositeState.builder().setShaderState(new RenderStateShard.ShaderStateShard(() -> {
+ return cosmicShader;
+ })).setDepthTestState(RenderStateShard.EQUAL_DEPTH_TEST).setLightmapState(RenderStateShard.LIGHTMAP).setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY).setTextureState(RenderStateShard.BLOCK_SHEET_MIPPED).createCompositeState(true));
+ }
+}
diff --git a/src/main/java/committee/nova/mods/avaritia/common/entity/HeavenArrowEntity.java b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenArrowEntity.java
similarity index 74%
rename from src/main/java/committee/nova/mods/avaritia/common/entity/HeavenArrowEntity.java
rename to src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenArrowEntity.java
index 18b4d90b..a5e3ce98 100644
--- a/src/main/java/committee/nova/mods/avaritia/common/entity/HeavenArrowEntity.java
+++ b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenArrowEntity.java
@@ -1,10 +1,11 @@
-package committee.nova.mods.avaritia.common.entity;
+package committee.nova.mods.avaritia.common.entity.arrow;
import committee.nova.mods.avaritia.init.registry.ModEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
+import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
@@ -46,43 +47,16 @@ public void setShooter(LivingEntity shooter) {
protected void onHitEntity(@NotNull EntityHitResult result) {
super.onHitEntity(result);
Entity entity = result.getEntity();
- var pos = new BlockPos(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
var randy = getCommandSenderWorld().random;
if (entity instanceof LivingEntity living) {
-
- for (int i = 0; i < 30; i++) {
- double angle = randy.nextDouble() * 2 * Math.PI;
- double dist = randy.nextGaussian() * 0.5;
-
- double x = Math.sin(angle) * dist + pos.getX();
- double z = Math.cos(angle) * dist + pos.getZ();
- double y = pos.getY() + 25.0;
-
- double dangle = randy.nextDouble() * 2 * Math.PI;
- double ddist = randy.nextDouble() * 0.35;
- double dx = Math.sin(dangle) * ddist;
- double dz = Math.cos(dangle) * ddist;
-
- HeavenSubArrowEntity subArrow = HeavenSubArrowEntity.create(getCommandSenderWorld(), x, y, z);
- if (shooter != null) subArrow.setOwner(shooter);
- subArrow.piercedAndKilledEntities = piercedAndKilledEntities;
- subArrow.push(dx, -(randy.nextDouble() * 1.85 + 0.15), dz);
- subArrow.setCritArrow(true);
- subArrow.pickup = pickup;
-
- getCommandSenderWorld().addFreshEntity(subArrow);
- }
-
+ var pos = living.getOnPos();
+ barrage(randy, pos);
this.remove(RemovalReason.KILLED);
}
}
- @Override
- protected void onHitBlock(@NotNull BlockHitResult result) {
- super.onHitBlock(result);
- var pos = result.getBlockPos();
- var randy = getCommandSenderWorld().random;
+ private void barrage(RandomSource randy, BlockPos pos) {
for (int i = 0; i < 30; i++) {
double angle = randy.nextDouble() * 2 * Math.PI;
double dist = randy.nextGaussian() * 0.5;
@@ -105,6 +79,14 @@ protected void onHitBlock(@NotNull BlockHitResult result) {
getCommandSenderWorld().addFreshEntity(subArrow);
}
+ }
+
+ @Override
+ protected void onHitBlock(@NotNull BlockHitResult result) {
+ super.onHitBlock(result);
+ var pos = result.getBlockPos();
+ var randy = getCommandSenderWorld().random;
+ barrage(randy, pos);
remove(RemovalReason.KILLED);
}
diff --git a/src/main/java/committee/nova/mods/avaritia/common/entity/HeavenSubArrowEntity.java b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenSubArrowEntity.java
similarity index 97%
rename from src/main/java/committee/nova/mods/avaritia/common/entity/HeavenSubArrowEntity.java
rename to src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenSubArrowEntity.java
index 0fcc4374..2864f299 100644
--- a/src/main/java/committee/nova/mods/avaritia/common/entity/HeavenSubArrowEntity.java
+++ b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/HeavenSubArrowEntity.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.common.entity;
+package committee.nova.mods.avaritia.common.entity.arrow;
import committee.nova.mods.avaritia.init.config.ModConfig;
import committee.nova.mods.avaritia.init.registry.ModEntities;
diff --git a/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/TraceArrowEntity.java b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/TraceArrowEntity.java
new file mode 100644
index 00000000..eb8803d0
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/common/entity/arrow/TraceArrowEntity.java
@@ -0,0 +1,691 @@
+package committee.nova.mods.avaritia.common.entity.arrow;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import committee.nova.mods.avaritia.init.registry.ModDamageTypes;
+import committee.nova.mods.avaritia.init.registry.ModEntities;
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+import net.minecraft.advancements.CriteriaTriggers;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.particles.ParticleTypes;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientGamePacketListener;
+import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
+import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket;
+import net.minecraft.network.syncher.EntityDataAccessor;
+import net.minecraft.network.syncher.EntityDataSerializers;
+import net.minecraft.network.syncher.SynchedEntityData;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.util.Mth;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.damagesource.DamageTypes;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.effect.MobEffects;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.ai.targeting.TargetingConditions;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.entity.projectile.AbstractArrow;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.item.ShieldItem;
+import net.minecraft.world.item.alchemy.Potion;
+import net.minecraft.world.item.alchemy.PotionUtils;
+import net.minecraft.world.item.alchemy.Potions;
+import net.minecraft.world.item.enchantment.EnchantmentHelper;
+import net.minecraft.world.level.ClipContext;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.phys.*;
+import net.minecraft.world.phys.shapes.VoxelShape;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
+import net.minecraftforge.event.ForgeEventFactory;
+import net.minecraftforge.network.NetworkHooks;
+import net.minecraftforge.registries.ForgeRegistries;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/**
+ * Name: Avaritia-forge / TraceArrowEntity
+ * Author: cnlimiter
+ * CreateTime: 2023/9/23 16:34
+ * Description:
+ */
+
+public class TraceArrowEntity extends AbstractArrow {
+ private static final EntityDataAccessor ID_EFFECT_COLOR;
+ private Potion potion;
+ private final Set effects;
+ private boolean fixedColor;
+ private LivingEntity homingTarget;
+ private Vec3 seekOrigin;
+ private int homingTime;
+ private static final EntityDataAccessor SPECTRAL_TIME;
+ private static final EntityDataAccessor JUMP_COUNT;
+ private static final List projectileAntiImmuneEntities;
+ private final Entity owner = this.getOwner() == null ? this : this.getOwner();
+
+ public TraceArrowEntity(EntityType extends AbstractArrow> entityType, Level world) {
+ super(entityType, world);
+ this.potion = Potions.EMPTY;
+ this.effects = Sets.newHashSet();
+ this.homingTarget = null;
+ this.seekOrigin = null;
+ this.homingTime = 0;
+ }
+
+ public TraceArrowEntity(Level world, double xPos, double yPos, double zPos) {
+ super(ModEntities.TRACE_ARROW.get(), xPos, yPos, zPos, world);
+ this.potion = Potions.EMPTY;
+ this.effects = Sets.newHashSet();
+ this.homingTarget = null;
+ this.seekOrigin = null;
+ this.homingTime = 0;
+ }
+
+ public TraceArrowEntity(Level world, LivingEntity shooter) {
+ super(ModEntities.TRACE_ARROW.get(), shooter, world);
+ this.potion = Potions.EMPTY;
+ this.effects = Sets.newHashSet();
+ this.homingTarget = null;
+ this.seekOrigin = null;
+ this.homingTime = 0;
+ }
+
+ public void setSpectral(int spectralTime) {
+ this.entityData.set(SPECTRAL_TIME, spectralTime);
+ }
+
+ public int getSpectralTime() {
+ return this.entityData.get(SPECTRAL_TIME);
+ }
+
+ public void setJumpCount(int jumpCount) {
+ this.entityData.set(JUMP_COUNT, jumpCount);
+ }
+
+ public int getJumpCount() {
+ return this.entityData.get(JUMP_COUNT);
+ }
+
+ @Override
+ public void tick() {
+ this.updateHoming();
+ this.superTick();
+ if (this.level().isClientSide) {
+ if (this.inGround) {
+ if (this.inGroundTime % 5 == 0) {
+ this.makeParticle(1);
+ }
+ } else {
+ this.makeParticle(2);
+ }
+ } else if (this.inGround && this.inGroundTime != 0 && !this.effects.isEmpty() && this.inGroundTime >= 600) {
+ this.level().broadcastEntityEvent(this, (byte)0);
+ this.potion = Potions.EMPTY;
+ this.effects.clear();
+ this.entityData.set(ID_EFFECT_COLOR, -1);
+ }
+
+ }
+
+ private void superTick() {
+ if (!this.leftOwner) {
+ this.leftOwner = this.checkLeftOwner();
+ }
+
+ if (!this.level().isClientSide) {
+ this.setSharedFlag(6, this.isCurrentlyGlowing());
+ }
+
+ this.baseTick();
+ boolean flag = this.isNoPhysics();
+ Vec3 vector3d = this.getDeltaMovement();
+ if (this.xRotO == 0.0F && this.yRotO == 0.0F) {
+ double f = vector3d.horizontalDistance();
+ this.setYRot((float)(Mth.atan2(vector3d.x, vector3d.z) * 57.2957763671875D));
+ this.setXRot((float)(Mth.atan2(vector3d.y, f) * 57.2957763671875D));
+ this.yRotO = this.getYRot();
+ this.xRotO = this.getXRot();
+ }
+
+ BlockPos blockpos = this.blockPosition();
+ BlockState blockstate = this.level().getBlockState(blockpos);
+ Vec3 vector3d3;
+ if (!blockstate.isAir() && !flag) {
+ VoxelShape voxelshape = blockstate.getCollisionShape(this.level(), blockpos);
+ if (!voxelshape.isEmpty()) {
+ vector3d3 = this.position();
+
+ for (AABB axisalignedbb : voxelshape.toAabbs()) {
+ if (axisalignedbb.move(blockpos).contains(vector3d3)) {
+ this.inGround = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (this.shakeTime > 0) {
+ --this.shakeTime;
+ }
+
+ if (this.isInWaterOrRain()) {
+ this.clearFire();
+ }
+
+ if (this.inGround && !flag) {
+ if (this.lastState != blockstate && this.shouldFall()) {
+ this.startFalling();
+ } else if (!this.level().isClientSide) {
+ this.tickDespawn();
+ }
+
+ ++this.inGroundTime;
+ } else {
+ this.inGroundTime = 0;
+ Vec3 vector3d2 = this.position();
+ vector3d3 = vector3d2.add(vector3d);
+ HitResult raytraceresult = this.level().clip(new ClipContext(vector3d2, vector3d3, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this));
+ if (raytraceresult.getType() != HitResult.Type.MISS) {
+ vector3d3 = raytraceresult.getLocation();
+ }
+
+ while(!this.isRemoved()) {
+ EntityHitResult entityraytraceresult = this.findHitEntity(vector3d2, vector3d3);
+ if (entityraytraceresult != null) {
+ raytraceresult = entityraytraceresult;
+ }
+
+ if (raytraceresult != null && raytraceresult.getType() == HitResult.Type.ENTITY) {
+ Entity entity = ((EntityHitResult)raytraceresult).getEntity();
+ Entity entity1 = this.getOwner();
+ if (entity instanceof Player && entity1 instanceof Player && !((Player)entity1).canHarmPlayer((Player)entity)) {
+ raytraceresult = null;
+ entityraytraceresult = null;
+ }
+ }
+
+ if (raytraceresult != null && raytraceresult.getType() != HitResult.Type.MISS && !flag && !ForgeEventFactory.onProjectileImpact(this, raytraceresult)) {
+ this.onHit(raytraceresult);
+ this.hasImpulse = true;
+ }
+
+ if (entityraytraceresult == null || this.getPierceLevel() <= 0) {
+ break;
+ }
+
+ raytraceresult = null;
+ }
+
+ vector3d = this.getDeltaMovement();
+ double d3 = vector3d.x;
+ double d4 = vector3d.y;
+ double d0 = vector3d.z;
+ if (this.isCritArrow()) {
+ for(int i = 0; i < 4; ++i) {
+ this.level().addParticle(ParticleTypes.CRIT, this.getX() + d3 * (double)i / 4.0D, this.getY() + d4 * (double)i / 4.0D, this.getZ() + d0 * (double)i / 4.0D, -d3, -d4 + 0.2D, -d0);
+ }
+ }
+
+ double d5 = this.getX() + d3;
+ double d1 = this.getY() + d4;
+ double d2 = this.getZ() + d0;
+ double f1 = vector3d.horizontalDistance();
+ if (flag) {
+ this.setYRot((float)(Mth.atan2(-d3, -d0) * 57.2957763671875D));
+ } else {
+ this.setYRot((float)(Mth.atan2(d3, d0) * 57.2957763671875D));
+ }
+
+ this.setXRot((float)(Mth.atan2(d4, f1) * 57.2957763671875D));
+ this.setXRot(lerpRotation(this.xRotO, this.getXRot()));
+ this.setYRot(lerpRotation(this.yRotO, this.getYRot()));
+ float f2 = 0.99F;
+ float f3 = 0.05F;
+ if (this.isInWater()) {
+ for(int j = 0; j < 4; ++j) {
+ float f4 = 0.25F;
+ this.level().addParticle(ParticleTypes.BUBBLE, d5 - d3 * 0.25D, d1 - d4 * 0.25D, d2 - d0 * 0.25D, d3, d4, d0);
+ }
+
+ f2 = this.getWaterInertia();
+ }
+
+ this.setDeltaMovement(vector3d.scale((double)f2));
+ if (!this.isNoGravity() && !flag) {
+ Vec3 vector3d4 = this.getDeltaMovement();
+ this.setDeltaMovement(vector3d4.x, vector3d4.y - 0.05000000074505806D, vector3d4.z);
+ }
+
+ this.setPos(d5, d1, d2);
+ this.checkInsideBlocks();
+ }
+
+ }
+
+ @Override
+ protected void onHitEntity(EntityHitResult p_213868_1_) {
+ Entity entity = p_213868_1_.getEntity();
+ float f = (float)this.getDeltaMovement().length();
+ int i = Mth.ceil(Mth.clamp((double)f * this.getBaseDamage(), 0.0D, 2.147483647E9D));
+ if (this.getPierceLevel() > 0) {
+ if (this.piercingIgnoreEntityIds == null) {
+ this.piercingIgnoreEntityIds = new IntOpenHashSet(5);
+ }
+
+ if (this.piercedAndKilledEntities == null) {
+ this.piercedAndKilledEntities = Lists.newArrayListWithCapacity(5);
+ }
+
+ if (this.piercingIgnoreEntityIds.size() >= this.getPierceLevel() + 1) {
+ this.discard();
+ return;
+ }
+
+ this.piercingIgnoreEntityIds.add(entity.getId());
+ }
+
+ if (this.isCritArrow()) {
+ long j = (long)this.random.nextInt(i / 2 + 2);
+ i = (int)Math.min(j + (long)i, 2147483647L);
+ }
+
+ Entity owner = this.getOwner() == null ? this : this.getOwner();
+ DamageSource damagesource = this.getDamageSource(entity);
+ boolean isEnderman = entity.getType() == EntityType.ENDERMAN;
+ int k = entity.getRemainingFireTicks();
+ if (this.isOnFire() && !isEnderman) {
+ entity.setSecondsOnFire(5);
+ }
+
+ if (entity instanceof Player player) {
+ if (player.isUsingItem() && player.getUseItem().getItem() instanceof ShieldItem) {
+ player.getCooldowns().addCooldown(player.getUseItem().getItem(), 100);
+ this.level().broadcastEntityEvent(player, (byte)30);
+ player.stopUsingItem();
+ }
+ }
+
+ if (entity.hurt(damagesource, (float)i)) {
+ if (entity instanceof LivingEntity livingentity) {
+ if (!this.level().isClientSide && this.getPierceLevel() <= 0) {
+ livingentity.setArrowCount(livingentity.getArrowCount() + 1);
+ }
+
+ if (this.knockback > 0) {
+ Vec3 vector3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale((double)this.knockback * 0.6D);
+ if (vector3d.lengthSqr() > 0.0D) {
+ livingentity.push(vector3d.x, 0.1D, vector3d.z);
+ }
+ }
+
+ if (!this.level().isClientSide && owner instanceof LivingEntity) {
+ EnchantmentHelper.doPostHurtEffects(livingentity, owner);
+ EnchantmentHelper.doPostDamageEffects((LivingEntity)owner, livingentity);
+ }
+
+ this.doPostHurtEffects(livingentity);
+ if (livingentity != owner && livingentity instanceof Player && owner instanceof ServerPlayer && !this.isSilent()) {
+ ((ServerPlayer)owner).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.ARROW_HIT_PLAYER, 0.0F));
+ }
+
+ if (!entity.isAlive() && this.piercedAndKilledEntities != null) {
+ this.piercedAndKilledEntities.add(livingentity);
+ }
+
+ if (!this.level().isClientSide && owner instanceof ServerPlayer serverplayerentity) {
+ if (this.piercedAndKilledEntities != null && this.shotFromCrossbow()) {
+ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverplayerentity, this.piercedAndKilledEntities);
+ } else if (!entity.isAlive() && this.shotFromCrossbow()) {
+ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverplayerentity, Arrays.asList(entity));
+ }
+ }
+ }
+
+ this.playSound(this.getHitGroundSoundEvent(), 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
+ if (this.getPierceLevel() <= 0) {
+ this.setDeltaMovement(this.getDeltaMovement().scale(0.0D));
+ this.setPos(entity.position());
+ this.seekNextTarget();
+ this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARROW_HIT, SoundSource.PLAYERS, 4.0F, 1.0F);
+ }
+ } else {
+ entity.setRemainingFireTicks(k);
+ this.setDeltaMovement(this.getDeltaMovement().scale(0.0D));
+ this.setYRot(this.getYRot() + 180.0F);
+ this.setPos(entity.position());
+ this.yRotO += 180.0F;
+ if (!this.level().isClientSide && this.getDeltaMovement().lengthSqr() < 1.0E-7D) {
+ if (this.pickup == Pickup.ALLOWED) {
+ this.spawnAtLocation(this.getPickupItem(), 0.1F);
+ }
+
+ this.seekNextTarget();
+ this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARROW_HIT, SoundSource.PLAYERS, 4.0F, 1.0F);
+ }
+ }
+
+ }
+
+ @Override
+ protected void onHitBlock(BlockHitResult hitResult) {
+ this.lastState = this.level().getBlockState(hitResult.getBlockPos());
+ BlockState blockstate = this.level().getBlockState(hitResult.getBlockPos());
+ blockstate.onProjectileHit(this.level(), blockstate, hitResult, this);
+ Vec3 vec3 = hitResult.getLocation().subtract(this.getX(), this.getY(), this.getZ());
+ this.setDeltaMovement(vec3);
+ Vec3 vec31 = vec3.normalize().scale(0.05000000074505806D);
+ this.setPosRaw(this.getX() - vec31.x, this.getY() - vec31.y, this.getZ() - vec31.z);
+ this.playSound(this.getHitGroundSoundEvent(), 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
+ this.seekNextTarget();
+ this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARROW_HIT, SoundSource.PLAYERS, 4.0F, 1.0F);
+ }
+
+ private DamageSource getDamageSource(Entity target) {
+ Entity owner = this.getOwner();
+ DamageSource damagesource;
+ if (owner == null) {
+ damagesource = target.damageSources().arrow(this, this);
+ } else {
+ damagesource = target.damageSources().arrow(this, owner);
+ if (owner instanceof LivingEntity) {
+ ((LivingEntity)owner).setLastHurtMob(target);
+ }
+ }
+
+ if (projectileAntiImmuneEntities.contains(Objects.requireNonNull(ForgeRegistries.ENTITY_TYPES.getKey(target.getType())).toString())) {
+ damagesource = ModDamageTypes.causeRandomDamage(owner);
+ }
+
+ return damagesource;
+ }
+
+ public void setEffectsFromItem(ItemStack p_184555_1_) {
+ if (p_184555_1_.getItem() == Items.TIPPED_ARROW) {
+ this.potion = PotionUtils.getPotion(p_184555_1_);
+ Collection collection = PotionUtils.getCustomEffects(p_184555_1_);
+ if (!collection.isEmpty()) {
+
+ for (MobEffectInstance effectinstance : collection) {
+ this.effects.add(new MobEffectInstance(effectinstance));
+ }
+ }
+
+ int i = getCustomColor(p_184555_1_);
+ if (i == -1) {
+ this.updateColor();
+ } else {
+ this.setFixedColor(i);
+ }
+ } else if (p_184555_1_.getItem() == Items.ARROW) {
+ this.potion = Potions.EMPTY;
+ this.effects.clear();
+ this.entityData.set(ID_EFFECT_COLOR, -1);
+ }
+
+ }
+
+ public static int getCustomColor(ItemStack p_191508_0_) {
+ CompoundTag compoundnbt = p_191508_0_.getTag();
+ return compoundnbt != null && compoundnbt.contains("CustomPotionColor", 99) ? compoundnbt.getInt("CustomPotionColor") : -1;
+ }
+
+ private void updateColor() {
+ this.fixedColor = false;
+ if (this.potion == Potions.EMPTY && this.effects.isEmpty()) {
+ this.entityData.set(ID_EFFECT_COLOR, -1);
+ } else {
+ this.entityData.set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects)));
+ }
+
+ }
+
+ public void addEffect(MobEffectInstance p_184558_1_) {
+ this.effects.add(p_184558_1_);
+ this.getEntityData().set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects)));
+ }
+
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+ this.entityData.define(ID_EFFECT_COLOR, -1);
+ this.entityData.define(SPECTRAL_TIME, 0);
+ this.entityData.define(JUMP_COUNT, 0);
+ }
+
+ private void makeParticle(int p_184556_1_) {
+ int i = this.getColor();
+ if (i != -1 && p_184556_1_ > 0) {
+ double d0 = (double)(i >> 16 & 255) / 255.0D;
+ double d1 = (double)(i >> 8 & 255) / 255.0D;
+ double d2 = (double)(i & 255) / 255.0D;
+
+ for(int j = 0; j < p_184556_1_; ++j) {
+ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2);
+ }
+ }
+
+ }
+
+ public int getColor() {
+ return this.entityData.get(ID_EFFECT_COLOR);
+ }
+
+ private void setFixedColor(int p_191507_1_) {
+ this.fixedColor = true;
+ this.entityData.set(ID_EFFECT_COLOR, p_191507_1_);
+ }
+
+ @Override
+ public void addAdditionalSaveData(@NotNull CompoundTag compound) {
+ super.addAdditionalSaveData(compound);
+ if (this.potion != Potions.EMPTY && this.potion != null) {
+ compound.putString("Potion", BuiltInRegistries.POTION.getKey(this.potion).toString());
+ }
+
+ if (this.fixedColor) {
+ compound.putInt("Color", this.getColor());
+ }
+
+ if (!this.effects.isEmpty()) {
+ ListTag listnbt = new ListTag();
+
+ for (MobEffectInstance effectinstance : this.effects) {
+ listnbt.add(effectinstance.save(new CompoundTag()));
+ }
+
+ compound.put("CustomPotionEffects", listnbt);
+ }
+
+ if (this.getSpectralTime() > 0) {
+ compound.putInt("spectral_time", this.entityData.get(SPECTRAL_TIME));
+ }
+
+ if (this.getJumpCount() > 0) {
+ compound.putInt("jump_count", this.entityData.get(JUMP_COUNT));
+ }
+
+ }
+
+ @Override
+ public void readAdditionalSaveData(@NotNull CompoundTag compound) {
+ super.readAdditionalSaveData(compound);
+ if (compound.contains("Potion", 8)) {
+ this.potion = PotionUtils.getPotion(compound);
+ }
+
+ for (MobEffectInstance effectinstance : PotionUtils.getCustomEffects(compound)) {
+ this.addEffect(effectinstance);
+ }
+
+ if (compound.contains("Color", 99)) {
+ this.setFixedColor(compound.getInt("Color"));
+ } else {
+ this.updateColor();
+ }
+
+ if (compound.contains("spectral_time")) {
+ this.setSpectral(compound.getInt("spectral_time"));
+ }
+
+ if (compound.contains("jump_count")) {
+ this.setJumpCount(compound.getInt("jump_count"));
+ }
+
+ }
+
+ @Override
+ protected void doPostHurtEffects(@NotNull LivingEntity livingEntity) {
+ super.doPostHurtEffects(livingEntity);
+ Iterator var2 = this.potion.getEffects().iterator();
+
+ MobEffectInstance effectinstance;
+ while(var2.hasNext()) {
+ effectinstance = var2.next();
+ livingEntity.addEffect(new MobEffectInstance(effectinstance.getEffect(), Math.max(effectinstance.getDuration() / 8, 1), effectinstance.getAmplifier(), effectinstance.isAmbient(), effectinstance.isVisible()));
+ }
+
+ if (!this.effects.isEmpty()) {
+ var2 = this.effects.iterator();
+
+ while(var2.hasNext()) {
+ effectinstance = var2.next();
+ livingEntity.addEffect(effectinstance);
+ }
+ }
+
+ int spectralTime = (Integer)this.entityData.get(SPECTRAL_TIME);
+ if (spectralTime > 0) {
+ effectinstance = new MobEffectInstance(MobEffects.GLOWING, spectralTime, 0);
+ livingEntity.addEffect(effectinstance);
+ }
+
+ }
+
+ @Override
+ protected @NotNull ItemStack getPickupItem() {
+ if (this.effects.isEmpty() && this.potion == Potions.EMPTY) {
+ return new ItemStack(Items.ARROW);
+ } else {
+ ItemStack itemstack = new ItemStack(Items.TIPPED_ARROW);
+ PotionUtils.setPotion(itemstack, this.potion);
+ PotionUtils.setCustomEffects(itemstack, this.effects);
+ if (this.fixedColor) {
+ itemstack.getOrCreateTag().putInt("CustomPotionColor", this.getColor());
+ }
+
+ return itemstack;
+ }
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ public void handleEntityEvent(byte p_70103_1_) {
+ if (p_70103_1_ == 0) {
+ int i = this.getColor();
+ if (i != -1) {
+ double d0 = (double)(i >> 16 & 255) / 255.0D;
+ double d1 = (double)(i >> 8 & 255) / 255.0D;
+ double d2 = (double)(i & 255) / 255.0D;
+
+ for(int j = 0; j < 20; ++j) {
+ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2);
+ }
+ }
+ } else {
+ super.handleEntityEvent(p_70103_1_);
+ }
+
+ }
+
+ @Override
+ public @NotNull Packet getAddEntityPacket() {
+ return NetworkHooks.getEntitySpawningPacket(this);
+ }
+
+ @Override
+ public boolean isInvulnerableTo(DamageSource source) {
+ return source.is(DamageTypes.ON_FIRE) || super.isInvulnerableTo(source);
+ }
+
+ public void seekNextTarget() {
+ if (this.getJumpCount() <= 16 && this.isCritArrow()) {
+ if (this.seekOrigin == null) {
+ this.seekOrigin = this.position();
+ }
+
+ if (!this.level().isClientSide) {
+ TargetingConditions conditions = TargetingConditions.forCombat().selector((living) -> living.hasLineOfSight(this));
+ this.homingTarget = this.level().getNearestEntity(LivingEntity.class, conditions, owner instanceof LivingEntity ? (LivingEntity)owner : null, this.seekOrigin.x, this.seekOrigin.y, this.seekOrigin.z, this.getBoundingBox().inflate(64.0D));
+ if (this.homingTarget != null) {
+ Vec3 targetPos = this.homingTarget.getEyePosition();
+ double x = targetPos.x - this.getX();
+ double y = targetPos.y - this.getY();
+ double z = targetPos.z - this.getZ();
+ this.shoot(x, y, z, 3.0F, 0.0F);
+ this.setJumpCount(this.getJumpCount() + 1);
+ this.homingTime = 0;
+ } else {
+ this.destroyArrow();
+ }
+
+ }
+ } else {
+ this.destroyArrow();
+ }
+ }
+
+ private void updateHoming() {
+ if (this.homingTarget != null) {
+ if (this.homingTime++ > 60) {
+ this.destroyArrow();
+ } else if (!this.homingTarget.isDeadOrDying() && !this.homingTarget.isRemoved()) {
+ Vec3 targetPos = this.homingTarget.getEyePosition();
+ if (targetPos.distanceToSqr(this.position()) >= 4.0D) {
+ double x = targetPos.x - this.getX();
+ double y = targetPos.y - this.getY();
+ double z = targetPos.z - this.getZ();
+ this.shoot(x, y, z, 3.0F, 0.0F);
+ this.hasImpulse = true;
+ }
+ } else {
+ this.homingTarget = null;
+ this.seekNextTarget();
+ }
+ }
+ }
+
+ private void destroyArrow() {
+ Level level1 = this.level();
+ if (!level1.isClientSide) {
+ if (level1 instanceof ServerLevel level) {
+ ClientboundLevelParticlesPacket packet = new ClientboundLevelParticlesPacket(ParticleTypes.SMOKE, true, this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F, 0.0F, 4.0F, 10);
+
+ if (owner instanceof ServerPlayer player){
+ player.connection.send(packet);
+ }
+ level.explode(this.getOwner() == null ? this : this.getOwner(), this.getX(), this.getY(), this.getZ(), 4.0F, Level.ExplosionInteraction.NONE);
+ }
+
+ this.discard();
+ }
+ else {
+ level1.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F, 0.0F );
+ }
+ }
+
+ static {
+ ID_EFFECT_COLOR = SynchedEntityData.defineId(TraceArrowEntity.class, EntityDataSerializers.INT);
+ SPECTRAL_TIME = SynchedEntityData.defineId(TraceArrowEntity.class, EntityDataSerializers.INT);
+ JUMP_COUNT = SynchedEntityData.defineId(TraceArrowEntity.class, EntityDataSerializers.INT);
+ projectileAntiImmuneEntities = Lists.newArrayList("minecraft:enderman", "minecraft:wither", "minecraft:ender_dragon", "draconicevolution:guardian_wither");
+ }
+}
diff --git a/src/main/java/committee/nova/mods/avaritia/common/item/tools/BowInfinityItem.java b/src/main/java/committee/nova/mods/avaritia/common/item/tools/BowInfinityItem.java
index 4028d0e5..01a88995 100644
--- a/src/main/java/committee/nova/mods/avaritia/common/item/tools/BowInfinityItem.java
+++ b/src/main/java/committee/nova/mods/avaritia/common/item/tools/BowInfinityItem.java
@@ -1,22 +1,33 @@
package committee.nova.mods.avaritia.common.item.tools;
-import committee.nova.mods.avaritia.common.entity.HeavenArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenArrowEntity;
import committee.nova.mods.avaritia.common.entity.ImmortalItemEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.TraceArrowEntity;
import committee.nova.mods.avaritia.init.registry.ModEntities;
import committee.nova.mods.avaritia.init.registry.ModItems;
+import committee.nova.mods.avaritia.util.math.RayTracer;
+import net.minecraft.nbt.CompoundTag;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
+import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
-import net.minecraft.world.item.BowItem;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.UseAnim;
+import net.minecraft.world.entity.projectile.Arrow;
+import net.minecraft.world.item.*;
+import net.minecraft.world.item.enchantment.EnchantmentHelper;
+import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
+import net.minecraft.world.phys.BlockHitResult;
+import net.minecraftforge.event.ForgeEventFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,18 +51,31 @@ public boolean isDamageable(ItemStack stack) {
return false;
}
+ @Override
+ public boolean canBeHurtBy(@NotNull DamageSource source) {
+ return source.is(DamageTypes.FELL_OUT_OF_WORLD);
+ }
+
+ @Override
+ public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) {
+ if (entity.getAge() >= 0) {
+ entity.setExtendedLifetime();
+ }
+ return super.onEntityItemUpdate(stack, entity);
+ }
+ @Override
+ public boolean isEnchantable(@NotNull ItemStack p_41456_) {
+ return true;
+ }
@Override
public int getEnchantmentValue(ItemStack stack) {
return 0;
}
-
-
@Override
public int getUseDuration(@NotNull ItemStack stack) {
return 1200;
}
-
@Override
public @NotNull UseAnim getUseAnimation(@NotNull ItemStack pStack) {
return UseAnim.BOW;
@@ -64,36 +88,91 @@ public Entity createEntity(Level level, Entity location, ItemStack stack) {
}
@Override
- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) {
- //无线箭矢
+ public @NotNull InteractionResultHolder use(@NotNull Level level, Player player, @NotNull InteractionHand hand) {
+ //无限箭矢
var itemstack = player.getItemInHand(hand);
InteractionResultHolder ret = net.minecraftforge.event.ForgeEventFactory.onArrowNock(itemstack, level, player, hand, true);
if (ret != null) return ret;
-
+ if (player.isCrouching()) {
+ CompoundTag tags = itemstack.getOrCreateTag();
+ tags.putBoolean("tracer", !tags.getBoolean("tracer"));
+ player.setMainArm(HumanoidArm.RIGHT);
+ return new InteractionResultHolder<>(InteractionResult.SUCCESS, itemstack);
+ }
player.startUsingItem(hand);
return InteractionResultHolder.success(itemstack);
}
@Override
- public void releaseUsing(ItemStack stack, Level level, LivingEntity player, int count) {
- var max = getUseDuration(stack);
- var velocity = BowItem.getPowerForTime(max - count);
-
- velocity = velocity < 1.0D ? 1.0f : velocity;
- HeavenArrowEntity arrow = HeavenArrowEntity.create(level, player);
- arrow.setPos(player.getX() - 0.3, player.getEyeY() - 0.1, player.getZ());
- arrow.shootFromRotation(player, player.getXRot(), player.getYRot(), 0, velocity * 4.0F, 1.0F);
- arrow.setCritArrow(true);
-
- level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.NEUTRAL, 1.0F, 1.0F / (level.random.nextFloat() * 0.4F + 1.2F) + velocity * 0.5F);
- arrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
-
+ public void releaseUsing(@NotNull ItemStack stack, @NotNull Level level, @NotNull LivingEntity entity, int timeLeft) {
if (!level.isClientSide) {
- level.addFreshEntity(arrow);
- if (player instanceof Player player1) player1.awardStat(Stats.ITEM_USED.get(this));
+ if (entity instanceof Player player) {
+ AbstractArrow arrowEntity;
+ ItemStack ammoStack = player.getProjectile(stack);
+ int drawTime = this.getUseDuration(stack) - timeLeft;
+ drawTime = ForgeEventFactory.onArrowLoose(stack, level, player, drawTime, true);
+ if (drawTime < 0) {
+ return;
+ }
+ float VELOCITY_MULTIPLIER = 1.2F;
+ float DAMAGE_MULTIPLIER = 5000.0F;
+ float draw = getPowerForTime(drawTime);
+ float powerForTime = draw * VELOCITY_MULTIPLIER;
+ if (ammoStack.isEmpty()) {
+ ammoStack = new ItemStack(Items.ARROW);
+ }
+ if (stack.getOrCreateTag().getBoolean("tracer")) {
+
+ if ((double)powerForTime >= 0.1D) {
+ ArrowItem arrowitem = (ArrowItem)(ammoStack.getItem() instanceof ArrowItem ? ammoStack.getItem() : Items.ARROW);
+ arrowEntity = this.customArrow(arrowitem.createArrow(level, ammoStack, entity));
+ if (arrowEntity instanceof Arrow arrow2) {
+ arrow2.setEffectsFromItem(ammoStack);
+ } else if (arrowEntity instanceof TraceArrowEntity infinityArrow) {
+ infinityArrow.setEffectsFromItem(ammoStack);
+ }
+
+ if (draw == 1.0F) {
+ arrowEntity.setCritArrow(true);
+ }
+
+ arrowEntity.setBaseDamage(arrowEntity.getBaseDamage() * (double)DAMAGE_MULTIPLIER);
+ addEnchant(stack, level, entity, arrowEntity, powerForTime);
+
+ }
+
+ }
+ else {
+ arrowEntity = HeavenArrowEntity.create(level, entity);
+ arrowEntity.setPos(entity.getX() - 0.3, entity.getEyeY() - 0.1, entity.getZ());
+ arrowEntity.setCritArrow(true);
+ addEnchant(stack, level, entity, arrowEntity, powerForTime);
+ }
+
+ level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (level.random.nextFloat() * 0.4F + 1.2F) + powerForTime * 0.5F);
+ player.awardStat(Stats.ITEM_USED.get(this));
+
+ }
}
}
+ private void addEnchant(@NotNull ItemStack stack, @NotNull Level level, @NotNull LivingEntity entity, AbstractArrow arrowEntity, float powerForTime) {
+ arrowEntity.shootFromRotation(entity, entity.getXRot(), entity.getYRot(), 0.0F, powerForTime * 3.0F, 0.01F);
+ int j = EnchantmentHelper.getTagEnchantmentLevel(Enchantments.POWER_ARROWS, stack);
+ if (j > 0) {
+ arrowEntity.setBaseDamage(arrowEntity.getBaseDamage() + (double)j * 0.5D + 0.5D);
+ }
+
+ int k = EnchantmentHelper.getTagEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack);
+ if (k > 0) {
+ arrowEntity.setKnockback(k);
+ }
+ if (EnchantmentHelper.getTagEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) {
+ arrowEntity.setSecondsOnFire(100);
+ }
+ arrowEntity.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
+ level.addFreshEntity(arrowEntity);
+ }
}
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModDataGen.java b/src/main/java/committee/nova/mods/avaritia/init/data/ModDataGen.java
index 4a4a7bd5..a9dd7299 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModDataGen.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/ModDataGen.java
@@ -1,7 +1,8 @@
package committee.nova.mods.avaritia.init.data;
-import committee.nova.mods.avaritia.init.data.loot.ModLootTables;
-import committee.nova.mods.avaritia.init.data.recipe.ModRecipes;
+import committee.nova.mods.avaritia.init.data.provider.loot.ModLootTables;
+import committee.nova.mods.avaritia.init.data.provider.*;
+import committee.nova.mods.avaritia.init.data.provider.recipe.ModRecipes;
import net.minecraft.DetectedVersion;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
@@ -32,11 +33,11 @@ public class ModDataGen {
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
ExistingFileHelper helper = event.getExistingFileHelper();
- PackOutput output = generator.getPackOutput();
CompletableFuture future = event.getLookupProvider();
if (event.includeClient()) {
generator.addProvider(true, new ModBlockStates(generator, helper));
+ generator.addProvider(true, new ModSpriteSource(generator, helper));
// generator.addProvider(true, new ModItemModels(output, helper));
// generator.addProvider(true, new ModLang(output));
generator.addProvider(true, new ModSoundDefinitions(generator, helper));
@@ -49,8 +50,8 @@ public static void gatherData(GatherDataEvent event) {
// generator.addProvider(true, new ModAdvancements(output, future, helper));
// generator.addProvider(true, new ModFluidTags(output, future, helper));
- ModRegistries.addProviders(true, generator, output, future, helper);
- generator.addProvider(true, new PackMetadataGenerator(output).add(PackMetadataSection.TYPE, new PackMetadataSection(
+ ModRegistries.addProviders(true, generator, future, helper);
+ generator.addProvider(true, new PackMetadataGenerator(generator.getPackOutput()).add(PackMetadataSection.TYPE, new PackMetadataSection(
Component.literal("Avaritia Resources"),
DetectedVersion.BUILT_IN.getPackVersion(PackType.CLIENT_RESOURCES),
Arrays.stream(PackType.values()).collect(Collectors.toMap(Function.identity(), DetectedVersion.BUILT_IN::getPackVersion)))));
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModRegistries.java b/src/main/java/committee/nova/mods/avaritia/init/data/ModRegistries.java
index b8e1c4e1..a99ecbe1 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModRegistries.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/ModRegistries.java
@@ -1,6 +1,7 @@
package committee.nova.mods.avaritia.init.data;
import committee.nova.mods.avaritia.Static;
+import committee.nova.mods.avaritia.init.data.provider.ModDamageTypeTags;
import committee.nova.mods.avaritia.init.registry.ModDamageTypes;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistryAccess;
@@ -30,9 +31,9 @@ private ModRegistries(PackOutput output, CompletableFuture provider, ExistingFileHelper helper) {
- generator.addProvider(isServer, new ModRegistries(output, provider));
- generator.addProvider(isServer, new ModDamageTypeTags(output, provider.thenApply(r -> append(r, BUILDER)), helper));
+ public static void addProviders(boolean isServer, DataGenerator generator, CompletableFuture provider, ExistingFileHelper helper) {
+ generator.addProvider(isServer, new ModRegistries(generator.getPackOutput(), provider));
+ generator.addProvider(isServer, new ModDamageTypeTags(generator.getPackOutput(), provider.thenApply(r -> append(r, BUILDER)), helper));
}
private static HolderLookup.Provider append(HolderLookup.Provider original, RegistrySetBuilder builder) {
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModBlockStates.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockStates.java
similarity index 91%
rename from src/main/java/committee/nova/mods/avaritia/init/data/ModBlockStates.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockStates.java
index 9d970064..481cc8ad 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModBlockStates.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockStates.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data;
+package committee.nova.mods.avaritia.init.data.provider;
import committee.nova.mods.avaritia.api.init.data.IBlockStateProvider;
import net.minecraft.data.DataGenerator;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModBlockTags.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockTags.java
similarity index 97%
rename from src/main/java/committee/nova/mods/avaritia/init/data/ModBlockTags.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockTags.java
index d85ab0ba..fe823929 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModBlockTags.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModBlockTags.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data;
+package committee.nova.mods.avaritia.init.data.provider;
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.init.registry.ModBlocks;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModDamageTypeTags.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModDamageTypeTags.java
similarity index 95%
rename from src/main/java/committee/nova/mods/avaritia/init/data/ModDamageTypeTags.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/ModDamageTypeTags.java
index 0f2cb617..53751a38 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModDamageTypeTags.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModDamageTypeTags.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data;
+package committee.nova.mods.avaritia.init.data.provider;
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.init.registry.ModDamageTypes;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModEntityTags.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModEntityTags.java
similarity index 95%
rename from src/main/java/committee/nova/mods/avaritia/init/data/ModEntityTags.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/ModEntityTags.java
index 77ba62de..49825887 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModEntityTags.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModEntityTags.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data;
+package committee.nova.mods.avaritia.init.data.provider;
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.init.registry.ModEntities;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/ModSoundDefinitions.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSoundDefinitions.java
similarity index 93%
rename from src/main/java/committee/nova/mods/avaritia/init/data/ModSoundDefinitions.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSoundDefinitions.java
index ac908e46..7270a282 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/ModSoundDefinitions.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSoundDefinitions.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data;
+package committee.nova.mods.avaritia.init.data.provider;
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.init.registry.ModSounds;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSpriteSource.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSpriteSource.java
new file mode 100644
index 00000000..90d1f1f2
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/ModSpriteSource.java
@@ -0,0 +1,25 @@
+package committee.nova.mods.avaritia.init.data.provider;
+
+import committee.nova.mods.avaritia.Static;
+import net.minecraft.client.renderer.texture.atlas.sources.DirectoryLister;
+import net.minecraft.data.DataGenerator;
+import net.minecraftforge.common.data.ExistingFileHelper;
+import net.minecraftforge.common.data.SpriteSourceProvider;
+
+/**
+ * Name: Avaritia-forge / ModSpriteSource
+ * Author: cnlimiter
+ * CreateTime: 2023/9/23 2:15
+ * Description:
+ */
+
+public class ModSpriteSource extends SpriteSourceProvider {
+ public ModSpriteSource(DataGenerator generator, ExistingFileHelper fileHelper) {
+ super(generator.getPackOutput(), fileHelper, Static.MOD_ID);
+ }
+
+ @Override
+ protected void addSources() {
+ atlas(SpriteSourceProvider.BLOCKS_ATLAS).addSource(new DirectoryLister("shader", ""));
+ }
+}
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/loot/ModBlockLootTables.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModBlockLootTables.java
similarity index 96%
rename from src/main/java/committee/nova/mods/avaritia/init/data/loot/ModBlockLootTables.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModBlockLootTables.java
index 9775b915..b0cc2e0c 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/loot/ModBlockLootTables.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModBlockLootTables.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.loot;
+package committee.nova.mods.avaritia.init.data.provider.loot;
import committee.nova.mods.avaritia.Static;
import committee.nova.mods.avaritia.init.registry.ModBlocks;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/loot/ModLootTables.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModLootTables.java
similarity index 96%
rename from src/main/java/committee/nova/mods/avaritia/init/data/loot/ModLootTables.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModLootTables.java
index 4fd292d5..248877ec 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/loot/ModLootTables.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/loot/ModLootTables.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.loot;
+package committee.nova.mods.avaritia.init.data.provider.loot;
import com.google.common.collect.ImmutableList;
import net.minecraft.data.DataGenerator;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModCatalystRecipeBuilder.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModCatalystRecipeBuilder.java
similarity index 99%
rename from src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModCatalystRecipeBuilder.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModCatalystRecipeBuilder.java
index 0b91ef6d..37d3335a 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModCatalystRecipeBuilder.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModCatalystRecipeBuilder.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.recipe;
+package committee.nova.mods.avaritia.init.data.provider.recipe;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModRecipes.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModRecipes.java
similarity index 95%
rename from src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModRecipes.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModRecipes.java
index 8760dd93..209ad13e 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModRecipes.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModRecipes.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.recipe;
+package committee.nova.mods.avaritia.init.data.provider.recipe;
import committee.nova.mods.avaritia.init.registry.ModBlocks;
import committee.nova.mods.avaritia.init.registry.ModItems;
@@ -116,6 +116,18 @@ protected void buildRecipes(@NotNull Consumer consumer) {
.requires(ItemTags.MUSIC_DISCS)
.unlockedBy("has_item", has(ItemTags.MUSIC_DISCS)).save(consumer);
+ ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.neutron_ingot.get(), 9)
+ .requires(ModBlocks.neutron.get())
+ .unlockedBy("has_item", has(ModBlocks.neutron.get())).save(consumer);
+
+ ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.infinity_ingot.get(), 9)
+ .requires(ModBlocks.infinity.get())
+ .unlockedBy("has_item", has(ModBlocks.infinity.get())).save(consumer);
+
+ ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.crystal_matrix_ingot.get(), 9)
+ .requires(ModBlocks.crystal_matrix.get())
+ .unlockedBy("has_item", has(ModBlocks.crystal_matrix.get())).save(consumer);
+
ModShapelessRecipeBuilder.shapeless(RecipeCategory.TOOLS, ModItems.cosmic_meatballs.get())
.requires(Items.PORKCHOP)
.requires(Items.BEEF)
@@ -270,7 +282,7 @@ protected void buildRecipes(@NotNull Consumer consumer) {
.pattern(" II")
.define('I', ModItems.infinity_ingot.get())
.define('W', ItemTags.WOOL)
- .define('X', ModItems.infinity_catalyst.get())
+ .define('X', ModBlocks.crystal_matrix.get())
.showNotification(true)
.unlockedBy("has_item", has(ModItems.infinity_ingot.get())).save(consumer);
@@ -298,7 +310,7 @@ protected void buildRecipes(@NotNull Consumer consumer) {
.pattern(" NNNNN ")
.define('I', ModItems.infinity_ingot.get())
.define('N', ModItems.neutron_ingot.get())
- .define('X', ModItems.infinity_catalyst.get())
+ .define('X', ModBlocks.crystal_matrix.get())
.showNotification(true)
.unlockedBy("has_item", has(ModItems.infinity_ingot.get())).save(consumer);
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapedRecipeBuilder.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapedRecipeBuilder.java
similarity index 99%
rename from src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapedRecipeBuilder.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapedRecipeBuilder.java
index 824deba0..a36ecb04 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapedRecipeBuilder.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapedRecipeBuilder.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.recipe;
+package committee.nova.mods.avaritia.init.data.provider.recipe;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapelessRecipeBuilder.java b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapelessRecipeBuilder.java
similarity index 99%
rename from src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapelessRecipeBuilder.java
rename to src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapelessRecipeBuilder.java
index 82b15dbd..00db2962 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/data/recipe/ModShapelessRecipeBuilder.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/data/provider/recipe/ModShapelessRecipeBuilder.java
@@ -1,4 +1,4 @@
-package committee.nova.mods.avaritia.init.data.recipe;
+package committee.nova.mods.avaritia.init.data.provider.recipe;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/handler/ItemOverrideHandler.java b/src/main/java/committee/nova/mods/avaritia/init/handler/ItemOverrideHandler.java
index d64b26b3..2730f4f4 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/handler/ItemOverrideHandler.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/handler/ItemOverrideHandler.java
@@ -35,7 +35,11 @@ public static void init(FMLClientSetupEvent event) {
event.enqueueWork(() -> setPropertyOverride(ModItems.matter_cluster.get(), Static.rl("cap"), (itemStack, world, livingEntity, d) -> {
return MatterClusterItem.getClusterSize(itemStack) == MatterClusterItem.CAPACITY ? 1 : 0;
}));
-
+ event.enqueueWork(() -> setPropertyOverride(ModItems.infinity_bow.get(), Static.rl("tracer"), (itemStack, world, livingEntity, d) -> {
+ if (itemStack.getItem() instanceof BowInfinityItem)
+ return itemStack.getOrCreateTag().getBoolean("tracer") ? 1 : 0;
+ return 0;
+ }));
event.enqueueWork(() -> setPropertyOverride(ModItems.infinity_bow.get(), Static.rl("pull"), (itemStack, world, livingEntity, d) -> {
if (livingEntity == null) {
return 0.0F;
diff --git a/src/main/java/committee/nova/mods/avaritia/init/registry/ModDamageTypes.java b/src/main/java/committee/nova/mods/avaritia/init/registry/ModDamageTypes.java
index ee6b5ebb..dcec8f3c 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/registry/ModDamageTypes.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/registry/ModDamageTypes.java
@@ -40,7 +40,7 @@ public static DamageSource source(Level level, ResourceKey id) {
return new DamageSource(damage);
}
- public static DamageSource causeRandomDamage(LivingEntity attacker) {
+ public static DamageSource causeRandomDamage(Entity attacker) {
return new DamageSourceRandomMessages(attacker.getCommandSenderWorld().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(INFINITY), attacker);
}
diff --git a/src/main/java/committee/nova/mods/avaritia/init/registry/ModEntities.java b/src/main/java/committee/nova/mods/avaritia/init/registry/ModEntities.java
index afa32b0c..ee243e2e 100644
--- a/src/main/java/committee/nova/mods/avaritia/init/registry/ModEntities.java
+++ b/src/main/java/committee/nova/mods/avaritia/init/registry/ModEntities.java
@@ -4,7 +4,11 @@
import committee.nova.mods.avaritia.client.render.entity.GapingVoidRender;
import committee.nova.mods.avaritia.client.render.entity.HeavenArrowRender;
import committee.nova.mods.avaritia.client.render.entity.HeavenSubArrowRender;
+import committee.nova.mods.avaritia.client.render.entity.TracerArrowRender;
import committee.nova.mods.avaritia.common.entity.*;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.HeavenSubArrowEntity;
+import committee.nova.mods.avaritia.common.entity.arrow.TraceArrowEntity;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.client.renderer.entity.ThrownItemRenderer;
import net.minecraft.resources.ResourceLocation;
@@ -41,19 +45,29 @@ public class ModEntities {
public static final RegistryObject> HEAVEN_ARROW = ENTITIES.register("heaven_arrow",
() -> EntityType.Builder.of(HeavenArrowEntity::new, MobCategory.MISC)
.sized(0.5F, 0.5F)
- .clientTrackingRange(32)
- .updateInterval(1)
+ .clientTrackingRange(4)
+ .updateInterval(20)
.setShouldReceiveVelocityUpdates(true)
.build(new ResourceLocation(Static.MOD_ID, "heaven_arrow").toString()));
public static final RegistryObject> HEAVEN_SUB_ARROW = ENTITIES.register("heaven_sub_arrow",
() -> EntityType.Builder.of(HeavenSubArrowEntity::new, MobCategory.MISC)
.sized(0.5F, 0.5F)
- .clientTrackingRange(32)
- .updateInterval(2)
+ .clientTrackingRange(4)
+ .updateInterval(20)
.setShouldReceiveVelocityUpdates(true)
.build(new ResourceLocation(Static.MOD_ID, "heaven_sub_arrow").toString()));
+ public static final RegistryObject> TRACE_ARROW = ENTITIES.register("trace_arrow",
+ () -> EntityType.Builder.of(TraceArrowEntity::new, MobCategory.MISC)
+ .sized(0.5F, 0.5F)
+ .clientTrackingRange(2)
+ .updateInterval(20)
+ .fireImmune()
+ .noSummon()
+ .setShouldReceiveVelocityUpdates(true)
+ .build(new ResourceLocation(Static.MOD_ID, "trace_arrow").toString()));
+
@OnlyIn(Dist.CLIENT)
public static void onClientSetup() {
@@ -61,6 +75,7 @@ public static void onClientSetup() {
EntityRenderers.register(ModEntities.GAPING_VOID.get(), GapingVoidRender::new);
EntityRenderers.register(ModEntities.HEAVEN_ARROW.get(), HeavenArrowRender::new);
EntityRenderers.register(ModEntities.HEAVEN_SUB_ARROW.get(), HeavenSubArrowRender::new);
+ EntityRenderers.register(ModEntities.TRACE_ARROW.get(), TracerArrowRender::new);
}
}
diff --git a/src/main/java/committee/nova/mods/avaritia/util/client/SpriteRegistryHelper.java b/src/main/java/committee/nova/mods/avaritia/util/client/SpriteRegistryHelper.java
new file mode 100644
index 00000000..9bef984d
--- /dev/null
+++ b/src/main/java/committee/nova/mods/avaritia/util/client/SpriteRegistryHelper.java
@@ -0,0 +1,41 @@
+package committee.nova.mods.avaritia.util.client;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.inventory.InventoryMenu;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.eventbus.api.IEventBus;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+
+import java.util.*;
+import java.util.function.Consumer;
+
+/**
+ * Name: Avaritia-forge / SpriteRegistryHelper
+ * Author: cnlimiter
+ * CreateTime: 2023/9/18 1:40
+ * Description:
+ */
+
+public class SpriteRegistryHelper {
+ public final Map sprites = new HashMap<>();
+
+
+ public SpriteRegistryHelper(IEventBus eventBus) {
+ eventBus.addListener(this::onTextureStitchPost);
+ }
+
+ private void onTextureStitchPost(TextureStitchEvent.Post event) {
+ TextureAtlas atlas = event.getAtlas();
+
+ for (ResourceLocation res : atlas.getTextureLocations()) {
+ TextureAtlasSprite sprite = atlas.getSprite(res);
+ sprites.put(sprite.atlasLocation(), sprite);
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg
index 9c3b83a0..d7e47b4b 100644
--- a/src/main/resources/META-INF/accesstransformer.cfg
+++ b/src/main/resources/META-INF/accesstransformer.cfg
@@ -15,3 +15,24 @@ public net.minecraft.world.entity.item.ItemEntity f_31986_ # pickupdelay
public net.minecraft.world.entity.item.ItemEntity f_31985_ # age
public net.minecraft.world.damagesource.DamageSources m_269079_(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/damagesource/DamageSource; # source
public net.minecraft.world.damagesource.DamageSources m_268998_(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/damagesource/DamageSource; # source
+
+
+public-f com.mojang.blaze3d.shaders.Uniform m_5985_(F)V # set
+public-f com.mojang.blaze3d.shaders.Uniform m_142276_(Lcom/mojang/math/Vector3f;)V # set
+public-f com.mojang.blaze3d.shaders.Uniform m_142558_(Lcom/mojang/math/Vector4f;)V # set
+public-f com.mojang.blaze3d.shaders.Uniform m_5941_([F)V # set
+public-f com.mojang.blaze3d.shaders.Uniform m_5679_(Lcom/mojang/math/Matrix4f;)V # set
+public-f com.mojang.blaze3d.shaders.Uniform m_200759_(Lcom/mojang/math/Matrix3f;)V # set
+
+public net.minecraft.client.renderer.RenderStateShard f_110145_ # BLOCK_SHEET_MIPPED
+public net.minecraft.client.renderer.RenderStateShard f_110139_ # TRANSLUCENT_TRANSPARENCY
+public net.minecraft.client.renderer.RenderStateShard f_110152_ # LIGHTMAP
+public net.minecraft.client.renderer.RenderStateShard f_110112_ # EQUAL_DEPTH_TEST
+
+public net.minecraft.world.entity.projectile.AbstractArrow f_36696_ # lastState
+public net.minecraft.world.entity.projectile.AbstractArrow f_36699_ # knockback
+public net.minecraft.world.entity.projectile.AbstractArrow f_36701_ # piercingIgnoreEntityIds
+public net.minecraft.world.entity.projectile.AbstractArrow m_36799_()V # startFalling
+public net.minecraft.world.entity.projectile.Projectile m_37276_()Z # checkLeftOwner
+public net.minecraft.world.entity.projectile.Projectile f_37246_ # leftOwner
+public net.minecraft.world.entity.projectile.AbstractArrow m_36798_()Z # shouldFall
\ No newline at end of file
diff --git a/src/main/resources/assets/avaritia/models/item/infinity_bow.json b/src/main/resources/assets/avaritia/models/item/infinity_bow.json
index 7087697f..4b9c8299 100644
--- a/src/main/resources/assets/avaritia/models/item/infinity_bow.json
+++ b/src/main/resources/assets/avaritia/models/item/infinity_bow.json
@@ -23,6 +23,12 @@
"avaritia:pull": 0.9
},
"model": "avaritia:item/infinity_bow_pulling_2"
+ },
+ {
+ "predicate": {
+ "avaritia:tracer": 1
+ },
+ "model": "avaritia:item/infinity_bow_tracer"
}
]
}
diff --git a/src/main/resources/assets/avaritia/models/item/infinity_bow_tracer.json b/src/main/resources/assets/avaritia/models/item/infinity_bow_tracer.json
new file mode 100644
index 00000000..030638e5
--- /dev/null
+++ b/src/main/resources/assets/avaritia/models/item/infinity_bow_tracer.json
@@ -0,0 +1,6 @@
+{
+ "parent": "item/bow",
+ "textures": {
+ "layer0": "avaritia:item/tools/infinity_bow/pull_0"
+ }
+}
diff --git a/src/main/resources/assets/avaritia/models/item/infinity_ingot.json b/src/main/resources/assets/avaritia/models/item/infinity_ingot.json
index 97a1ac13..18526110 100644
--- a/src/main/resources/assets/avaritia/models/item/infinity_ingot.json
+++ b/src/main/resources/assets/avaritia/models/item/infinity_ingot.json
@@ -1,6 +1,15 @@
{
"parent": "minecraft:item/generated",
"textures": {
- "layer0": "avaritia:item/resource/infinity_ingot"
+ "layer0": "avaritia:item/resource/infinity_ingot",
+ "layer2": "avaritia:item/misc/halo"
+ },
+ "loader": "forge:item_layers",
+ "forge_data": {
+ "layers": {
+ "2": {
+ "color": "FF000000"
+ }
+ }
}
}
diff --git a/src/main/resources/assets/avaritia/shaders/core/cosmic.fsh b/src/main/resources/assets/avaritia/shaders/core/cosmic.fsh
new file mode 100644
index 00000000..eaf59b11
--- /dev/null
+++ b/src/main/resources/assets/avaritia/shaders/core/cosmic.fsh
@@ -0,0 +1,188 @@
+#version 150
+
+#define M_PI 3.1415926535897932384626433832795
+
+#moj_import
+
+const int cosmiccount = 10;
+const int cosmicoutof = 101;
+const float lightmix = 0.2f;
+
+uniform sampler2D Sampler0;
+
+uniform vec4 ColorModulator;
+uniform float FogStart;
+uniform float FogEnd;
+uniform vec4 FogColor;
+
+uniform float time;
+
+uniform float yaw;
+uniform float pitch;
+uniform float externalScale;
+
+uniform float opacity;
+
+uniform mat2 cosmicuvs[cosmiccount];
+
+in float vertexDistance;
+in vec4 vertexColor;
+in vec2 texCoord0;
+in vec4 normal;
+in vec3 fPos;
+
+out vec4 fragColor;
+
+mat4 rotationMatrix(vec3 axis, float angle)
+{
+
+ axis = normalize(axis);
+ float s = sin(angle);
+ float c = cos(angle);
+ float oc = 1.0 - c;
+
+ return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
+ oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
+ oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+void main (void)
+{
+ vec4 mask = texture(Sampler0, texCoord0.xy);
+
+ float oneOverExternalScale = 1.0/externalScale;
+
+ int uvtiles = 16;
+
+ // background colour
+ vec4 col = vec4(0.1,0.0,0.0,1.0);
+
+ float pulse = mod(time,400)/400.0;
+
+ col.g = sin(pulse*M_PI*2) * 0.075 + 0.225;
+ col.b = cos(pulse*M_PI*2) * 0.05 + 0.3;
+
+ // get ray from camera to fragment
+ vec4 dir = normalize(vec4(-fPos, 0));
+
+ // rotate the ray to show the right bit of the sphere for the angle
+ float sb = sin(pitch);
+ float cb = cos(pitch);
+ dir = normalize(vec4(dir.x, dir.y * cb - dir.z * sb, dir.y * sb + dir.z * cb, 0));
+
+ float sa = sin(-yaw);
+ float ca = cos(-yaw);
+ dir = normalize(vec4(dir.z * sa + dir.x * ca, dir.y, dir.z * ca - dir.x * sa, 0));
+
+ vec4 ray;
+
+ // draw the layers
+ for (int i=0; i<16; i++) {
+ int mult = 16-i;
+
+ // get semi-random stuff
+ int j = i + 7;
+ float rand1 = (j * j * 4321 + j * 8) * 2.0F;
+ int k = j + 1;
+ float rand2 = (k * k * k * 239 + k * 37) * 3.6F;
+ float rand3 = rand1 * 347.4 + rand2 * 63.4;
+
+ // random rotation matrix by random rotation around random axis
+ vec3 axis = normalize(vec3(sin(rand1), sin(rand2) , cos(rand3)));
+
+ // apply
+ ray = dir * rotationMatrix(axis, mod(rand3, 2*M_PI));
+
+ // calcuate the UVs from the final ray
+ float rawu = 0.5 + (atan(ray.z,ray.x)/(2*M_PI));
+ float rawv = 0.5 + (asin(ray.y)/M_PI);
+
+ // get UV scaled for layers and offset by time;
+ float scale = mult*0.5 + 2.75;
+ float u = rawu * scale * externalScale;
+ //float v = (rawv + time * 0.00006) * scale * 0.6;
+ float v = (rawv + time * 0.0002 * oneOverExternalScale) * scale * 0.6 * externalScale;
+
+ vec2 tex = vec2( u, v );
+
+ // tile position of the current uv
+ int tu = int(mod(floor(u*uvtiles),uvtiles));
+ int tv = int(mod(floor(v*uvtiles),uvtiles));
+
+ // get pseudorandom variants
+ int position = ((1777541 * tu) + (7649689 * tv) + (3612703 * (i+31)) + 1723609 ) ^ 50943779;
+ int symbol = int(mod(position, cosmicoutof));
+ int rotation = int(mod(pow(tu,float(tv)) + tu + 3 + tv*i, 8));
+ bool flip = false;
+ if (rotation >= 4) {
+ rotation -= 4;
+ flip = true;
+ }
+
+ // if it's an icon, then add the colour!
+ if (symbol >= 0 && symbol < cosmiccount) {
+
+ vec2 cosmictex = vec2(1.0,1.0);
+ vec4 tcol = vec4(1.0,0.0,0.0,1.0);
+
+ // get uv within the tile
+ float ru = clamp(mod(u,1.0)*uvtiles - tu, 0.0, 1.0);
+ float rv = clamp(mod(v,1.0)*uvtiles - tv, 0.0, 1.0);
+
+ if (flip) {
+ ru = 1.0 - ru;
+ }
+
+ float oru = ru;
+ float orv = rv;
+
+ // rotate uvs if necessary
+ if (rotation == 1) {
+ oru = 1.0-rv;
+ orv = ru;
+ } else if (rotation == 2) {
+ oru = 1.0-ru;
+ orv = 1.0-rv;
+ } else if (rotation == 3) {
+ oru = rv;
+ orv = 1.0-ru;
+ }
+
+ // get the iicon uvs for the tile
+ float umin = cosmicuvs[symbol][0][0];
+ float umax = cosmicuvs[symbol][1][0];
+ float vmin = cosmicuvs[symbol][0][1];
+ float vmax = cosmicuvs[symbol][1][1];
+
+ // interpolate based on tile uvs
+ cosmictex.x = umin * (1.0-oru) + umax * oru;
+ cosmictex.y = vmin * (1.0-orv) + vmax * orv;
+
+ tcol = texture(Sampler0, cosmictex);
+
+ // set the alpha, blending out at the bunched ends
+ float a = tcol.r * (0.5 + (1.0/mult) * 1.0) * (1.0-smoothstep(0.15, 0.48, abs(rawv-0.5)));
+
+ // get fancy colours
+ float r = (mod(rand1, 29.0)/29.0) * 0.3 + 0.4;
+ float g = (mod(rand2, 35.0)/35.0) * 0.4 + 0.6;
+ float b = (mod(rand1, 17.0)/17.0) * 0.3 + 0.7;
+
+ // mix the colours
+ //col = col*(1-a) + vec4(r,g,b,1)*a;
+ col = col + vec4(r,g,b,1)*a;
+ }
+ }
+
+ // apply lighting
+ vec3 shade = vertexColor.rgb * (lightmix) + vec3(1.0-lightmix,1.0-lightmix,1.0-lightmix);
+ col.rgb *= shade;
+
+ // apply mask
+ col.a *= mask.r * opacity;
+
+ col = clamp(col,0.0,1.0);
+
+ fragColor = linear_fog(col * ColorModulator, vertexDistance, FogStart, FogEnd, FogColor);
+}
diff --git a/src/main/resources/assets/avaritia/shaders/core/cosmic.json b/src/main/resources/assets/avaritia/shaders/core/cosmic.json
new file mode 100644
index 00000000..80d80693
--- /dev/null
+++ b/src/main/resources/assets/avaritia/shaders/core/cosmic.json
@@ -0,0 +1,35 @@
+{
+ "blend": {
+ "func": "add",
+ "srcrgb": "srcalpha",
+ "dstrgb": "1-srcalpha"
+ },
+ "vertex": "avaritia:cosmic",
+ "fragment": "avaritia:cosmic",
+ "attributes": [
+ "Position",
+ "Color",
+ "UV0",
+ "UV2",
+ "Normal"
+ ],
+ "samplers": [
+ { "name": "Sampler0" },
+ { "name": "Sampler2" }
+ ],
+ "uniforms": [
+ { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
+ { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
+ { "name": "ColorModulator", "type": "vec4", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] },
+ { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] },
+ { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] },
+ { "name": "FogColor", "type": "vec4", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] },
+ { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] },
+ { "name": "time", "type": "float", "count": 1, "values": [ 0 ] },
+ { "name": "yaw", "type": "float", "count": 1, "values": [ 0.0 ] },
+ { "name": "pitch", "type": "float", "count": 1, "values": [ 0.0 ] },
+ { "name": "externalScale", "type": "float", "count": 1, "values": [ 0.0 ] },
+ { "name": "opacity", "type": "float", "count": 1, "values": [ 0.0 ] },
+ { "name": "cosmicuvs", "type": "matrix2x2", "count": 40, "values": [ 0.0 ] }
+ ]
+}
diff --git a/src/main/resources/assets/avaritia/shaders/core/cosmic.vsh b/src/main/resources/assets/avaritia/shaders/core/cosmic.vsh
new file mode 100644
index 00000000..0e8f2f44
--- /dev/null
+++ b/src/main/resources/assets/avaritia/shaders/core/cosmic.vsh
@@ -0,0 +1,32 @@
+#version 150
+
+#moj_import
+#moj_import
+
+in vec3 Position;
+in vec4 Color;
+in vec2 UV0;
+in ivec2 UV2;
+in vec3 Normal;
+
+uniform sampler2D Sampler2;
+
+uniform mat4 ModelViewMat;
+uniform mat4 ProjMat;
+uniform int FogShape;
+
+out float vertexDistance;
+out vec4 vertexColor;
+out vec2 texCoord0;
+out vec4 normal;
+out vec3 fPos;
+
+void main() {
+ gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
+ fPos = (ModelViewMat * vec4(Position, 1.0)).xyz;
+
+ vertexDistance = fog_distance(ModelViewMat, Position, FogShape);
+ vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2);
+ texCoord0 = UV0;
+ normal = ProjMat * ModelViewMat * vec4(Normal, 0.0);
+}
diff --git a/src/main/resources/assets/avaritia/textures/item/misc/halo.png b/src/main/resources/assets/avaritia/textures/item/misc/halo.png
new file mode 100644
index 00000000..5c6f1c50
Binary files /dev/null and b/src/main/resources/assets/avaritia/textures/item/misc/halo.png differ
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_0.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_0.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_0.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_0.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_0.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_0.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_0.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_0.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_1.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_1.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_1.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_1.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_1.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_1.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_1.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_1.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_2.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_2.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_2.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_2.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_2.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_2.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_2.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_2.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_3.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_3.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_3.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_3.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_3.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_3.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_3.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_3.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_4.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_4.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_4.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_4.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_4.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_4.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_4.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_4.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_5.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_5.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_5.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_5.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_5.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_5.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_5.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_5.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_6.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_6.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_6.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_6.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_6.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_6.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_6.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_6.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_7.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_7.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_7.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_7.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_7.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_7.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_7.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_7.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_8.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_8.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_8.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_8.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_8.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_8.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_8.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_8.png.mcmeta
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_9.png b/src/main/resources/assets/avaritia/textures/shader/cosmic_9.png
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_9.png
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_9.png
diff --git a/src/main/resources/assets/avaritia/textures/shaders/cosmic_9.png.mcmeta b/src/main/resources/assets/avaritia/textures/shader/cosmic_9.png.mcmeta
similarity index 100%
rename from src/main/resources/assets/avaritia/textures/shaders/cosmic_9.png.mcmeta
rename to src/main/resources/assets/avaritia/textures/shader/cosmic_9.png.mcmeta