mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-04-22 11:18:15 +02:00
43/103 rejected minecraft source files applied
(idk what i was counting in the previous commit...)
This commit is contained in:
@@ -1,6 +1,33 @@
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -380,7 +_,7 @@
|
||||
@@ -168,6 +_,7 @@
|
||||
SlotProvider,
|
||||
DebugValueSource,
|
||||
TypedInstance<EntityType<?>> {
|
||||
+ public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes
|
||||
// CraftBukkit start
|
||||
private static final int CURRENT_LEVEL = 2;
|
||||
static boolean isLevelAtLeast(ValueInput input, int level) {
|
||||
@@ -341,8 +_,9 @@
|
||||
public double xOld;
|
||||
public double yOld;
|
||||
public double zOld;
|
||||
+ public float maxUpStep; // Purpur - Add option to set armorstand step height
|
||||
public boolean noPhysics;
|
||||
- public final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
|
||||
+ public final RandomSource random; // Paper - Share random for entities to make them more random // Add toggle for RNG manipulation
|
||||
public int tickCount;
|
||||
private int remainingFireTicks;
|
||||
private final EntityFluidInteraction fluidInteraction = new EntityFluidInteraction(Set.of(FluidTags.WATER, FluidTags.LAVA));
|
||||
@@ -374,13 +_,13 @@
|
||||
public @Nullable PortalProcessor portalProcess;
|
||||
public int portalCooldown;
|
||||
private boolean invulnerable;
|
||||
- protected UUID uuid = Mth.createInsecureUUID(this.random);
|
||||
- protected String stringUUID = this.uuid.toString();
|
||||
+ protected UUID uuid; // Purpur - Add toggle for RNG manipulation
|
||||
+ protected String stringUUID; // Purpur - Add toggle for RNG manipulation
|
||||
private boolean hasGlowingTag;
|
||||
private final Set<String> tags = new io.papermc.paper.util.SizeLimitedSet<>(new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(), MAX_ENTITY_TAG_COUNT); // Paper - fully limit tag size - replace set impl
|
||||
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
|
||||
private long pistonDeltasGameTime;
|
||||
@@ -9,3 +36,141 @@
|
||||
private float eyeHeight;
|
||||
public boolean isInPowderSnow;
|
||||
public boolean wasInPowderSnow;
|
||||
@@ -426,6 +_,7 @@
|
||||
private final int despawnTime; // Paper - entity despawn time limit
|
||||
public int totalEntityAge; // Paper - age-like counter for all entities
|
||||
public final io.papermc.paper.entity.activation.ActivationType activationType = io.papermc.paper.entity.activation.ActivationType.activationTypeFor(this); // Paper - EAR 2/tracking ranges
|
||||
+ public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API
|
||||
// CraftBukkit end
|
||||
|
||||
// Paper start
|
||||
@@ -434,10 +_,22 @@
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Purpur start - Add canSaveToDisk to Entity
|
||||
+ public boolean canSaveToDisk() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Purpur end - Add canSaveToDisk to Entity
|
||||
+
|
||||
public Entity(final EntityType<?> type, final Level level) {
|
||||
this.type = type;
|
||||
this.level = level;
|
||||
this.dimensions = type.getDimensions();
|
||||
+ this.maxAirTicks = level == null ? Entity.TOTAL_AIR_SUPPLY : this.level.purpurConfig.drowningAirTicks; // Purpur - Drowning Settings
|
||||
+ // Purpur start - Add toggle for RNG manipulation
|
||||
+ this.random = level == null || level.purpurConfig.entitySharedRandom ? SHARED_RANDOM : RandomSource.create();
|
||||
+ this.uuid = Mth.createInsecureUUID(this.random);
|
||||
+ this.stringUUID = this.uuid.toString();
|
||||
+ // Purpur end - Add toggle for RNG manipulation
|
||||
this.position = Vec3.ZERO;
|
||||
this.blockPosition = BlockPos.ZERO;
|
||||
this.chunkPosition = ChunkPos.ZERO;
|
||||
@@ -828,6 +_,7 @@
|
||||
&& this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
|
||||
&& (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
|
||||
// Paper end - Configurable nether ceiling damage
|
||||
+ if (this.level.purpurConfig.teleportOnNetherCeilingDamage && this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this instanceof ServerPlayer player) player.teleport(org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.level.levelData.getRespawnData().pos(), this.level)); else // Purpur - Add option to teleport to spawn on nether ceiling damage
|
||||
this.onBelowWorld();
|
||||
}
|
||||
}
|
||||
@@ -1826,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean fireImmune() {
|
||||
- return this.getType().fireImmune();
|
||||
+ return this.immuneToFire != null ? immuneToFire : this.getType().fireImmune(); // Purpur - add fire immune API
|
||||
}
|
||||
|
||||
public boolean causeFallDamage(final double fallDistance, final float damageModifier, final DamageSource damageSource) {
|
||||
@@ -2412,7 +_,7 @@
|
||||
output.putBoolean("Bukkit.invisible", this.persistentInvisibility);
|
||||
}
|
||||
// SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
- if (this.maxAirTicks != this.getDefaultMaxAirSupply()) {
|
||||
+ if (this.maxAirTicks != this.getDefaultMaxAirSupply() && this.getDefaultMaxAirSupply() != this.level().purpurConfig.drowningAirTicks) { // Purpur - Drowning Settings
|
||||
output.putInt("Bukkit.MaxAirSupply", this.getMaxAirSupply());
|
||||
}
|
||||
output.putInt("Spigot.ticksLived", this.totalEntityAge); // Paper
|
||||
@@ -2499,6 +_,11 @@
|
||||
output.putBoolean("Paper.FreezeLock", true);
|
||||
}
|
||||
// Paper end
|
||||
+ // Purpur start - Fire immune API
|
||||
+ if (immuneToFire != null) {
|
||||
+ output.putBoolean("Purpur.FireImmune", immuneToFire);
|
||||
+ }
|
||||
+ // Purpur end - Fire immune API
|
||||
} catch (Throwable var7) {
|
||||
CrashReport report = CrashReport.forThrowable(var7, "Saving entity NBT");
|
||||
CrashReportCategory category = report.addCategory("Entity being saved");
|
||||
@@ -2621,6 +_,9 @@
|
||||
}
|
||||
freezeLocked = input.getBooleanOr("Paper.FreezeLock", false);
|
||||
// Paper end
|
||||
+
|
||||
+ immuneToFire = input.read("Purpur.FireImmune", com.mojang.serialization.Codec.BOOL).orElse(null); // Purpur - Fire immune API
|
||||
+
|
||||
} catch (Throwable var7) {
|
||||
CrashReport report = CrashReport.forThrowable(var7, "Loading entity NBT");
|
||||
CrashReportCategory category = report.addCategory("Entity being loaded");
|
||||
@@ -2800,6 +_,7 @@
|
||||
if (this.isAlive() && this instanceof Leashable leashablex) {
|
||||
if (leashablex.getLeashHolder() == player) {
|
||||
if (!this.level().isClientSide()) {
|
||||
+ if (hand == InteractionHand.OFF_HAND && (level().purpurConfig.villagerCanBeLeashed || level().purpurConfig.wanderingTraderCanBeLeashed) && this instanceof net.minecraft.world.entity.npc.villager.AbstractVillager) return InteractionResult.CONSUME; // Purpur - Allow leashing villagers
|
||||
// Paper start - EntityUnleashEvent
|
||||
if (!org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerUnleashEntityEvent(
|
||||
leashablex, player, hand, !player.hasInfiniteMaterials(), true
|
||||
@@ -3230,15 +_,18 @@
|
||||
return Vec3.directionFromRotation(this.getRotationVector());
|
||||
}
|
||||
|
||||
+ public BlockPos portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals
|
||||
public void setAsInsidePortal(final Portal portal, final BlockPos pos) {
|
||||
if (this.isOnPortalCooldown()) {
|
||||
+ if (!(level().purpurConfig.playerFixStuckPortal && this instanceof Player && !pos.equals(this.portalPos))) // Purpur - Fix stuck in portals
|
||||
this.setPortalCooldown();
|
||||
- } else {
|
||||
+ } else if (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer) { // Purpur - Entities can use portals
|
||||
if (this.portalProcess == null || !this.portalProcess.isSamePortal(portal)) {
|
||||
this.portalProcess = new PortalProcessor(portal, pos.immutable());
|
||||
} else if (!this.portalProcess.isInsidePortalThisTick()) {
|
||||
this.portalProcess.updateEntryPosition(pos.immutable());
|
||||
this.portalProcess.setAsInsidePortalThisTick(true);
|
||||
+ this.portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3967,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean canUsePortal(final boolean ignorePassenger) {
|
||||
- return (ignorePassenger || !this.isPassenger()) && this.isAlive();
|
||||
+ return (ignorePassenger || !this.isPassenger()) && this.isAlive() && (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer); // Purpur - Entities can use portals
|
||||
}
|
||||
|
||||
public boolean canTeleport(final Level from, final Level to) {
|
||||
@@ -4515,6 +_,12 @@
|
||||
return Mth.lerp(partial, this.yRotO, this.yRot);
|
||||
}
|
||||
|
||||
+ // Purpur start - Stop squids floating on top of water
|
||||
+ public AABB getAxisForFluidCheck() {
|
||||
+ return this.getBoundingBox().deflate(0.001D);
|
||||
+ }
|
||||
+ // Purpur end - Stop squids floating on top of water
|
||||
+
|
||||
public boolean touchingUnloadedChunk() {
|
||||
AABB box = this.getBoundingBox().inflate(1.0);
|
||||
int x0 = Mth.floor(box.minX);
|
||||
@@ -4809,7 +_,7 @@
|
||||
}
|
||||
|
||||
public float maxUpStep() {
|
||||
- return 0.0F;
|
||||
+ return maxUpStep; // Purpur - Add option to set armorstand step height
|
||||
}
|
||||
|
||||
public void onExplosionHit(final @Nullable Entity explosionCausedBy) {
|
||||
|
||||
@@ -9,3 +9,45 @@
|
||||
private final float spawnDimensionsScale;
|
||||
private final FeatureFlagSet requiredFeatures;
|
||||
private final boolean allowedInPeaceful;
|
||||
@@ -1238,6 +_,16 @@
|
||||
return register(vanillaEntityId(vanillaId), builder);
|
||||
}
|
||||
|
||||
+ // Purpur start - PlayerSetSpawnerTypeWithEggEvent
|
||||
+ public static EntityType<?> getFromBukkitType(org.bukkit.entity.EntityType bukkitType) {
|
||||
+ return getFromKey(Identifier.parse(bukkitType.getKey().toString()));
|
||||
+ }
|
||||
+
|
||||
+ public static EntityType<?> getFromKey(Identifier location) {
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getValue(location);
|
||||
+ }
|
||||
+ // Purpur end - PlayerSetSpawnerTypeWithEggEvent
|
||||
+
|
||||
public static Identifier getKey(final EntityType<?> type) {
|
||||
return BuiltInRegistries.ENTITY_TYPE.getKey(type);
|
||||
}
|
||||
@@ -1495,6 +_,16 @@
|
||||
return this.category;
|
||||
}
|
||||
|
||||
+ // Purpur start - PlayerSetSpawnerTypeWithEggEvent
|
||||
+ public String getName() {
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getKey(this).getPath();
|
||||
+ }
|
||||
+
|
||||
+ public String getTranslatedName() {
|
||||
+ return getDescription().getString();
|
||||
+ }
|
||||
+ // Purpur end - PlayerSetSpawnerTypeWithEggEvent
|
||||
+
|
||||
public String getDescriptionId() {
|
||||
return this.descriptionId;
|
||||
}
|
||||
@@ -1556,6 +_,7 @@
|
||||
// Paper start - Add logging for debugging entity tags with invalid ids
|
||||
() -> {
|
||||
LOGGER.warn("Skipping Entity with id {}", input.getStringOr("id", "[invalid]"));
|
||||
+ LOGGER.warn("Location: {} {}", level.getWorld().getName(), input.read("Pos", net.minecraft.world.phys.Vec3.CODEC).orElse(net.minecraft.world.phys.Vec3.ZERO)); // Purpur - log skipped entity's position
|
||||
if ((DEBUG_ENTITIES_WITH_INVALID_IDS || level.getCraftServer().getServer().isDebugging()) && input instanceof TagValueInput tagInput) {
|
||||
LOGGER.warn("Skipped entity tag: {}", tagInput.input);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
--- a/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -352,7 +_,7 @@
|
||||
public void playerTouch(final Player player) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
|
||||
- player.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(player, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entity.takeXpDelay = 2;
|
||||
+ player.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(player, this.level().purpurConfig.playerExpPickupDelay, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entity.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay
|
||||
player.take(this, 1);
|
||||
int remaining = this.repairPlayerItems(serverPlayer, this.getValue());
|
||||
if (remaining > 0) {
|
||||
@@ -368,7 +_,8 @@
|
||||
}
|
||||
|
||||
private int repairPlayerItems(final ServerPlayer player, final int amount) {
|
||||
- Optional<EnchantedItemInUse> selected = EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged);
|
||||
+ Optional<EnchantedItemInUse> selected = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) :EnchantmentHelper.getRandomItemWith(// Purpur - Add option to mend the most damaged equipment first
|
||||
+ EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged);
|
||||
if (selected.isPresent()) {
|
||||
ItemStack itemStack = selected.get().itemStack();
|
||||
int toRepairFromXpAmount = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), itemStack, amount);
|
||||
@@ -1,5 +1,180 @@
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -440,6 +_,12 @@
|
||||
if (dist < 0.0) {
|
||||
double damagePerBlock = level.getWorldBorder().getDamagePerBlock();
|
||||
if (damagePerBlock > 0.0) {
|
||||
+ // Purpur start - Add option to teleport to spawn if outside world border
|
||||
+ if (this.level().purpurConfig.teleportIfOutsideBorder && this instanceof ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.teleport(org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.level().levelData.getRespawnData().pos(), this.level()));
|
||||
+ return;
|
||||
+ }
|
||||
+ // Purpur end - Add option to teleport to spawn if outside world border
|
||||
this.hurtServer(level, this.damageSources().outOfBorder(), Math.max(1, Mth.floor(-dist * damagePerBlock)));
|
||||
}
|
||||
}
|
||||
@@ -455,7 +_,7 @@
|
||||
if (this.shouldTakeDrowningDamage()) {
|
||||
this.setAirSupply(0);
|
||||
level.broadcastEntityEvent(this, EntityEvent.DROWN_PARTICLES);
|
||||
- this.hurtServer(level, this.damageSources().drown(), 2.0F);
|
||||
+ this.hurtServer(level, this.damageSources().drown(), (float) this.level().purpurConfig.damageFromDrowning); // Purpur - Drowning Settings
|
||||
}
|
||||
} else if (this.getAirSupply() < this.getMaxAirSupply() && MobEffectUtil.shouldEffectsRefillAirsupply(this)) {
|
||||
this.setAirSupply(this.increaseAirSupply(this.getAirSupply()));
|
||||
@@ -515,7 +_,7 @@
|
||||
}
|
||||
|
||||
protected boolean shouldTakeDrowningDamage() {
|
||||
- return this.getAirSupply() <= -20;
|
||||
+ return this.getAirSupply() <= -this.level().purpurConfig.drowningDamageInterval; // Purpur - Drowning Settings
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1045,15 +_,33 @@
|
||||
}
|
||||
|
||||
if (targetingEntity != null) {
|
||||
- ItemStack itemStack = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
- if (targetingEntity.is(EntityType.SKELETON) && itemStack.is(Items.SKELETON_SKULL)
|
||||
- || targetingEntity.is(EntityType.ZOMBIE) && itemStack.is(Items.ZOMBIE_HEAD)
|
||||
- || targetingEntity.is(EntityType.PIGLIN) && itemStack.is(Items.PIGLIN_HEAD)
|
||||
- || targetingEntity.is(EntityType.PIGLIN_BRUTE) && itemStack.is(Items.PIGLIN_HEAD)
|
||||
- || targetingEntity.is(EntityType.CREEPER) && itemStack.is(Items.CREEPER_HEAD)) {
|
||||
- visibilityPercent *= 0.5;
|
||||
- }
|
||||
- }
|
||||
+ ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
+ // Purpur start - Mob head visibility percent
|
||||
+ if (targetingEntity.is(EntityType.SKELETON) && itemBySlot.is(Items.SKELETON_SKULL)) {
|
||||
+ visibilityPercent *= targetingEntity.level().purpurConfig.skeletonHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if (targetingEntity.is(EntityType.ZOMBIE) && itemBySlot.is(Items.ZOMBIE_HEAD)) {
|
||||
+ visibilityPercent *= targetingEntity.level().purpurConfig.zombieHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if ((targetingEntity.is(EntityType.PIGLIN) || targetingEntity.is(EntityType.PIGLIN_BRUTE)) && itemBySlot.is(Items.PIGLIN_HEAD)) {
|
||||
+ visibilityPercent *= targetingEntity.level().purpurConfig.piglinHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if (targetingEntity.is(EntityType.CREEPER) && itemBySlot.is(Items.CREEPER_HEAD)) {
|
||||
+ visibilityPercent *= targetingEntity.level().purpurConfig.creeperHeadVisibilityPercent;
|
||||
+ }
|
||||
+ // Purpur end - Mob head visibility percent
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - Configurable mob blindness
|
||||
+ if (targetingEntity instanceof LivingEntity entityliving) {
|
||||
+ if (entityliving.hasEffect(MobEffects.BLINDNESS)) {
|
||||
+ int amplifier = entityliving.getEffect(MobEffects.BLINDNESS).getAmplifier();
|
||||
+ for (int i = 0; i < amplifier; i++) {
|
||||
+ d *= this.level().purpurConfig.mobsBlindnessMultiplier;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Configurable mob blindness
|
||||
|
||||
return visibilityPercent;
|
||||
}
|
||||
@@ -1100,6 +_,7 @@
|
||||
Iterator<MobEffectInstance> iterator = this.activeEffects.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
MobEffectInstance effect = iterator.next();
|
||||
+ if (cause == EntityPotionEffectEvent.Cause.MILK && !this.level().purpurConfig.milkClearsBeneficialEffects && effect.getEffect().value().isBeneficial()) continue; // Purpur - Milk Keeps Beneficial Effects
|
||||
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED);
|
||||
if (event.isCancelled()) {
|
||||
continue;
|
||||
@@ -1431,6 +_,24 @@
|
||||
this.stopSleeping();
|
||||
}
|
||||
|
||||
+ // Purpur start - One Punch Man!
|
||||
+ if (damageSource.getEntity() instanceof net.minecraft.world.entity.player.Player player && damageSource.getEntity().level().purpurConfig.creativeOnePunch && !damageSource.is(DamageTypeTags.IS_PROJECTILE)) {
|
||||
+ if (player.isCreative()) {
|
||||
+ org.apache.commons.lang3.mutable.MutableDouble attackDamage = new org.apache.commons.lang3.mutable.MutableDouble();
|
||||
+ player.getMainHandItem().forEachModifier(EquipmentSlot.MAINHAND, (attributeHolder, attributeModifier) -> {
|
||||
+ if (attributeModifier.operation() == AttributeModifier.Operation.ADD_VALUE) {
|
||||
+ attackDamage.addAndGet(attributeModifier.amount());
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ if (attackDamage.doubleValue() == 0.0D) {
|
||||
+ // One punch!
|
||||
+ amount = 9999F;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - One Punch Man!
|
||||
+
|
||||
this.noActionTime = 0;
|
||||
if (damage < 0.0F) {
|
||||
damage = 0.0F;
|
||||
@@ -1692,10 +_,10 @@
|
||||
protected @Nullable Player resolvePlayerResponsibleForDamage(final DamageSource source) {
|
||||
Entity sourceEntity = source.getEntity();
|
||||
if (sourceEntity instanceof Player playerSource) {
|
||||
- this.setLastHurtByPlayer(playerSource, 100);
|
||||
+ this.setLastHurtByPlayer(playerSource, this.level().purpurConfig.mobLastHurtByPlayerTime); // Purpur - Config for mob last hurt by player time
|
||||
} else if (sourceEntity instanceof Wolf wolf && wolf.isTame()) {
|
||||
if (wolf.getOwnerReference() != null) {
|
||||
- this.setLastHurtByPlayer(wolf.getOwnerReference().getUUID(), 100);
|
||||
+ this.setLastHurtByPlayer(wolf.getOwnerReference().getUUID(), this.level().purpurConfig.mobLastHurtByPlayerTime); // Purpur - Config for mob last hurt by player time
|
||||
} else {
|
||||
this.lastHurtByPlayer = null;
|
||||
this.lastHurtByPlayerMemoryTime = 0;
|
||||
@@ -1746,6 +_,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start - Totems work in inventory
|
||||
+ if (level().purpurConfig.totemOfUndyingWorksInInventory && this instanceof ServerPlayer player && (itemStack == null || itemStack.getItem() != Items.TOTEM_OF_UNDYING) && player.getBukkitEntity().hasPermission("purpur.inventory_totem")) {
|
||||
+ for (ItemStack item : player.getInventory().getNonEquipmentItems()) {
|
||||
+ if (item.getItem() == Items.TOTEM_OF_UNDYING) {
|
||||
+ itemInHand = item;
|
||||
+ itemStack = item.copy();
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Totems work in inventory
|
||||
+
|
||||
+ // Purpur start - Totems work in inventory
|
||||
+ if (level().purpurConfig.totemOfUndyingWorksInInventory && this instanceof ServerPlayer player && (itemStack == null || itemStack.getItem() != Items.TOTEM_OF_UNDYING) && player.getBukkitEntity().hasPermission("purpur.inventory_totem")) {
|
||||
+ for (ItemStack item : player.getInventory().getNonEquipmentItems()) {
|
||||
+ if (item.getItem() == Items.TOTEM_OF_UNDYING) {
|
||||
+ itemInHand = item;
|
||||
+ itemStack = item.copy();
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Totems work in inventory
|
||||
+
|
||||
final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null;
|
||||
final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot);
|
||||
event.setCancelled(protectionItem == null);
|
||||
@@ -1920,6 +_,7 @@
|
||||
boolean playerKilled = this.lastHurtByPlayerMemoryTime > 0;
|
||||
this.dropEquipment(level); // CraftBukkit - from below
|
||||
if (this.shouldDropLoot(level)) {
|
||||
+ if (!(source.is(net.minecraft.world.damagesource.DamageTypes.CRAMMING) && level().purpurConfig.disableDropsOnCrammingDeath)) { // Purpur - Disable loot drops on death by cramming
|
||||
this.dropFromLootTable(level, source, playerKilled);
|
||||
// Paper start
|
||||
final boolean prev = this.clearEquipmentSlots;
|
||||
@@ -1928,6 +_,7 @@
|
||||
// Paper end
|
||||
this.dropCustomDeathLoot(level, source, playerKilled);
|
||||
this.clearEquipmentSlots = prev; // Paper
|
||||
+ } // Purpur - Disable loot drops on death by cramming
|
||||
}
|
||||
|
||||
// CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment
|
||||
@@ -3269,6 +_,7 @@
|
||||
float dmg = (float)(diff * 10.0 - 3.0);
|
||||
if (dmg > 0.0F) {
|
||||
this.playSound(this.getFallDamageSound((int)dmg), 1.0F, 1.0F);
|
||||
+ if (level().purpurConfig.elytraKineticDamage) // Purpur - Toggle for kinetic damage
|
||||
this.hurt(this.damageSources().flyIntoWall(), dmg);
|
||||
}
|
||||
}
|
||||
@@ -3852,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
@@ -9,3 +184,16 @@
|
||||
if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) {
|
||||
for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
if (canGlideUsing(this.getItemBySlot(slot), slot)) {
|
||||
@@ -4740,6 +_,12 @@
|
||||
? slot == EquipmentSlot.MAINHAND && this.canUseSlot(EquipmentSlot.MAINHAND)
|
||||
: slot == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.typeHolder());
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Dispenser curse of binding protection
|
||||
+ public @Nullable EquipmentSlot getEquipmentSlotForDispenserItem(ItemStack itemstack) {
|
||||
+ return EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BINDING_CURSE, itemstack) > 0 ? null : this.getEquipmentSlotForItem(itemstack);
|
||||
+ }
|
||||
+ // Purpur end - Dispenser curse of binding protection
|
||||
|
||||
private static SlotAccess createEquipmentSlotAccess(final LivingEntity entity, final EquipmentSlot equipmentSlot) {
|
||||
return equipmentSlot != EquipmentSlot.HEAD && equipmentSlot != EquipmentSlot.MAINHAND && equipmentSlot != EquipmentSlot.OFFHAND
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -150,6 +_,7 @@
|
||||
private int homeRadius = -1;
|
||||
public boolean aware = true; // CraftBukkit
|
||||
public net.kyori.adventure.util.TriState despawnInPeacefulOverride = net.kyori.adventure.util.TriState.NOT_SET; // Paper - allow changing despawnInPeaceful
|
||||
+ public int ticksSinceLastInteraction; // Purpur - Entity lifespan
|
||||
|
||||
protected Mob(final EntityType<? extends Mob> type, final Level level) {
|
||||
super(type, level);
|
||||
@@ -285,6 +_,7 @@
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
+ if (target instanceof net.minecraft.server.level.ServerPlayer) this.ticksSinceLastInteraction = 0; // Purpur - Entity lifespan
|
||||
this.target = this.asValidTarget(target);
|
||||
return true;
|
||||
// CraftBukkit end
|
||||
@@ -328,7 +_,27 @@
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
- }
|
||||
+ incrementTicksSinceLastInteraction(); // Purpur - Entity lifespan
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - Entity lifespan
|
||||
+ private void incrementTicksSinceLastInteraction() {
|
||||
+ ++this.ticksSinceLastInteraction;
|
||||
+ if (getRider() != null) {
|
||||
+ this.ticksSinceLastInteraction = 0;
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.level().purpurConfig.entityLifeSpan <= 0) {
|
||||
+ return; // feature disabled
|
||||
+ }
|
||||
+ if (!this.removeWhenFarAway(0) || isPersistenceRequired() || requiresCustomPersistence() || hasCustomName()) {
|
||||
+ return; // mob persistent
|
||||
+ }
|
||||
+ if (this.ticksSinceLastInteraction > this.level().purpurConfig.entityLifeSpan) {
|
||||
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Entity lifespan
|
||||
|
||||
@Override
|
||||
protected void playHurtSound(final DamageSource source) {
|
||||
@@ -432,6 +_,7 @@
|
||||
output.putString("Paper.DespawnInPeacefulOverride", this.despawnInPeacefulOverride.name());
|
||||
}
|
||||
// Paper end - allow changing despawnInPeaceful
|
||||
+ output.putInt("Purpur.ticksSinceLastInteraction", this.ticksSinceLastInteraction); // Purpur - Entity lifespan
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -459,6 +_,7 @@
|
||||
this.lootTableSeed = input.getLongOr("DeathLootTableSeed", 0L);
|
||||
this.setNoAi(input.getBooleanOr("NoAI", false));
|
||||
this.aware = input.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
|
||||
+ this.ticksSinceLastInteraction = input.getIntOr("Purpur.ticksSinceLastInteraction", 0); // Purpur- Entity lifespan
|
||||
// Paper start - allow changing despawnInPeaceful
|
||||
this.despawnInPeacefulOverride = readDespawnInPeacefulOverride(input);
|
||||
}
|
||||
@@ -1237,7 +_,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
- this.setLeftHanded(random.nextFloat() < 0.05F);
|
||||
+ this.setLeftHanded(random.nextFloat() < level.getLevel().purpurConfig.entityLeftHandedChance); // Purpur - Changeable Mob Left Handed Chance
|
||||
return groupData;
|
||||
}
|
||||
|
||||
@@ -1598,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.postPiercingAttack();
|
||||
+ if (target instanceof net.minecraft.server.level.ServerPlayer) this.ticksSinceLastInteraction = 0; // Purpur - Entity lifespan
|
||||
return wasHurt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
--- a/net/minecraft/world/entity/npc/CatSpawner.java
|
||||
+++ b/net/minecraft/world/entity/npc/CatSpawner.java
|
||||
@@ -23,7 +_,7 @@
|
||||
public void tick(final ServerLevel level, final boolean spawnEnemies) {
|
||||
this.nextTick--;
|
||||
if (this.nextTick <= 0) {
|
||||
- this.nextTick = 1200;
|
||||
+ this.nextTick = level.purpurConfig.catSpawnDelay; // Purpur - Cat spawning options
|
||||
Player player = level.getRandomPlayer();
|
||||
if (player != null) {
|
||||
RandomSource random = level.getRandom();
|
||||
@@ -45,9 +_,12 @@
|
||||
}
|
||||
|
||||
private void spawnInVillage(final ServerLevel serverLevel, final BlockPos spawnPos) {
|
||||
- int radius = 48;
|
||||
- if (serverLevel.getPoiManager().getCountInRange(p -> p.is(PoiTypes.HOME), spawnPos, 48, PoiManager.Occupancy.IS_OCCUPIED) > 4L) {
|
||||
- List<Cat> cats = serverLevel.getEntitiesOfClass(Cat.class, new AABB(spawnPos).inflate(48.0, 8.0, 48.0));
|
||||
+ // Purpur start - Cat spawning options
|
||||
+ int radius = serverLevel.purpurConfig.catSpawnVillageScanRange;
|
||||
+ if (radius <= 0) return;
|
||||
+ if (serverLevel.getPoiManager().getCountInRange(holder -> holder.is(PoiTypes.HOME), spawnPos, radius, PoiManager.Occupancy.IS_OCCUPIED) > 4L) {
|
||||
+ List<Cat> cats = serverLevel.getEntitiesOfClass(Cat.class, new AABB(spawnPos).inflate(radius, 8.0, radius));
|
||||
+ // Purpur end - Cat spawning options
|
||||
if (cats.size() < 5) {
|
||||
this.spawnCat(spawnPos, serverLevel, false);
|
||||
}
|
||||
@@ -55,8 +_,11 @@
|
||||
}
|
||||
|
||||
private void spawnInHut(final ServerLevel level, final BlockPos spawnPos) {
|
||||
- int radius = 16;
|
||||
- List<Cat> cats = level.getEntitiesOfClass(Cat.class, new AABB(spawnPos).inflate(16.0, 8.0, 16.0));
|
||||
+ // Purpur start - Cat spawning options
|
||||
+ int radius = level.purpurConfig.catSpawnSwampHutScanRange;
|
||||
+ if (radius <= 0) return;
|
||||
+ List<Cat> cats = level.getEntitiesOfClass(Cat.class, new AABB(spawnPos).inflate(radius, 8.0, radius));
|
||||
+ // Purpur end - Cat spawning options
|
||||
if (cats.isEmpty()) {
|
||||
this.spawnCat(spawnPos, level, true);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
||||
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
||||
@@ -61,6 +_,13 @@
|
||||
super(type, level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Allow leashing villagers
|
||||
+ @Override
|
||||
+ public boolean canBeLeashed() {
|
||||
+ return level().purpurConfig.wanderingTraderCanBeLeashed;
|
||||
+ }
|
||||
+ // Purpur end - Allow leashing villagers
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
@@ -78,7 +_,7 @@
|
||||
.addGoal(
|
||||
0,
|
||||
new UseItemGoal<>(
|
||||
- this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, e -> this.canDrinkMilk && this.level().isBrightOutside() && e.isInvisible() // Paper - Add more WanderingTrader API
|
||||
+ this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, e -> level().purpurConfig.milkClearsBeneficialEffects && this.canDrinkMilk && this.level().isBrightOutside() && e.isInvisible() // Paper - Add more WanderingTrader API // Purpur - Milk Keeps Beneficial Effects
|
||||
)
|
||||
);
|
||||
this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this));
|
||||
@@ -121,8 +_,10 @@
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
|
||||
+ if (this.level().purpurConfig.wanderingTraderAllowTrading) { // Purpur - Add config for villager trading
|
||||
this.setTradingPlayer(player);
|
||||
this.openTradingScreen(player, this.getDisplayName(), 1);
|
||||
+ } // Purpur - Add config for villager trading
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -1,5 +1,75 @@
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -174,11 +_,20 @@
|
||||
public float hurtDir;
|
||||
public boolean affectsSpawning = true; // Paper - Affects Spawning API
|
||||
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
|
||||
+ public int burpDelay = 0; // Purpur - Burp delay
|
||||
+ public boolean canPortalInstant = false; // Purpur - Add portal permission bypass
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
public int oldLevel = -1;
|
||||
|
||||
+ // Purpur start - AFK API
|
||||
+ public abstract void setAfk(boolean afk);
|
||||
+
|
||||
+ public boolean isAfk() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Purpur end - AFK API
|
||||
@Override
|
||||
public org.bukkit.craftbukkit.entity.CraftHumanEntity getBukkitEntity() {
|
||||
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
|
||||
@@ -240,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Purpur start - Burp delay
|
||||
+ if (this.burpDelay > 0 && --this.burpDelay == 0) {
|
||||
+ this.level().playSound(null, getX(), getY(), getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 1.0F, this.level().random.nextFloat() * 0.1F + 0.9F);
|
||||
+ }
|
||||
+ // Purpur end - Burp delay
|
||||
+
|
||||
this.noPhysics = this.isSpectator();
|
||||
if (this.isSpectator() || this.isPassenger()) {
|
||||
this.setOnGround(false);
|
||||
@@ -297,6 +_,17 @@
|
||||
this.turtleHelmetTick();
|
||||
}
|
||||
|
||||
+ // Purpur start - Full netherite armor grants fire resistance
|
||||
+ if (this.level().purpurConfig.playerNetheriteFireResistanceDuration > 0 && this.level().getGameTime() % 20 == 0) {
|
||||
+ if (this.getItemBySlot(EquipmentSlot.HEAD).is(Items.NETHERITE_HELMET)
|
||||
+ && this.getItemBySlot(EquipmentSlot.CHEST).is(Items.NETHERITE_CHESTPLATE)
|
||||
+ && this.getItemBySlot(EquipmentSlot.LEGS).is(Items.NETHERITE_LEGGINGS)
|
||||
+ && this.getItemBySlot(EquipmentSlot.FEET).is(Items.NETHERITE_BOOTS)) {
|
||||
+ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, this.level().purpurConfig.playerNetheriteFireResistanceDuration, this.level().purpurConfig.playerNetheriteFireResistanceAmplifier, this.level().purpurConfig.playerNetheriteFireResistanceAmbient, this.level().purpurConfig.playerNetheriteFireResistanceShowParticles, this.level().purpurConfig.playerNetheriteFireResistanceShowIcon), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.NETHERITE_ARMOR);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Full netherite armor grants fire resistance
|
||||
+
|
||||
this.cooldowns.tick();
|
||||
this.updatePlayerPose();
|
||||
}
|
||||
@@ -502,7 +_,7 @@
|
||||
List<Entity> orbs = Lists.newArrayList();
|
||||
|
||||
for (Entity entity : entities) {
|
||||
- if (entity.is(EntityType.EXPERIENCE_ORB)) {
|
||||
+ if (entity.is(EntityType.EXPERIENCE_ORB) && entity.level().purpurConfig.playerExpPickupDelay >= 0) { // Purpur - Configurable player pickup exp delay
|
||||
orbs.add(entity);
|
||||
} else if (!entity.isRemoved()) {
|
||||
this.touch(entity);
|
||||
@@ -1045,7 +_,7 @@
|
||||
criticalAttack = criticalAttack && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
|
||||
if (criticalAttack) {
|
||||
damageSource = damageSource.critical(); // Paper - critical damage API
|
||||
- baseDamage *= 1.5F;
|
||||
+ baseDamage *= (float) this.level().purpurConfig.playerCriticalDamageMultiplier; // Purpur - Add config change multiplier critical damage value
|
||||
}
|
||||
|
||||
float totalDamage = baseDamage + magicBoost;
|
||||
@@ -1519,7 +_,7 @@
|
||||
}
|
||||
|
||||
@@ -9,3 +79,42 @@
|
||||
return !this.abilities.flying && super.canGlide();
|
||||
}
|
||||
|
||||
@@ -1747,7 +_,23 @@
|
||||
|
||||
@Override
|
||||
protected int getBaseExperienceReward(final ServerLevel level) {
|
||||
- return !level.getGameRules().get(GameRules.KEEP_INVENTORY) && !this.isSpectator() ? Math.min(this.experienceLevel * 7, 100) : 0;
|
||||
+ // Purpur start - Add player death exp control options
|
||||
+ if (!level.getGameRules().get(GameRules.KEEP_INVENTORY) && !this.isSpectator()) {
|
||||
+ int toDrop;
|
||||
+ try {
|
||||
+ toDrop = Math.round(((Number) scriptEngine.eval("let expLevel = " + experienceLevel + "; " +
|
||||
+ "let expTotal = " + totalExperience + "; " +
|
||||
+ "let exp = " + experienceProgress + "; " +
|
||||
+ level().purpurConfig.playerDeathExpDropEquation)).floatValue());
|
||||
+ } catch (javax.script.ScriptException e) {
|
||||
+ e.printStackTrace();
|
||||
+ toDrop = experienceLevel * 7;
|
||||
+ }
|
||||
+ return Math.min(toDrop, level().purpurConfig.playerDeathExpDropMax);
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ // Purpur end - Add player death exp control options
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1790,6 +_,13 @@
|
||||
public boolean addItem(final ItemStack itemStack) {
|
||||
return this.inventory.add(itemStack);
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Player ridable in water option
|
||||
+ @Override
|
||||
+ public boolean dismountsUnderwater() {
|
||||
+ return !level().purpurConfig.playerRidableInWater;
|
||||
+ }
|
||||
+ // Purpur end - Player ridable in water option
|
||||
|
||||
public abstract @Nullable GameType gameMode();
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/projectile/arrow/ThrownTrident.java
|
||||
+++ b/net/minecraft/world/entity/projectile/arrow/ThrownTrident.java
|
||||
@@ -72,7 +_,7 @@
|
||||
|
||||
Entity currentOwner = this.getOwner();
|
||||
int loyalty = this.entityData.get(ID_LOYALTY);
|
||||
- if (loyalty > 0 && (this.dealtDamage || this.isNoPhysics()) && currentOwner != null) {
|
||||
+ if (loyalty > 0 && (this.dealtDamage || this.isNoPhysics() || (level().purpurConfig.tridentLoyaltyVoidReturnHeight < 0.0D && getY() < level().purpurConfig.tridentLoyaltyVoidReturnHeight)) && currentOwner != null) { // Purpur - Add option to allow loyalty on tridents to work in the void
|
||||
if (!this.isAcceptibleReturnOwner()) {
|
||||
if (this.level() instanceof ServerLevel level && this.pickup == AbstractArrow.Pickup.ALLOWED) {
|
||||
this.spawnAtLocation(level, this.getPickupItem(), 0.1F);
|
||||
@@ -0,0 +1,43 @@
|
||||
--- a/net/minecraft/world/entity/projectile/throwableitemprojectile/Snowball.java
|
||||
+++ b/net/minecraft/world/entity/projectile/throwableitemprojectile/Snowball.java
|
||||
@@ -56,9 +_,39 @@
|
||||
protected void onHitEntity(final EntityHitResult hitResult) {
|
||||
super.onHitEntity(hitResult);
|
||||
Entity entity = hitResult.getEntity();
|
||||
- int damage = entity instanceof Blaze ? 3 : 0;
|
||||
+ int damage = entity.level().purpurConfig.snowballDamage >= 0 ? entity.level().purpurConfig.snowballDamage : entity instanceof Blaze ? 3 : 0; // Purpur - Add configurable snowball damage
|
||||
entity.hurt(this.damageSources().thrown(this, this.getOwner()), damage);
|
||||
}
|
||||
+
|
||||
+ // Purpur start - options to extinguish fire blocks with snowballs - borrowed and modified code from ThrownPotion#onHitBlock and ThrownPotion#dowseFire
|
||||
+ @Override
|
||||
+ protected void onHitBlock(net.minecraft.world.phys.BlockHitResult blockHitResult) {
|
||||
+ super.onHitBlock(blockHitResult);
|
||||
+
|
||||
+ if (!this.level().isClientSide()) {
|
||||
+ net.minecraft.core.BlockPos pos = blockHitResult.getBlockPos();
|
||||
+ net.minecraft.core.BlockPos relativePos = pos.relative(blockHitResult.getDirection());
|
||||
+
|
||||
+ net.minecraft.world.level.block.state.BlockState blockState = this.level().getBlockState(pos);
|
||||
+
|
||||
+ if (this.level().purpurConfig.snowballExtinguishesFire && this.level().getBlockState(relativePos).is(net.minecraft.world.level.block.Blocks.FIRE)) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, relativePos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) {
|
||||
+ this.level().removeBlock(relativePos, false);
|
||||
+ }
|
||||
+ } else if (this.level().purpurConfig.snowballExtinguishesCandles && net.minecraft.world.level.block.AbstractCandleBlock.isLit(blockState)) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(net.minecraft.world.level.block.AbstractCandleBlock.LIT, false))) {
|
||||
+ net.minecraft.world.level.block.AbstractCandleBlock.extinguish(null, blockState, this.level(), pos);
|
||||
+ }
|
||||
+ } else if (this.level().purpurConfig.snowballExtinguishesCampfires && net.minecraft.world.level.block.CampfireBlock.isLitCampfire(blockState)) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(net.minecraft.world.level.block.CampfireBlock.LIT, false))) {
|
||||
+ this.level().levelEvent(null, 1009, pos, 0);
|
||||
+ net.minecraft.world.level.block.CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState);
|
||||
+ this.level().setBlockAndUpdate(pos, blockState.setValue(net.minecraft.world.level.block.CampfireBlock.LIT, false));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - options to extinguish fire blocks with snowballs
|
||||
|
||||
@Override
|
||||
protected void onHit(final HitResult hitResult) {
|
||||
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java
|
||||
+++ b/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java
|
||||
@@ -113,9 +_,10 @@
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- if (this.random.nextFloat() < 0.05F && level.isSpawningMonsters()) {
|
||||
+ if (this.random.nextFloat() < level.purpurConfig.enderPearlEndermiteChance && level.isSpawningMonsters()) { // Purpur - Configurable Ender Pearl RNG
|
||||
Endermite endermite = EntityType.ENDERMITE.create(level, EntitySpawnReason.TRIGGERED);
|
||||
if (endermite != null) {
|
||||
+ endermite.setPlayerSpawned(true); // Purpur - Add back player spawned endermite API
|
||||
endermite.snapTo(preTeleportX, preTeleportY, preTeleportZ, preTeleportYRot, preTeleportXRot); // Paper - spawn endermite at pre teleport position as teleport has been moved up
|
||||
level.addFreshEntity(endermite, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.ENDER_PEARL); // Paper - add reason
|
||||
}
|
||||
@@ -135,7 +_,7 @@
|
||||
if (newOwner != null) {
|
||||
newOwner.resetFallDistance();
|
||||
newOwner.resetCurrentImpulseContext();
|
||||
- newOwner.hurtServer(player.level(), this.damageSources().enderPearl().eventEntityDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
+ newOwner.hurtServer(player.level(), this.damageSources().enderPearl().eventEntityDamager(this), this.level().purpurConfig.enderPearlDamage); // CraftBukkit // Paper - fix DamageSource API // Purpur - Configurable Ender Pearl damage
|
||||
}
|
||||
|
||||
this.playSound(level, teleportPos);
|
||||
@@ -0,0 +1,42 @@
|
||||
--- a/net/minecraft/world/entity/raid/Raids.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raids.java
|
||||
@@ -29,6 +_,7 @@
|
||||
|
||||
public class Raids extends SavedData {
|
||||
private static final Identifier RAID_FILE_ID = Identifier.withDefaultNamespace("raids");
|
||||
+ public final java.util.Map<java.util.UUID, Integer> playerCooldowns = com.google.common.collect.Maps.newHashMap(); // Purpur - Raid cooldown setting
|
||||
public static final Codec<Raids> CODEC = RecordCodecBuilder.create(
|
||||
i -> i.group(
|
||||
Raids.RaidWithId.CODEC
|
||||
@@ -75,6 +_,17 @@
|
||||
|
||||
public void tick(final ServerLevel level) {
|
||||
this.tick++;
|
||||
+ // Purpur start - Raid cooldown setting
|
||||
+ if (level.purpurConfig.raidCooldownSeconds != 0 && this.tick % 20 == 0) {
|
||||
+ com.google.common.collect.ImmutableMap.copyOf(playerCooldowns).forEach((uuid, i) -> {
|
||||
+ if (i < 1) {
|
||||
+ playerCooldowns.remove(uuid);
|
||||
+ } else {
|
||||
+ playerCooldowns.put(uuid, i - 1);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ // Purpur end - Raid cooldown setting
|
||||
Iterator<Raid> raidIterator = this.raidMap.values().iterator();
|
||||
|
||||
while (raidIterator.hasNext()) {
|
||||
@@ -137,11 +_,11 @@
|
||||
// }
|
||||
|
||||
if (!raid.isStarted() || (raid.isInProgress() && raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel())) { // CraftBukkit - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished
|
||||
- // CraftBukkit start
|
||||
+ if (level.purpurConfig.raidCooldownSeconds != 0 && playerCooldowns.containsKey(player.getUUID())) return null; // Purpur - Raid cooldown setting// CraftBukkit start
|
||||
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(level, raid, player)) {
|
||||
player.removeEffect(net.minecraft.world.effect.MobEffects.RAID_OMEN);
|
||||
return null;
|
||||
- }
|
||||
+ }if (level.purpurConfig.raidCooldownSeconds != 0) playerCooldowns.put(player.getUUID(), serverLevel.purpurConfig.raidCooldownSeconds); // Purpur - Raid cooldown setting
|
||||
|
||||
if (!raid.isStarted() && !this.raidMap.containsValue(raid)) {
|
||||
this.raidMap.put(this.getUniqueId(), raid);
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
@@ -431,6 +_,7 @@
|
||||
float friction = this.getGroundFriction();
|
||||
if (friction > 0.0F) {
|
||||
this.landFriction = friction;
|
||||
+ if (level().purpurConfig.boatEjectPlayersOnLand) ejectPassengers(); // Purpur - Add option for boats to eject players on land
|
||||
return AbstractBoat.Status.ON_LAND;
|
||||
} else {
|
||||
return AbstractBoat.Status.IN_AIR;
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/vehicle/minecart/NewMinecartBehavior.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/minecart/NewMinecartBehavior.java
|
||||
@@ -394,7 +_,7 @@
|
||||
private Vec3 calculateBoostTrackSpeed(final Vec3 deltaMovement, final BlockPos pos, final BlockState state) {
|
||||
if (state.is(Blocks.POWERED_RAIL) && state.getValue(PoweredRailBlock.POWERED)) {
|
||||
if (deltaMovement.length() > 0.01) {
|
||||
- return deltaMovement.normalize().scale(deltaMovement.length() + 0.06);
|
||||
+ return deltaMovement.normalize().scale(deltaMovement.length() + this.level().purpurConfig.poweredRailBoostModifier); // Purpur - Configurable powered rail boost modifier
|
||||
} else {
|
||||
Vec3 powerDirection = this.minecart.getRedstoneDirection(pos);
|
||||
return powerDirection.lengthSqr() <= 0.0 ? deltaMovement : powerDirection.scale(deltaMovement.length() + 0.2);
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/world/entity/vehicle/minecart/OldMinecartBehavior.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/minecart/OldMinecartBehavior.java
|
||||
@@ -242,8 +_,8 @@
|
||||
Vec3 vec3 = this.getDeltaMovement();
|
||||
double speedLength = vec3.horizontalDistance();
|
||||
if (speedLength > 0.01) {
|
||||
- double speed = 0.06;
|
||||
- this.setDeltaMovement(vec3.add(vec3.x / speedLength * 0.06, 0.0, vec3.z / speedLength * 0.06));
|
||||
+ double speed = level.purpurConfig.poweredRailBoostModifier; // Purpur - Configurable powered rail boost modifier
|
||||
+ this.setDeltaMovement(vec3.add(vec3.x / speedLength * level.purpurConfig.poweredRailBoostModifier, 0.0, vec3.z / speedLength * level.purpurConfig.poweredRailBoostModifier)); // Purpur - Configurable powered rail boost modifier
|
||||
} else {
|
||||
Vec3 deltaMovement = this.getDeltaMovement();
|
||||
double dx = deltaMovement.x;
|
||||
Reference in New Issue
Block a user