Skip to content

Commit

Permalink
This one's a banger
Browse files Browse the repository at this point in the history
  • Loading branch information
doctor4t committed Apr 23, 2021
1 parent 83bb38c commit c81fb88
Show file tree
Hide file tree
Showing 12 changed files with 512 additions and 35 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Features:
- Creepers explode when getting damaged by an explosion
- Creepers ignite when on fire
- Creepers get charged up when damaged by a charged creeper
- Creepers have 4 times the follow / target range
- Creepers spawn at any light level
- Creepers have a randomly reduced fuse time
- Creepers have a 10% chance to expel random flying blocks
- These blocks can have any blockstate in the game
- These blocks deal damage like anvils
- Creepers have a 10% chance to spawn 1 to 10 other creepers with random status effects when exploding
- Creepers don't take fall damage
- Creepers have a 10% chance to spawn charged
- Creepers are twice as fast
- Creeper explosion have a random knockback between normal and five times the Vanilla knockback
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '0.2.6-SNAPSHOT'
id 'fabric-loom' version '0.6-SNAPSHOT'
id 'maven-publish'
}

Expand Down
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
org.gradle.jvmargs=-Xmx1G

# Fabric Properties
minecraft_version=20w09a
yarn_mappings=20w09a+build.6
loader_version=0.7.8+build.186
minecraft_version=21w16a
yarn_mappings=21w16a+build.4
loader_version=0.11.3

#Fabric api
fabric_version=0.4.33+build.301-1.16
fabric_version=0.33.0+1.17

# Mod Properties
mod_version = 1.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
package ladysnake.reactivecreepers.mixin;

import net.fabricmc.fabric.mixin.object.builder.SpawnRestrictionAccessor;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnRestriction;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.entity.mob.MobEntityWithAi;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.mob.Monster;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(CreeperEntity.class)
public abstract class CreeperEntityMixin extends HostileEntityMixin {
@Shadow protected abstract void explode();
public abstract class CreeperEntityMixin extends LivingEntityMixin implements Monster {
@Shadow
protected abstract void explode();

@Shadow public abstract void setIgnited();
@Shadow
public abstract void ignite();

@Shadow private int fuseTime;
@Shadow
private int fuseTime;

@Shadow @Final private static TrackedData<Boolean> CHARGED;
@Shadow
@Final
private static TrackedData<Boolean> CHARGED;

protected CreeperEntityMixin(EntityType<? extends MobEntityWithAi> type, World world) {
protected CreeperEntityMixin(EntityType<? extends CreeperEntity> type, World world) {
super(type, world);
}

Expand All @@ -31,18 +47,40 @@ protected float onDamage(DamageSource source, float amount) {
this.getDataTracker().set(CHARGED, true);
return 1F;
} else {
this.fuseTime = 0;
this.setIgnited();
this.ignite();
return 0.0F;
}
}

if (source.isFire() && !this.getDataTracker().get(CHARGED)) {
this.setIgnited();
this.ignite();
}

if (source.isFromFalling()) {
return 0;
}

return amount;
}

private boolean shouldCharge(DamageSource source) {
return source.getAttacker() instanceof CreeperEntity && source.getAttacker().getDataTracker().get(CHARGED) && !this.getDataTracker().get(CHARGED);
}

// bigger follow range and faster speed
@Inject(method = "createCreeperAttributes", at = @At("RETURN"), cancellable = true)
private static void createCreeperAttributes(CallbackInfoReturnable<DefaultAttributeContainer.Builder> cir) {
cir.setReturnValue(HostileEntity.createHostileAttributes().add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.5D).add(EntityAttributes.GENERIC_FOLLOW_RANGE, 35.0D));
}

@Inject(method = "ignite", at = @At("RETURN"))
public void ignite(CallbackInfo ci) {
this.fuseTime = this.random.nextInt(30);
}

@Inject(method = "initDataTracker", at = @At("RETURN"))
protected void initDataTracker(CallbackInfo ci) {
this.dataTracker.set(CHARGED, random.nextInt(10) == 0);
}

}
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
package ladysnake.reactivecreepers.mixin;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.mob.MobEntityWithAi;
import net.minecraft.entity.mob.Monster;
import net.minecraft.world.World;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Difficulty;
import net.minecraft.world.ServerWorldAccess;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(HostileEntity.class)
public abstract class HostileEntityMixin extends MobEntityWithAi implements Monster {
protected HostileEntityMixin(EntityType<? extends MobEntityWithAi> type, World world) {
super(type, world);
}
import java.util.Random;

@ModifyVariable(at = @At(value = "HEAD"), method = "damage", argsOnly = true)
private float damage(float amount, DamageSource source) {
return this.onDamage(source, amount);
}
@Mixin(HostileEntity.class)
public class HostileEntityMixin {

@Unique
protected float onDamage(DamageSource source, float amount) {
return amount;
@Inject(method = "canSpawnInDark", at = @At("RETURN"), cancellable = true)
private static void canSpawnInDark(EntityType<? extends HostileEntity> type, ServerWorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random, CallbackInfoReturnable<Boolean> cir) {
if (world.getDifficulty() != Difficulty.PEACEFUL && type == EntityType.CREEPER) {
cir.setReturnValue(true);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ladysnake.reactivecreepers.mixin;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin extends Entity {
public LivingEntityMixin(EntityType<?> type, World world) {
super(type, world);
}

@ModifyVariable(at = @At(value = "HEAD"), method = "damage", argsOnly = true)
private float damage(float amount, DamageSource source) {
return this.onDamage(source, amount);
}

@Unique
protected float onDamage(DamageSource source, float amount) {
return amount;
}

}
30 changes: 30 additions & 0 deletions src/main/java/ladysnake/reactivecreepers/mixin/MobEntityMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ladysnake.reactivecreepers.mixin;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Difficulty;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.Random;

@Mixin(MobEntity.class)
public abstract class MobEntityMixin extends LivingEntity {
protected MobEntityMixin(EntityType<? extends MobEntity> entityType, World world) {
super(entityType, world);
}

@Inject(method = "canMobSpawn", at = @At("HEAD"), cancellable = true)
private static void canMobSpawn(EntityType<? extends MobEntity> type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random, CallbackInfoReturnable<Boolean> cir) {
if (world.getDifficulty() != Difficulty.PEACEFUL && type == EntityType.CREEPER) {
cir.setReturnValue(true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ladysnake.reactivecreepers.mixin;

import ladysnake.reactivecreepers.world.CustomCreeperExplosion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.explosion.ExplosionBehavior;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(ServerWorld.class)
public class ServerWorldMixin {
@ModifyVariable(method = "createExplosion(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/damage/DamageSource;Lnet/minecraft/world/explosion/ExplosionBehavior;DDDFZLnet/minecraft/world/explosion/Explosion$DestructionType;)Lnet/minecraft/world/explosion/Explosion;", at = @At("STORE"))
private Explosion createExplosion(Explosion explosion, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionBehavior behavior, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType destructionType) {
if (entity instanceof CreeperEntity) {
return new CustomCreeperExplosion((World) (Object) this, entity, damageSource, behavior, x, y, z, power, destructionType);
} else {
return explosion;
}
}
}
Loading

0 comments on commit c81fb88

Please sign in to comment.