shit
This commit is contained in:
69
src/main/java/dev/tggamesyt/szar/HitterEntity.java
Normal file
69
src/main/java/dev/tggamesyt/szar/HitterEntity.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.ai.goal.LookAroundGoal;
|
||||
import net.minecraft.entity.ai.goal.MeleeAttackGoal;
|
||||
import net.minecraft.entity.ai.goal.WanderAroundFarGoal;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.mob.PathAwareEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HitterEntity extends PathAwareEntity implements Arrestable{
|
||||
|
||||
public static boolean arrestable = true;
|
||||
|
||||
public HitterEntity(EntityType<? extends PathAwareEntity> type, World world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initGoals() {
|
||||
this.goalSelector.add(0, new MeleeAttackGoal(this, 1.2D, true));
|
||||
this.goalSelector.add(2, new WanderAroundFarGoal(this, 1.0D));
|
||||
this.goalSelector.add(3, new LookAroundGoal(this));
|
||||
|
||||
this.targetSelector.add(1, new AggroOnHitRevengeGoal(this));
|
||||
}
|
||||
|
||||
|
||||
public static DefaultAttributeContainer.Builder createAttributes() {
|
||||
return MobEntity.createMobAttributes()
|
||||
.add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
|
||||
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot(DamageSource source, boolean causedByPlayer) {
|
||||
ItemStack book = new ItemStack(Items.WRITTEN_BOOK);
|
||||
|
||||
NbtCompound nbt = book.getOrCreateNbt();
|
||||
nbt.putString("title", "Hitler's will");
|
||||
nbt.putString("author", "Hitler");
|
||||
|
||||
// Pages need to be JSON text components
|
||||
NbtList pages = new NbtList();
|
||||
pages.add(NbtString.of("{\"text\":\"Hitler's will\\n - Kill all jews\\n - Kill all players\"}"));
|
||||
pages.add(NbtString.of("{\"text\":\"die\"}"));
|
||||
|
||||
nbt.put("pages", pages);
|
||||
|
||||
this.dropStack(book);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isArrestable() {
|
||||
return arrestable;
|
||||
}
|
||||
}
|
||||
65
src/main/java/dev/tggamesyt/szar/NaziEntity.java
Normal file
65
src/main/java/dev/tggamesyt/szar/NaziEntity.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.ai.goal.LookAroundGoal;
|
||||
import net.minecraft.entity.ai.goal.MeleeAttackGoal;
|
||||
import net.minecraft.entity.ai.goal.WanderAroundFarGoal;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.mob.PathAwareEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class NaziEntity extends PathAwareEntity implements Arrestable{
|
||||
|
||||
public static boolean arrestable = true;
|
||||
|
||||
public NaziEntity(EntityType<? extends PathAwareEntity> type, World world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initGoals() {
|
||||
this.goalSelector.add(0, new MeleeAttackGoal(this, 1.2D, true));
|
||||
this.goalSelector.add(2, new WanderAroundFarGoal(this, 1.0D));
|
||||
this.goalSelector.add(3, new LookAroundGoal(this));
|
||||
|
||||
this.targetSelector.add(1, new AggroOnHitRevengeGoal(this));
|
||||
}
|
||||
|
||||
|
||||
public static DefaultAttributeContainer.Builder createAttributes() {
|
||||
return MobEntity.createMobAttributes()
|
||||
.add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
|
||||
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot(DamageSource source, boolean causedByPlayer) {
|
||||
ItemStack book = new ItemStack(Items.WRITTEN_BOOK);
|
||||
|
||||
NbtCompound nbt = book.getOrCreateNbt();
|
||||
nbt.putString("title", "Nazi's message");
|
||||
nbt.putString("author", "Nazi");
|
||||
|
||||
// Pages need to be JSON text components
|
||||
NbtList pages = new NbtList();
|
||||
pages.add(NbtString.of("{\"text\":\"Hail Hitler\"}"));
|
||||
|
||||
nbt.put("pages", pages);
|
||||
|
||||
this.dropStack(book);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArrestable() {
|
||||
return arrestable;
|
||||
}
|
||||
}
|
||||
17
src/main/java/dev/tggamesyt/szar/PlaneAnimation.java
Normal file
17
src/main/java/dev/tggamesyt/szar/PlaneAnimation.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
public enum PlaneAnimation {
|
||||
START_ENGINE(false),
|
||||
STOP_ENGINE(false),
|
||||
FLYING(true),
|
||||
LANDING(false),
|
||||
LAND_STARTED(true),
|
||||
LIFT_UP(false);
|
||||
|
||||
public final boolean looping;
|
||||
|
||||
PlaneAnimation(boolean looping) {
|
||||
this.looping = looping;
|
||||
}
|
||||
}
|
||||
|
||||
324
src/main/java/dev/tggamesyt/szar/PlaneEntity.java
Normal file
324
src/main/java/dev/tggamesyt/szar/PlaneEntity.java
Normal file
@@ -0,0 +1,324 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import dev.tggamesyt.szar.PlaneAnimation;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.data.DataTracker;
|
||||
import net.minecraft.entity.data.TrackedData;
|
||||
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static dev.tggamesyt.szar.Szar.ANIMATION_TIMINGS;
|
||||
import static dev.tggamesyt.szar.Szar.ANIMATION_TIMINGS_SECONDS;
|
||||
|
||||
public class PlaneEntity extends Entity {
|
||||
|
||||
/* -------- DATA TRACKER -------- */
|
||||
|
||||
private static final TrackedData<Boolean> ENGINE_ON =
|
||||
DataTracker.registerData(PlaneEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||
|
||||
private static final TrackedData<Boolean> IS_FLYING =
|
||||
DataTracker.registerData(PlaneEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||
// PlaneEntity.java (CLIENT SIDE ONLY FIELDS)
|
||||
@Environment(EnvType.CLIENT)
|
||||
private PlaneAnimation currentAnimation;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private long animationStartTick;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private boolean looping;
|
||||
|
||||
// --- SERVER STATE ---
|
||||
private PlaneAnimation currentServerAnimation = null;
|
||||
private int animationTick = 0;
|
||||
private boolean hadPassengerLastTick = false;
|
||||
private boolean wasFlyingLastTick = false;
|
||||
|
||||
private void playServerAnimation(PlaneAnimation anim) {
|
||||
if (this.currentServerAnimation == anim) return;
|
||||
|
||||
this.currentServerAnimation = anim;
|
||||
Szar.playPlaneAnimation(anim, this.getId());
|
||||
}
|
||||
private boolean isAboveGround(double distance) {
|
||||
return !this.getWorld().isSpaceEmpty(
|
||||
this,
|
||||
this.getBoundingBox().offset(0, -distance, 0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public PlaneEntity(EntityType<? extends PlaneEntity> type, World world) {
|
||||
super(type, world);
|
||||
this.noClip = false;
|
||||
}
|
||||
|
||||
/* -------- DATA -------- */
|
||||
|
||||
@Override
|
||||
protected void initDataTracker() {
|
||||
this.dataTracker.startTracking(ENGINE_ON, false);
|
||||
this.dataTracker.startTracking(IS_FLYING, false);
|
||||
}
|
||||
|
||||
public boolean isEngineOn() {
|
||||
return dataTracker.get(ENGINE_ON);
|
||||
}
|
||||
|
||||
public void setEngineOn(boolean value) {
|
||||
dataTracker.set(ENGINE_ON, value);
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return dataTracker.get(IS_FLYING);
|
||||
}
|
||||
|
||||
public void setFlying(boolean value) {
|
||||
dataTracker.set(IS_FLYING, value);
|
||||
}
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void playAnimation(PlaneAnimation anim, boolean looping) {
|
||||
this.currentAnimation = anim;
|
||||
this.looping = looping;
|
||||
this.animationStartTick = this.age;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void stopAnimation() {
|
||||
this.currentAnimation = null;
|
||||
this.looping = false;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public PlaneAnimation getCurrentAnimation() {
|
||||
return currentAnimation;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public float getAnimationTime(float tickDelta) {
|
||||
if (currentAnimation == null) return 0;
|
||||
|
||||
float time = (this.age + tickDelta) - animationStartTick;
|
||||
|
||||
if (looping) {
|
||||
return time % ANIMATION_TIMINGS_SECONDS.getOrDefault(currentAnimation, -1f);
|
||||
}
|
||||
|
||||
return Math.min(time, ANIMATION_TIMINGS_SECONDS.getOrDefault(currentAnimation, -1f));
|
||||
}
|
||||
|
||||
|
||||
/* -------- SAVE / LOAD -------- */
|
||||
|
||||
@Override
|
||||
protected void readCustomDataFromNbt(NbtCompound nbt) {
|
||||
setEngineOn(nbt.getBoolean("EngineOn"));
|
||||
setFlying(nbt.getBoolean("IsFlying"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeCustomDataToNbt(NbtCompound nbt) {
|
||||
nbt.putBoolean("EngineOn", isEngineOn());
|
||||
nbt.putBoolean("IsFlying", isFlying());
|
||||
}
|
||||
|
||||
/* -------- TICK -------- */
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (getWorld().isClient) return;
|
||||
|
||||
PlayerEntity player = getControllingPassenger();
|
||||
boolean hasPassenger = player != null;
|
||||
|
||||
// Tick the current animation
|
||||
if (currentServerAnimation != null) {
|
||||
animationTick++;
|
||||
|
||||
int duration = ANIMATION_TIMINGS.getOrDefault(currentServerAnimation, -1);
|
||||
|
||||
// If it's a non-looping animation and finished, clear it
|
||||
if (duration != -1 && animationTick >= duration) {
|
||||
currentServerAnimation = null;
|
||||
animationTick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
LANDING / GRAVITY CHECK
|
||||
-------------------------------- */
|
||||
|
||||
boolean nearGround = isAboveGround(1.5);
|
||||
|
||||
if (!nearGround && isFlying()) {
|
||||
setFlying(false);
|
||||
setNoGravity(false);
|
||||
playServerAnimation(PlaneAnimation.LANDING);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
PASSENGER STATE CHANGES
|
||||
-------------------------------- */
|
||||
|
||||
if (!hadPassengerLastTick && hasPassenger) {
|
||||
setEngineOn(true);
|
||||
playServerAnimation(PlaneAnimation.START_ENGINE);
|
||||
}
|
||||
|
||||
if (hadPassengerLastTick && !hasPassenger) {
|
||||
setEngineOn(false);
|
||||
setFlying(false);
|
||||
setNoGravity(false);
|
||||
playServerAnimation(PlaneAnimation.STOP_ENGINE);
|
||||
currentServerAnimation = null; // allow full stop
|
||||
}
|
||||
|
||||
hadPassengerLastTick = hasPassenger;
|
||||
|
||||
/* --------------------------------
|
||||
IDLE (NO PASSENGER)
|
||||
-------------------------------- */
|
||||
|
||||
if (!hasPassenger) {
|
||||
setVelocity(getVelocity().multiply(0.9));
|
||||
move(MovementType.SELF, getVelocity());
|
||||
return;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
ENGINE RUNNING (ON GROUND)
|
||||
-------------------------------- */
|
||||
|
||||
if (isEngineOn() && !isFlying()) {
|
||||
playServerAnimation(PlaneAnimation.LAND_STARTED);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
FLIGHT TAKEOFF
|
||||
-------------------------------- */
|
||||
boolean nearGroundForTakeoff = isAboveGround(1.5);
|
||||
boolean wantsTakeoff = player.jumping;
|
||||
|
||||
if (!isFlying()) {
|
||||
if (wantsTakeoff && nearGroundForTakeoff) {
|
||||
// Start engine if not on yet
|
||||
if (!isEngineOn()) {
|
||||
setEngineOn(true);
|
||||
playServerAnimation(PlaneAnimation.START_ENGINE);
|
||||
}
|
||||
// Play lift up if not already lifting
|
||||
if (currentServerAnimation != PlaneAnimation.LIFT_UP) {
|
||||
playServerAnimation(PlaneAnimation.LIFT_UP);
|
||||
animationTick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If lift-up animation finished, start flying
|
||||
if (currentServerAnimation == PlaneAnimation.LIFT_UP) {
|
||||
int liftUpDuration = ANIMATION_TIMINGS.getOrDefault(PlaneAnimation.LIFT_UP, 10);
|
||||
if (animationTick >= liftUpDuration) {
|
||||
setFlying(true);
|
||||
setNoGravity(true);
|
||||
playServerAnimation(PlaneAnimation.FLYING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Already flying, handle in-air movement
|
||||
setNoGravity(true);
|
||||
playServerAnimation(PlaneAnimation.FLYING); // ensure looping
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
FLIGHT PHYSICS
|
||||
-------------------------------- */
|
||||
|
||||
setYaw(player.getYaw());
|
||||
setPitch(player.getPitch());
|
||||
prevYaw = getYaw();
|
||||
|
||||
float forward = player.forwardSpeed;
|
||||
float sideways = player.sidewaysSpeed;
|
||||
float speed = isFlying() ? 0.4f : 0.15f;
|
||||
|
||||
Vec3d forwardDir = Vec3d.fromPolar(0, getYaw());
|
||||
Vec3d velocity = forwardDir.multiply(forward * speed);
|
||||
setYaw(getYaw() + sideways * 3.0f);
|
||||
|
||||
if (isFlying() && player.isSneaking()) {
|
||||
velocity = velocity.add(0, -0.06, 0);
|
||||
}
|
||||
|
||||
setVelocity(getVelocity().add(velocity).multiply(0.98));
|
||||
move(MovementType.SELF, getVelocity());
|
||||
|
||||
wasFlyingLastTick = isFlying();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ActionResult interact(PlayerEntity player, Hand hand) {
|
||||
player.startRiding(this);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
@Override
|
||||
protected boolean canAddPassenger(Entity passenger) {
|
||||
return passenger instanceof PlayerEntity && this.getPassengerList().isEmpty();
|
||||
}
|
||||
@Override
|
||||
public void updatePassengerPosition(Entity passenger, PositionUpdater positionUpdater) {
|
||||
if (this.hasPassenger(passenger)) {
|
||||
passenger.setPosition(
|
||||
this.getX(),
|
||||
this.getY() + 0.8, // seat height
|
||||
this.getZ() - 1.0
|
||||
);
|
||||
}
|
||||
}
|
||||
@Nullable
|
||||
public PlayerEntity getControllingPassenger() {
|
||||
Entity passenger = this.getFirstPassenger();
|
||||
return passenger instanceof PlayerEntity player ? player : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrackedPosition(double x, double y, double z) {
|
||||
super.updateTrackedPosition(x, y, z);
|
||||
this.prevYaw = this.getYaw();
|
||||
}
|
||||
public static DefaultAttributeContainer.Builder createAttributes() {
|
||||
return MobEntity.createMobAttributes()
|
||||
.add(EntityAttributes.GENERIC_MAX_HEALTH, 1.0)
|
||||
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 1.0)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 1.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPushable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import dev.tggamesyt.szar.PlaneAnimation;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
|
||||
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
|
||||
import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
|
||||
@@ -25,9 +30,12 @@ import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.entity.passive.VillagerEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.*;
|
||||
import net.minecraft.registry.tag.BiomeTags;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.structure.StructurePieceType;
|
||||
import net.minecraft.text.Text;
|
||||
@@ -63,6 +71,9 @@ public class Szar implements ModInitializer {
|
||||
|
||||
public static final String MOD_ID = "szar";
|
||||
public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
|
||||
public static MinecraftServer SERVER;
|
||||
public static final Identifier PLANE_ANIM_PACKET =
|
||||
new Identifier("szar", "plane_anim");
|
||||
public static final Block SZAR_BLOCK =
|
||||
new SzarBlock();
|
||||
public static final TrackedData<Long> LAST_CRIME_TICK =
|
||||
@@ -100,6 +111,24 @@ public class Szar implements ModInitializer {
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<HitterEntity> HitterEntityType =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
new Identifier(MOD_ID, "hitler"),
|
||||
FabricEntityTypeBuilder
|
||||
.create(SpawnGroup.CREATURE, HitterEntity::new)
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<NaziEntity> NaziEntityType =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
new Identifier(MOD_ID, "nazi"),
|
||||
FabricEntityTypeBuilder
|
||||
.create(SpawnGroup.CREATURE, NaziEntity::new)
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<PoliceEntity> PoliceEntityType =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
@@ -118,6 +147,15 @@ public class Szar implements ModInitializer {
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<PlaneEntity> PLANE_ENTITY_TYPE =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
new Identifier(MOD_ID, "plane"),
|
||||
FabricEntityTypeBuilder
|
||||
.create(SpawnGroup.CREATURE, PlaneEntity::new)
|
||||
.dimensions(EntityDimensions.fixed(5.0F, 2.0F))
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<IslamTerrorist> TERRORIST_ENTITY_TYPE =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
@@ -163,6 +201,13 @@ public class Szar implements ModInitializer {
|
||||
);
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
||||
SERVER = server;
|
||||
});
|
||||
|
||||
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
|
||||
SERVER = null;
|
||||
});
|
||||
|
||||
// register block
|
||||
Registry.register(
|
||||
@@ -301,9 +346,13 @@ public class Szar implements ModInitializer {
|
||||
NiggerEntityType,
|
||||
NiggerEntity.createAttributes()
|
||||
);
|
||||
FabricDefaultAttributeRegistry.register(
|
||||
HitterEntityType,
|
||||
HitterEntity.createAttributes()
|
||||
);
|
||||
FabricDefaultAttributeRegistry.register(
|
||||
PoliceEntityType,
|
||||
NiggerEntity.createAttributes()
|
||||
PoliceEntity.createAttributes()
|
||||
);
|
||||
FabricDefaultAttributeRegistry.register(
|
||||
GYPSY_ENTITY_TYPE,
|
||||
@@ -345,6 +394,46 @@ public class Szar implements ModInitializer {
|
||||
1, // min group size
|
||||
2 // max group size
|
||||
);
|
||||
// 1. Allow entity A to spawn naturally in your biomes
|
||||
BiomeModifications.addSpawn(
|
||||
BiomeSelectors.includeByKey(BiomeKeys.FOREST, BiomeKeys.FLOWER_FOREST),
|
||||
SpawnGroup.MONSTER,
|
||||
HitterEntityType,
|
||||
5, 1, 1
|
||||
);
|
||||
|
||||
ServerTickEvents.END_WORLD_TICK.register(world -> {
|
||||
if (world.isClient) return;
|
||||
|
||||
if (world.random.nextInt(200) != 0) return;
|
||||
|
||||
world.getEntitiesByClass(
|
||||
HitterEntity.class, // <-- your A entity class
|
||||
entityA -> entityA.isAlive() && !entityA.hasTag("b_group_spawned")
|
||||
).forEach(entityA -> {
|
||||
if (entityA.isAlive() && !entityA.getCommandTags().contains("b_group_spawned")) return;
|
||||
entityA.addCommandTag("b_group_spawned");
|
||||
|
||||
int groupSize = 2 + world.random.nextInt(9); // 2–10 Bs
|
||||
for (int i = 0; i < groupSize; i++) {
|
||||
Entity entityB = NaziEntityType.create(world);
|
||||
if (entityB != null) {
|
||||
double offsetX = (world.random.nextDouble() - 0.5) * 4;
|
||||
double offsetZ = (world.random.nextDouble() - 0.5) * 4;
|
||||
entityB.refreshPositionAndAngles(
|
||||
entityA.getX() + offsetX,
|
||||
entityA.getY(),
|
||||
entityA.getZ() + offsetZ,
|
||||
world.random.nextFloat() * 360,
|
||||
0
|
||||
);
|
||||
world.spawnEntity(entityB);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
BiomeModifications.addSpawn(
|
||||
BiomeSelectors.includeByKey(
|
||||
BiomeKeys.JUNGLE,
|
||||
@@ -589,6 +678,26 @@ public class Szar implements ModInitializer {
|
||||
new Item.Settings()
|
||||
)
|
||||
);
|
||||
public static final Item HITTER_SPAWNEGG = Registry.register(
|
||||
Registries.ITEM,
|
||||
new Identifier(MOD_ID, "hitler_spawn_egg"),
|
||||
new SpawnEggItem(
|
||||
HitterEntityType,
|
||||
0x000000,
|
||||
0xFF0000,
|
||||
new Item.Settings()
|
||||
)
|
||||
);
|
||||
public static final Item NAZI_SPAWNEGG = Registry.register(
|
||||
Registries.ITEM,
|
||||
new Identifier(MOD_ID, "hitler_spawn_egg"),
|
||||
new SpawnEggItem(
|
||||
NaziEntityType,
|
||||
0x000000,
|
||||
0xFF0000,
|
||||
new Item.Settings()
|
||||
)
|
||||
);
|
||||
public static final Item POLICE_SPAWNEGG = Registry.register(
|
||||
Registries.ITEM,
|
||||
new Identifier(MOD_ID, "police_spawn_egg"),
|
||||
@@ -678,4 +787,34 @@ public class Szar implements ModInitializer {
|
||||
.getProgress(advancement)
|
||||
.isDone();
|
||||
}
|
||||
public static void playPlaneAnimation(PlaneAnimation animation, int entityId) {
|
||||
for (ServerWorld world : SERVER.getWorlds()) {
|
||||
for (ServerPlayerEntity player : world.getPlayers()) {
|
||||
PacketByteBuf buf = PacketByteBufs.create();
|
||||
buf.writeInt(entityId); // <-- important change
|
||||
buf.writeEnumConstant(animation); // PlaneAnimation
|
||||
ServerPlayNetworking.send(player, PLANE_ANIM_PACKET, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final Map<PlaneAnimation, Integer> ANIMATION_TIMINGS = new HashMap<>();
|
||||
|
||||
static {
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.START_ENGINE, 46); // 2.2917s * 20 ticks
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.STOP_ENGINE, 40); // 2.0s * 20 ticks
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.FLYING, -1); // looping
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.LANDING, 40); // 2.0s * 20 ticks
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.LAND_STARTED, -1); // looping
|
||||
ANIMATION_TIMINGS.put(PlaneAnimation.LIFT_UP, 30); // 1.5s * 20 ticks
|
||||
}
|
||||
public static final Map<PlaneAnimation, Float> ANIMATION_TIMINGS_SECONDS = new HashMap<>();
|
||||
|
||||
static {
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.START_ENGINE, 2.2917f); // 2.2917s * 20 ticks
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.STOP_ENGINE, 20f); // 2.0s * 20 ticks
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.FLYING, -1f); // looping
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LANDING, 2f); // 2.0s * 20 ticks
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LAND_STARTED, -1f); // looping
|
||||
ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LIFT_UP, 1.5f); // 1.5s * 20 ticks
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,8 @@
|
||||
"effect.szar.arrested": "Arrested",
|
||||
"item.szar.police_key": "Police Key",
|
||||
"item.szar.police_handcuff": "Police Handcuff",
|
||||
"entity.szar.gypsy": "Cigány"
|
||||
"entity.szar.gypsy": "Cigány",
|
||||
"entity.szar.plane": "Plane",
|
||||
"entity.szar.hitler": "Hitler",
|
||||
"item.szar.hitler_spawn_egg":"Hitler Spawn Egg"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "minecraft:item/template_spawn_egg"
|
||||
}
|
||||
BIN
src/main/resources/assets/szar/textures/entity/hitter.png
Normal file
BIN
src/main/resources/assets/szar/textures/entity/hitter.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/assets/szar/textures/entity/plane.png
Normal file
BIN
src/main/resources/assets/szar/textures/entity/plane.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,3 +1,4 @@
|
||||
accessWidener v2 named
|
||||
|
||||
accessible field net/minecraft/client/gui/hud/InGameHud spyglassScale F
|
||||
accessible field net/minecraft/client/gui/hud/InGameHud spyglassScale F
|
||||
accessible field net/minecraft/entity/LivingEntity jumping Z
|
||||
Reference in New Issue
Block a user