瀏覽代碼

stronger explosions, explosions always drop all items

Kajetan Johannes Hammerle 4 年之前
父節點
當前提交
3110266c65

+ 0 - 1
src/main/java/me/km/Client.java

@@ -2,7 +2,6 @@ package me.km;
 
 import java.awt.Color;
 import java.util.List;
-import java.util.Map;
 import me.km.blocks.ModBlocks;
 import me.km.blocks.cookingpot.TileEntityCookingPot;
 import me.km.items.ItemColoredSoup;

+ 17 - 0
src/main/java/me/km/CommonEvents.java

@@ -0,0 +1,17 @@
+package me.km;
+
+import me.km.utils.ExplosionUtils;
+import net.minecraftforge.event.world.ExplosionEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+public class CommonEvents
+{
+    @SubscribeEvent
+    public void onExplosionDetonation(ExplosionEvent.Detonate e)
+    {
+        if(!e.isCanceled())
+        {
+            ExplosionUtils.explosion(e.getExplosion(), e.getWorld());
+        }
+    }
+}

+ 3 - 0
src/main/java/me/km/KajetansMod.java

@@ -2,6 +2,7 @@ package me.km;
 
 import me.km.networking.ModPacketHandler;
 import me.km.world.ModWorldGeneration;
+import net.minecraftforge.common.MinecraftForge;
 import net.minecraftforge.fluids.FluidRegistry;
 import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
 import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
@@ -38,6 +39,8 @@ public class KajetansMod
         ModWorldGeneration.register();
         
         DamageUtils.init();
+        
+        MinecraftForge.EVENT_BUS.register(new CommonEvents());
     }
     
     private void clientInit(FMLClientSetupEvent e)

+ 2 - 1
src/main/java/me/km/snuviscript/ScriptEvents.java

@@ -14,6 +14,7 @@ import me.km.entities.EntityItemProjectile;
 import me.km.events.CommandEvent;
 import me.km.events.PlayerTabListNameEvent;
 import me.km.permissions.PermissionManager;
+import me.km.utils.ExplosionUtils;
 import me.km.utils.Location;
 import net.minecraft.command.ICommandSource;
 import net.minecraft.entity.Entity;
@@ -829,7 +830,7 @@ public class ScriptEvents
     }
     
     @SubscribeEvent(priority = EventPriority.HIGHEST)
-    public void BlockExplosionProtection(ExplosionEvent.Start e)
+    public void onExplosion(ExplosionEvent.Start e)
     {
         e.setCanceled(true);
         

+ 94 - 0
src/main/java/me/km/utils/ExplosionUtils.java

@@ -0,0 +1,94 @@
+package me.km.utils;
+
+import com.google.common.collect.Sets;
+import java.util.Set;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.fluid.IFluidState;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+import net.minecraft.world.Explosion;
+import net.minecraft.world.World;
+
+public class ExplosionUtils
+{
+    public static void explosion(Explosion ex, World w)
+    {
+        ex.getAffectedBlockPositions().clear();
+        
+        ReflectionUtils.setNoBreakMode(ex);
+        Vec3d pos = ex.getPosition();
+        
+        Entity exploder = ReflectionUtils.getExploder(ex);
+        float size = ReflectionUtils.getSize(ex);
+        
+        ex.getAffectedBlockPositions().addAll(getAffectedBlocks(ex, w, size, pos.x, pos.y, pos.z, exploder));
+    }
+
+    private static Set<BlockPos> getAffectedBlocks(Explosion ex, World w, float size, double x, double y, double z, Entity exploder)
+    {
+        Set<BlockPos> set = Sets.newHashSet();
+        for(int j = 0; j < 16; ++j)
+        {
+            for(int k = 0; k < 16; ++k)
+            {
+                for(int l = 0; l < 16; ++l)
+                {
+                    if(j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15)
+                    {
+                        // calc direction vector
+                        double dirX = j / 7.5 - 1.0;
+                        double dirY = k / 7.5 - 1.0;
+                        double dirZ = l / 7.5 - 1.0;
+                        double dirLength = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
+                        dirX /= dirLength;
+                        dirY /= dirLength;
+                        dirZ /= dirLength;
+                        // scale to the right size, moved outside of the loop
+                        dirX *= 0.3;
+                        dirY *= 0.3;
+                        dirZ *= 0.3;
+                        
+                        float strength = size * (0.7f + w.rand.nextFloat() * 0.6f);
+                        double currentX = x;
+                        double currentY = y;
+                        double currentZ = z;
+
+                        for(; strength > 0.0f; strength -= 0.225f)
+                        {
+                            BlockPos pos = new BlockPos(currentX, currentY, currentZ);
+                            BlockState state = w.getBlockState(pos);
+                            IFluidState fState = w.getFluidState(pos);
+                            if(!state.isAir(w, pos) || !fState.isEmpty())
+                            {
+                                float resistance = Math.max(state.getExplosionResistance(w, pos, exploder, ex), fState.getExplosionResistance(w, pos, exploder, ex));
+                                if(exploder != null)
+                                {
+                                    resistance = exploder.getExplosionResistance(ex, w, pos, state, fState, resistance);
+                                }
+                                
+                                // make explosives stronger, keep strong resistance but lower low resistance
+                                if(resistance <= 10)
+                                {
+                                    resistance = Math.min(resistance, 1.0f);
+                                }
+
+                                strength -= (resistance + 0.3F) * 0.3F;
+                            }
+
+                            if(strength > 0.0F && (exploder == null || exploder.canExplosionDestroyBlock(ex, w, pos, state, strength)))
+                            {
+                                set.add(pos);
+                            }
+
+                            currentX += dirX;
+                            currentY += dirY;
+                            currentZ += dirZ;
+                        }
+                    }
+                }
+            }
+        }
+        return set;
+    }
+}

+ 29 - 0
src/main/java/me/km/utils/ReflectionUtils.java

@@ -6,6 +6,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Map;
 import net.minecraft.command.Commands;
+import net.minecraft.entity.Entity;
 import net.minecraft.entity.LivingEntity;
 import net.minecraft.entity.item.ItemEntity;
 import net.minecraft.entity.player.PlayerAbilities;
@@ -16,6 +17,7 @@ import net.minecraft.server.management.PlayerList;
 import net.minecraft.util.DamageSource;
 import net.minecraft.util.FoodStats;
 import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.Explosion;
 import net.minecraft.world.IWorld;
 import net.minecraftforge.common.DimensionManager;
 import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
@@ -289,4 +291,31 @@ public class ReflectionUtils
             LogManager.getLogger().warn("damageArmor - " + ex);
         }
     }
+    
+    // -----------------------------------------------------------------------------------
+    // explosion stuff
+    // -----------------------------------------------------------------------------------
+    
+    private final static Field MODE = getField(Explosion.class, "field_222260_b"); // mode
+    private final static Field EXPLODER = getField(Explosion.class, "field_77283_e"); // exploder
+    private final static Field SIZE = getField(Explosion.class, "field_77280_f"); // size
+
+    public static void setNoBreakMode(Explosion ex)
+    {
+        Explosion.Mode mode = getFieldValue(Explosion.Mode.class, ex, MODE);
+        if(mode == Explosion.Mode.DESTROY)
+        {
+            setFieldValue(ex, MODE, Explosion.Mode.BREAK);
+        }
+    }
+    
+    public static Entity getExploder(Explosion ex)
+    {
+        return getFieldValue(Entity.class, ex, EXPLODER);
+    }
+    
+    public static float getSize(Explosion ex)
+    {
+        return getFloat(ex, SIZE, 1);
+    }
 }