mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
3 more patches
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
java
|
||||
id("com.github.johnrengelman.shadow") version "7.0.0" apply false
|
||||
id("io.papermc.paperweight.patcher") version "1.0.4-SNAPSHOT"
|
||||
id("io.papermc.paperweight.patcher") version "1.1.0-SNAPSHOT"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 9 May 2019 18:26:06 -0500
|
||||
Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c133bc3f733 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
@@ -14,6 +14,7 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
+import net.minecraft.world.entity.monster.Phantom;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@@ -32,6 +33,12 @@ public class EndCrystal extends Entity {
|
||||
private static final EntityDataAccessor<Boolean> DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN);
|
||||
public int time;
|
||||
public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals
|
||||
+ // Purpur start
|
||||
+ private Phantom targetPhantom;
|
||||
+ private int phantomBeamTicks = 0;
|
||||
+ private int phantomDamageCooldown = 0;
|
||||
+ private int idleCooldown = 0;
|
||||
+ // Purpur end
|
||||
|
||||
public EndCrystal(EntityType<? extends EndCrystal> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -81,7 +88,50 @@ public class EndCrystal extends Entity {
|
||||
// Paper end
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ if (level.purpurConfig.phantomAttackedByCrystalRadius <= 0 || --idleCooldown > 0) {
|
||||
+ return; // on cooldown
|
||||
+ }
|
||||
+
|
||||
+ if (targetPhantom == null) {
|
||||
+ for (Phantom phantom : level.getEntitiesOfClass(Phantom.class, getBoundingBox().inflate(level.purpurConfig.phantomAttackedByCrystalRadius))) {
|
||||
+ if (phantom.hasLineOfSight(this)) {
|
||||
+ attackPhantom(phantom);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ setBeamTarget(new BlockPos(targetPhantom).offset(0, -2, 0));
|
||||
+ if (--phantomBeamTicks > 0 && targetPhantom.isAlive()) {
|
||||
+ phantomDamageCooldown--;
|
||||
+ if (targetPhantom.hasLineOfSight(this)) {
|
||||
+ if (phantomDamageCooldown <= 0) {
|
||||
+ phantomDamageCooldown = 20;
|
||||
+ targetPhantom.hurt(DamageSource.indirectMagic(this, this), level.purpurConfig.phantomAttackedByCrystalDamage);
|
||||
+ }
|
||||
+ } else {
|
||||
+ forgetPhantom(); // no longer in sight
|
||||
+ }
|
||||
+ } else {
|
||||
+ forgetPhantom(); // attacked long enough
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void attackPhantom(Phantom phantom) {
|
||||
+ phantomDamageCooldown = 0;
|
||||
+ phantomBeamTicks = 60;
|
||||
+ targetPhantom = phantom;
|
||||
+ }
|
||||
+
|
||||
+ private void forgetPhantom() {
|
||||
+ targetPhantom = null;
|
||||
+ setBeamTarget(null);
|
||||
+ phantomBeamTicks = 0;
|
||||
+ phantomDamageCooldown = 0;
|
||||
+ idleCooldown = 60;
|
||||
}
|
||||
+ // Purpur end
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag nbt) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2ddcd1306f4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
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.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
@@ -36,10 +37,15 @@ import net.minecraft.world.entity.ai.control.MoveControl;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
|
||||
import net.minecraft.world.entity.animal.Cat;
|
||||
+import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
+import net.minecraft.world.level.storage.loot.LootContext;
|
||||
+import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Phantom extends FlyingMob implements Enemy {
|
||||
@@ -50,6 +56,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
Vec3 moveTargetPoint;
|
||||
BlockPos anchorPoint;
|
||||
Phantom.AttackPhase attackPhase;
|
||||
+ Vec3 crystalPosition; // Purpur
|
||||
|
||||
public Phantom(EntityType<? extends Phantom> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -73,12 +80,38 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
- this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal());
|
||||
- this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal());
|
||||
- this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal());
|
||||
+ // Purpur start
|
||||
+ if (level.purpurConfig.phantomOrbitCrystalRadius > 0) {
|
||||
+ this.goalSelector.addGoal(1, new FindCrystalGoal(this));
|
||||
+ this.goalSelector.addGoal(2, new OrbitCrystalGoal(this));
|
||||
+ }
|
||||
+ this.goalSelector.addGoal(3, new Phantom.PhantomAttackStrategyGoal());
|
||||
+ this.goalSelector.addGoal(4, new Phantom.PhantomSweepAttackGoal());
|
||||
+ this.goalSelector.addGoal(5, new Phantom.PhantomCircleAroundAnchorGoal());
|
||||
this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal());
|
||||
+ // Purpur end
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ @Override
|
||||
+ protected LootContext.Builder createLootContext(boolean causedByPlayer, DamageSource source) {
|
||||
+ boolean dropped = false;
|
||||
+ if (lastHurtByPlayer == null && source.getEntity() instanceof EndCrystal) {
|
||||
+ if (random.nextInt(5) < 1) {
|
||||
+ dropped = spawnAtLocation(new ItemStack(Items.PHANTOM_MEMBRANE)) != null;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!dropped) {
|
||||
+ return super.createLootContext(causedByPlayer, source);
|
||||
+ }
|
||||
+ return new LootContext.Builder((ServerLevel) level);
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCirclingCrystal() {
|
||||
+ return crystalPosition != null;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
@@ -263,6 +296,124 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
private AttackPhase() {}
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ class FindCrystalGoal extends Goal {
|
||||
+ private final Phantom phantom;
|
||||
+ private EndCrystal crystal;
|
||||
+ private Comparator<EndCrystal> comparator;
|
||||
+
|
||||
+ FindCrystalGoal(Phantom phantom) {
|
||||
+ this.phantom = phantom;
|
||||
+ this.comparator = Comparator.comparingDouble(phantom::distanceToSqr);
|
||||
+ this.setFlags(EnumSet.of(Flag.LOOK));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldActivate() {
|
||||
+ double range = maxTargetRange();
|
||||
+ List<EndCrystal> crystals = level.getEntitiesOfClass(EndCrystal.class, phantom.getBoundingBox().inflate(range));
|
||||
+ if (crystals.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ crystals.sort(comparator);
|
||||
+ crystal = crystals.get(0);
|
||||
+ if (phantom.distanceToSqr(crystal) > range * range) {
|
||||
+ crystal = null;
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldStayActive() {
|
||||
+ if (crystal == null || !crystal.isAlive()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ double range = maxTargetRange();
|
||||
+ return phantom.distanceToSqr(crystal) <= (range * range) * 2;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void start() {
|
||||
+ phantom.crystalPosition = new Vec3(crystal.getX(), crystal.getY() + (phantom.random.nextInt(10) + 10), crystal.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stop() {
|
||||
+ crystal = null;
|
||||
+ phantom.crystalPosition = null;
|
||||
+ super.stop();
|
||||
+ }
|
||||
+
|
||||
+ private double maxTargetRange() {
|
||||
+ return phantom.level.purpurConfig.phantomOrbitCrystalRadius;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class OrbitCrystalGoal extends Goal {
|
||||
+ private final Phantom phantom;
|
||||
+ private float offset;
|
||||
+ private float radius;
|
||||
+ private float verticalChange;
|
||||
+ private float direction;
|
||||
+
|
||||
+ OrbitCrystalGoal(Phantom phantom) {
|
||||
+ this.phantom = phantom;
|
||||
+ this.setFlags(EnumSet.of(Flag.MOVE));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldActivate() {
|
||||
+ return phantom.isCirclingCrystal();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void start() {
|
||||
+ this.radius = 5.0F + phantom.random.nextFloat() * 10.0F;
|
||||
+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F;
|
||||
+ this.direction = phantom.random.nextBoolean() ? 1.0F : -1.0F;
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void tick() {
|
||||
+ if (phantom.random.nextInt(350) == 0) {
|
||||
+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F;
|
||||
+ }
|
||||
+ if (phantom.random.nextInt(250) == 0) {
|
||||
+ ++this.radius;
|
||||
+ if (this.radius > 15.0F) {
|
||||
+ this.radius = 5.0F;
|
||||
+ this.direction = -this.direction;
|
||||
+ }
|
||||
+ }
|
||||
+ if (phantom.random.nextInt(450) == 0) {
|
||||
+ this.offset = phantom.random.nextFloat() * 2.0F * 3.1415927F;
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.distanceToSqr(phantom.getX(), phantom.getY(), phantom.getZ()) < 4.0D) {
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.y < phantom.getY() && !phantom.level.isEmptyBlock(new BlockPos(phantom).below(1))) {
|
||||
+ this.verticalChange = Math.max(1.0F, this.verticalChange);
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.y > phantom.getY() && !phantom.level.isEmptyBlock(new BlockPos(phantom).above(1))) {
|
||||
+ this.verticalChange = Math.min(-1.0F, this.verticalChange);
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void updateOffset() {
|
||||
+ this.offset += this.direction * 15.0F * 0.017453292F;
|
||||
+ phantom.moveTargetPoint = phantom.crystalPosition.add(
|
||||
+ this.radius * Mth.cos(this.offset),
|
||||
+ -4.0F + this.verticalChange,
|
||||
+ this.radius * Mth.sin(this.offset));
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
private class PhantomMoveControl extends MoveControl {
|
||||
|
||||
private float speed = 0.1F;
|
||||
@@ -349,6 +500,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
+ if (isCirclingCrystal()) return false;
|
||||
LivingEntity entityliving = Phantom.this.getTarget();
|
||||
|
||||
return entityliving != null ? Phantom.this.canAttack(Phantom.this.getTarget(), TargetingConditions.DEFAULT) : false;
|
||||
@@ -538,6 +690,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
+ if (isCirclingCrystal()) return false;
|
||||
if (this.nextScanTick > 0) {
|
||||
--this.nextScanTick;
|
||||
return false;
|
||||
@@ -566,6 +719,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
+ if (isCirclingCrystal()) return false;
|
||||
LivingEntity entityliving = Phantom.this.getTarget();
|
||||
|
||||
return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false;
|
||||
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
index e39e1ff19f49b093ae27a98cba280ad2643df7a2..8985cc0ca2e5f1f673ef6ae59976095993332559 100644
|
||||
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
@@ -617,6 +617,9 @@ public class PurpurWorldConfig {
|
||||
public float phantomFlameDamage = 1.0F;
|
||||
public int phantomFlameFireTime = 8;
|
||||
public boolean phantomAllowGriefing = false;
|
||||
+ public double phantomAttackedByCrystalRadius = 0.0D;
|
||||
+ public float phantomAttackedByCrystalDamage = 1.0F;
|
||||
+ public double phantomOrbitCrystalRadius = 0.0D;
|
||||
private void phantomSettings() {
|
||||
phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
|
||||
phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
|
||||
@@ -624,6 +627,9 @@ public class PurpurWorldConfig {
|
||||
phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage);
|
||||
phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime);
|
||||
phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
|
||||
+ phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
|
||||
+ phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
|
||||
+ phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
|
||||
}
|
||||
|
||||
public boolean pigRidable = false;
|
||||
232
patches/server/0077-Add-phantom-spawning-options.patch
Normal file
232
patches/server/0077-Add-phantom-spawning-options.patch
Normal file
@@ -0,0 +1,232 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Fri, 3 Jul 2020 00:03:52 -0500
|
||||
Subject: [PATCH] Add phantom spawning options
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
index 79504dc3448402e73b09c4232b1fd0488872cf68..5c7683058b79953aa4f7427d7654b7e4823dbf09 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -2,12 +2,15 @@ package net.minecraft.world.level.levelgen;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
+import net.minecraft.stats.Stat;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
@@ -23,84 +26,100 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.NaturalSpawner;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
public class PhantomSpawner implements CustomSpawner {
|
||||
|
||||
- private int nextTick;
|
||||
+ private int spawnDelay; // Purpur
|
||||
|
||||
public PhantomSpawner() {}
|
||||
|
||||
@Override
|
||||
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
|
||||
+ // Purpur start - rewrite entire thing
|
||||
if (!spawnMonsters) {
|
||||
return 0;
|
||||
- } else if (!world.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
|
||||
+ }
|
||||
+
|
||||
+ if (!world.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ --this.spawnDelay;
|
||||
+ if (this.spawnDelay > 0) {
|
||||
return 0;
|
||||
- } else {
|
||||
- Random random = world.random;
|
||||
-
|
||||
- --this.nextTick;
|
||||
- if (this.nextTick > 0) {
|
||||
- return 0;
|
||||
- } else {
|
||||
- this.nextTick += (60 + random.nextInt(60)) * 20;
|
||||
- if (world.getSkyDarken() < 5 && world.dimensionType().hasSkyLight()) {
|
||||
- return 0;
|
||||
- } else {
|
||||
- int i = 0;
|
||||
- Iterator iterator = world.players().iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- Player entityhuman = (Player) iterator.next();
|
||||
-
|
||||
- if (!entityhuman.isSpectator() && (!world.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper
|
||||
- BlockPos blockposition = entityhuman.blockPosition();
|
||||
-
|
||||
- if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) {
|
||||
- DifficultyInstance difficultydamagescaler = world.getCurrentDifficultyAt(blockposition);
|
||||
-
|
||||
- if (difficultydamagescaler.isHarderThan(random.nextFloat() * 3.0F)) {
|
||||
- ServerStatsCounter serverstatisticmanager = ((ServerPlayer) entityhuman).getStats();
|
||||
- int j = Mth.clamp(serverstatisticmanager.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
|
||||
- boolean flag2 = true;
|
||||
-
|
||||
- if (random.nextInt(j) >= 72000) {
|
||||
- BlockPos blockposition1 = blockposition.above(20 + random.nextInt(15)).east(-10 + random.nextInt(21)).south(-10 + random.nextInt(21));
|
||||
- BlockState iblockdata = world.getBlockState(blockposition1);
|
||||
- FluidState fluid = world.getFluidState(blockposition1);
|
||||
-
|
||||
- if (NaturalSpawner.isValidEmptySpawnBlock((BlockGetter) world, blockposition1, iblockdata, fluid, EntityType.PHANTOM)) {
|
||||
- SpawnGroupData groupdataentity = null;
|
||||
- int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1);
|
||||
-
|
||||
- for (int l = 0; l < k; ++l) {
|
||||
- // Paper start
|
||||
- com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(world, blockposition1), ((ServerPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL);
|
||||
- if (!event.callEvent()) {
|
||||
- if (event.shouldAbortSpawn()) {
|
||||
- break;
|
||||
- }
|
||||
- continue;
|
||||
- }
|
||||
- // Paper end
|
||||
- Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world);
|
||||
- entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper
|
||||
- entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
|
||||
- groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null);
|
||||
- world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
|
||||
- }
|
||||
-
|
||||
- i += k;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ }
|
||||
+ this.spawnDelay += world.purpurConfig.phantomSpawnDelayMin + world.random.nextInt(world.purpurConfig.phantomSpawnDelayMax - world.purpurConfig.phantomSpawnDelayMin);
|
||||
+
|
||||
+ if (!world.dimensionType().hasSkyLight() || world.getSkyDarken() < world.purpurConfig.phantomSpawnMinSkyDarkness) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ int numberSpawnsAttempted = 0;
|
||||
+ for (ServerPlayer player : world.players()) {
|
||||
+ if (player.isSpectator() || (player.isCreative() && world.paperConfig.phantomIgnoreCreative)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ BlockPos playerPos = player.blockPosition();
|
||||
+ if (playerPos.getY() < world.getSeaLevel() && world.purpurConfig.phantomSpawnOnlyAboveSeaLevel) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!world.canSeeSky(playerPos) && world.purpurConfig.phantomSpawnOnlyWithVisibleSky) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ DifficultyInstance difficultyInstance = world.getCurrentDifficultyAt(playerPos);
|
||||
+ if (!difficultyInstance.isHarderThan(world.random.nextFloat() * (float) world.purpurConfig.phantomSpawnLocalDifficultyChance)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ServerStatsCounter stats = player.getStats();
|
||||
+ int timeSinceRest = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
|
||||
+ if (world.random.nextInt(timeSinceRest) < world.purpurConfig.phantomSpawnMinTimeSinceSlept) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ BlockPos spawnPos = playerPos
|
||||
+ .above(world.purpurConfig.phantomSpawnMinOverhead + world.random.nextInt(world.purpurConfig.phantomSpawnMaxOverhead - world.purpurConfig.phantomSpawnMinOverhead))
|
||||
+ .east(-world.purpurConfig.phantomSpawnOverheadRadius + world.random.nextInt(world.purpurConfig.phantomSpawnOverheadRadius + 1))
|
||||
+ .south(-world.purpurConfig.phantomSpawnOverheadRadius + world.random.nextInt(world.purpurConfig.phantomSpawnOverheadRadius + 1));
|
||||
+
|
||||
+ if (!NaturalSpawner.isValidEmptySpawnBlock(world, spawnPos, world.getTypeIfLoaded(spawnPos), world.getFluidState(spawnPos), EntityType.PHANTOM)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ int difficulty = difficultyInstance.getDifficulty().getId();
|
||||
+ int spawnAttempts = world.purpurConfig.phantomSpawnMinPerAttempt + world.random.nextInt((world.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? difficulty : world.purpurConfig.phantomSpawnMaxPerAttempt) + world.purpurConfig.phantomSpawnMinPerAttempt);
|
||||
+
|
||||
+ SpawnGroupData groupData = null;
|
||||
+ for (int count = 0; count < spawnAttempts; ++count) {
|
||||
+ // Paper start
|
||||
+ PhantomPreSpawnEvent event = new PhantomPreSpawnEvent(MCUtil.toLocation(world, spawnPos), player.getBukkitEntity(), CreatureSpawnEvent.SpawnReason.NATURAL);
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ break;
|
||||
}
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- return i;
|
||||
+ Phantom phantom = EntityType.PHANTOM.create(world);
|
||||
+ if (phantom == null) {
|
||||
+ continue;
|
||||
}
|
||||
+
|
||||
+ phantom.setSpawningEntity(player.getUUID());
|
||||
+ phantom.moveTo(playerPos, 0.0F, 0.0F);
|
||||
+ groupData = phantom.finalizeSpawn(world, difficultyInstance, MobSpawnType.NATURAL, groupData, null);
|
||||
+ world.addEntity(phantom, CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
|
||||
}
|
||||
+
|
||||
+ numberSpawnsAttempted += spawnAttempts;
|
||||
}
|
||||
+
|
||||
+ return numberSpawnsAttempted;
|
||||
+ // Purpur end - rewrite entire thing
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
index 8985cc0ca2e5f1f673ef6ae59976095993332559..891b0ef41e57e95ab3aa7b14891ba53abd135171 100644
|
||||
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
@@ -620,6 +620,18 @@ public class PurpurWorldConfig {
|
||||
public double phantomAttackedByCrystalRadius = 0.0D;
|
||||
public float phantomAttackedByCrystalDamage = 1.0F;
|
||||
public double phantomOrbitCrystalRadius = 0.0D;
|
||||
+ public int phantomSpawnDelayMin = 1200;
|
||||
+ public int phantomSpawnDelayMax = 2400;
|
||||
+ public int phantomSpawnMinSkyDarkness = 5;
|
||||
+ public boolean phantomSpawnOnlyAboveSeaLevel = true;
|
||||
+ public boolean phantomSpawnOnlyWithVisibleSky = true;
|
||||
+ public double phantomSpawnLocalDifficultyChance = 3.0D;
|
||||
+ public int phantomSpawnMinTimeSinceSlept = 72000;
|
||||
+ public int phantomSpawnMinOverhead = 20;
|
||||
+ public int phantomSpawnMaxOverhead = 35;
|
||||
+ public int phantomSpawnOverheadRadius = 10;
|
||||
+ public int phantomSpawnMinPerAttempt = 1;
|
||||
+ public int phantomSpawnMaxPerAttempt = -1;
|
||||
private void phantomSettings() {
|
||||
phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
|
||||
phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
|
||||
@@ -630,6 +642,18 @@ public class PurpurWorldConfig {
|
||||
phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
|
||||
phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
|
||||
phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
|
||||
+ phantomSpawnDelayMin = getInt("mobs.phantom.spawn.delay.min", phantomSpawnDelayMin);
|
||||
+ phantomSpawnDelayMax = getInt("mobs.phantom.spawn.delay.max", phantomSpawnDelayMax);
|
||||
+ phantomSpawnMinSkyDarkness = getInt("mobs.phantom.spawn.min-sky-darkness", phantomSpawnMinSkyDarkness);
|
||||
+ phantomSpawnOnlyAboveSeaLevel = getBoolean("mobs.phantom.spawn.only-above-sea-level", phantomSpawnOnlyAboveSeaLevel);
|
||||
+ phantomSpawnOnlyWithVisibleSky = getBoolean("mobs.phantom.spawn.only-with-visible-sky", phantomSpawnOnlyWithVisibleSky);
|
||||
+ phantomSpawnLocalDifficultyChance = getDouble("mobs.phantom.spawn.local-difficulty-chance", phantomSpawnLocalDifficultyChance);
|
||||
+ phantomSpawnMinTimeSinceSlept = getInt("mobs.phantom.spawn.min-time-since-slept", phantomSpawnMinTimeSinceSlept);
|
||||
+ phantomSpawnMinOverhead = getInt("mobs.phantom.spawn.overhead.min", phantomSpawnMinOverhead);
|
||||
+ phantomSpawnMaxOverhead = getInt("mobs.phantom.spawn.overhead.max", phantomSpawnMaxOverhead);
|
||||
+ phantomSpawnOverheadRadius = getInt("mobs.phantom.spawn.overhead.radius", phantomSpawnOverheadRadius);
|
||||
+ phantomSpawnMinPerAttempt = getInt("mobs.phantom.spawn.per-attempt.min", phantomSpawnMinPerAttempt);
|
||||
+ phantomSpawnMaxPerAttempt = getInt("mobs.phantom.spawn.per-attempt.max", phantomSpawnMaxPerAttempt);
|
||||
}
|
||||
|
||||
public boolean pigRidable = false;
|
||||
62
patches/server/0078-Implement-bed-explosion-options.patch
Normal file
62
patches/server/0078-Implement-bed-explosion-options.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 4 Jul 2020 13:12:43 -0500
|
||||
Subject: [PATCH] Implement bed explosion options
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
|
||||
index 163a7861f987c3832aac51cc6df950c768546731..cfe4cdbd28ff11ea2781d47fe6d8c2de7912a3f6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
|
||||
@@ -97,7 +97,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
|
||||
world.removeBlock(blockposition1, false);
|
||||
}
|
||||
|
||||
- world.explode((Entity) null, DamageSource.badRespawnPointExplosion(), (ExplosionDamageCalculator) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0F, true, Explosion.BlockInteraction.DESTROY);
|
||||
+ if (world.purpurConfig.bedExplode) world.explode((Entity) null, DamageSource.badRespawnPointExplosion(), null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Purpur
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
|
||||
if (!this.kickVillagerOutOfBed(world, pos)) {
|
||||
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
index 891b0ef41e57e95ab3aa7b14891ba53abd135171..d232768e789ea6a7790cada4a4ad2624cd32e4b2 100644
|
||||
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
||||
@@ -4,6 +4,7 @@ import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
+import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -12,6 +13,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
+import java.util.logging.Level;
|
||||
|
||||
import static net.pl3x.purpur.PurpurConfig.log;
|
||||
|
||||
@@ -258,6 +260,22 @@ public class PurpurWorldConfig {
|
||||
});
|
||||
}
|
||||
|
||||
+ public boolean bedExplode = true;
|
||||
+ public double bedExplosionPower = 5.0D;
|
||||
+ public boolean bedExplosionFire = true;
|
||||
+ public Explosion.BlockInteraction bedExplosionEffect = Explosion.BlockInteraction.DESTROY;
|
||||
+ private void bedSettings() {
|
||||
+ bedExplode = getBoolean("blocks.bed.explode", bedExplode);
|
||||
+ bedExplosionPower = getDouble("blocks.bed.explosion-power", bedExplosionPower);
|
||||
+ bedExplosionFire = getBoolean("blocks.bed.explosion-fire", bedExplosionFire);
|
||||
+ try {
|
||||
+ bedExplosionEffect = Explosion.BlockInteraction.valueOf(getString("blocks.bed.explosion-effect", bedExplosionEffect.name()));
|
||||
+ } catch (IllegalArgumentException e) {
|
||||
+ log(Level.SEVERE, "Unknown value for `blocks.bed.explosion-effect`! Using default of `DESTROY`");
|
||||
+ bedExplosionEffect = Explosion.BlockInteraction.DESTROY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public boolean dispenserApplyCursedArmor = true;
|
||||
private void dispenserSettings() {
|
||||
dispenserApplyCursedArmor = getBoolean("blocks.dispenser.apply-cursed-to-armor-slots", dispenserApplyCursedArmor);
|
||||
Reference in New Issue
Block a user