mirror of
https://github.com/PaperMC/Paper.git
synced 2026-11-04 17:00:09 -05:00
Compare commits
57
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
592f013c5c | ||
|
|
b4682bfef6 | ||
|
|
b685281d74 | ||
|
|
b8b4a1c7cd | ||
|
|
11dbf11014 | ||
|
|
39bd1bac06 | ||
|
|
afea65c2d2 | ||
|
|
1835b0468f | ||
|
|
b80b604636 | ||
|
|
6048c2d97c | ||
|
|
2e7bb166b1 | ||
|
|
39a1aa5c7f | ||
|
|
174eab0192 | ||
|
|
5d62ec0ed9 | ||
|
|
17524d0ee0 | ||
|
|
7799bf28ae | ||
|
|
55be6c0ef5 | ||
|
|
5dc4afc1dd | ||
|
|
f4e769a74d | ||
|
|
651d8481b7 | ||
|
|
acfe105b9d | ||
|
|
a64ea13e8e | ||
|
|
1f8197327f | ||
|
|
8021488ef4 | ||
|
|
182b2f8a2a | ||
|
|
a8c05a35c2 | ||
|
|
945aea9961 | ||
|
|
4aef3f0a67 | ||
|
|
60073714ba | ||
|
|
4f184db3c9 | ||
|
|
57d84f68a3 | ||
|
|
49daadd25d | ||
|
|
b2b1e177cb | ||
|
|
90aee8e007 | ||
|
|
d74f6bc77a | ||
|
|
dd203a2716 | ||
|
|
dcf5577aae | ||
|
|
c39822ae08 | ||
|
|
4af86ff3e0 | ||
|
|
1a8417b12b | ||
|
|
65461225ef | ||
|
|
7b31cc2b6b | ||
|
|
aa6f09b098 | ||
|
|
944ce44a4a | ||
|
|
6fe7eb5aae | ||
|
|
948acae8c2 | ||
|
|
ef4e85d6db | ||
|
|
3611a815e6 | ||
|
|
1d14197790 | ||
|
|
6bac3c95bf | ||
|
|
9b1dd57135 | ||
|
|
4be1a310c2 | ||
|
|
66d3bbed38 | ||
|
|
d0be5e20fd | ||
|
|
dd0810c4af | ||
|
|
04ee8eac9b | ||
|
|
c58cba39fb |
No files matched your search
+12
-3
@@ -420,13 +420,19 @@ int maxPlayers = GlobalConfiguration.get().misc.maxNumOfPlayers;
|
||||
Generally for global config values you will use the fully qualified class name,
|
||||
`io.papermc.paper.configuration.GlobalConfiguration` since it's not imported in
|
||||
most places.
|
||||
---
|
||||
|
||||
If you are adding a new world config value, you must have access to an instance
|
||||
of the `net.minecraft.world.level.Level` which you can then access the config by doing
|
||||
```java
|
||||
int maxPlayers = level.paperConfig().misc.maxNumOfPlayers;
|
||||
```
|
||||
|
||||
#### Documentation
|
||||
When adding or removing a config option, you should open a pull request in our [documentation repository](https://github.com/PaperMC/docs)
|
||||
to keep it in sync and accurate. If you're unsure whether your original change will be accepted, then it's fine to wait with making the documentation
|
||||
pull request until a maintainer has reviewed your changes. Once everything is done, the documentation pull request will be merged at the same time
|
||||
that your original pull request is.
|
||||
|
||||
## Testing API changes
|
||||
|
||||
### Using the Paper Test Plugin
|
||||
@@ -470,10 +476,13 @@ If you use Maven to build your plugin:
|
||||
|
||||
### My commit doesn't need a build, what do I do?
|
||||
|
||||
Quite simple: You add `[ci skip]` to the start of your commit subject.
|
||||
Quite simple: You add `[ci skip]` to the start of your pull request title.
|
||||
|
||||
This case most often applies to changes to files like `README.md`, this very
|
||||
file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth.
|
||||
file (`CONTRIBUTING.md`), the `LICENSE.md` file, and also small updates to Javadocs or other documentation.
|
||||
|
||||
Do *not* add [ci skip] to the start of your individual commit subjects, as your
|
||||
pull request will not be mergeable until a new commit is added due to status check requirements.
|
||||
|
||||
### Patching and building is *really* slow, what can I do?
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ mcVersion=26.1.2
|
||||
# This is the current API version for use in (paper-)plugin.yml files
|
||||
# During snapshot cycles this should be the anticipated version of the release target
|
||||
apiVersion=26.1.2
|
||||
channel=ALPHA
|
||||
channel=STABLE
|
||||
|
||||
# Set to true while updating Minecraft version
|
||||
updatingMinecraft=false
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package io.papermc.paper.registry.keys;
|
||||
|
||||
import static net.kyori.adventure.key.Key.key;
|
||||
|
||||
import io.papermc.paper.annotation.GeneratedClass;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Vanilla keys for {@link RegistryKey#POINT_OF_INTEREST_TYPE}.
|
||||
*
|
||||
* @apiNote The fields provided here are a direct representation of
|
||||
* what is available from the vanilla game source. They may be
|
||||
* changed (including removals) on any Minecraft version
|
||||
* bump, so cross-version compatibility is not provided on the
|
||||
* same level as it is on most of the other API.
|
||||
*/
|
||||
@SuppressWarnings({
|
||||
"unused",
|
||||
"SpellCheckingInspection"
|
||||
})
|
||||
@NullMarked
|
||||
@GeneratedClass
|
||||
public final class PoiTypeKeys {
|
||||
/**
|
||||
* {@code minecraft:armorer}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> ARMORER = create(key("armorer"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:bee_nest}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> BEE_NEST = create(key("bee_nest"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:beehive}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> BEEHIVE = create(key("beehive"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:butcher}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> BUTCHER = create(key("butcher"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:cartographer}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> CARTOGRAPHER = create(key("cartographer"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:cleric}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> CLERIC = create(key("cleric"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:farmer}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> FARMER = create(key("farmer"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:fisherman}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> FISHERMAN = create(key("fisherman"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:fletcher}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> FLETCHER = create(key("fletcher"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:home}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> HOME = create(key("home"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:leatherworker}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> LEATHERWORKER = create(key("leatherworker"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:librarian}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> LIBRARIAN = create(key("librarian"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:lightning_rod}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> LIGHTNING_ROD = create(key("lightning_rod"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:lodestone}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> LODESTONE = create(key("lodestone"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:mason}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> MASON = create(key("mason"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:meeting}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> MEETING = create(key("meeting"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:nether_portal}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> NETHER_PORTAL = create(key("nether_portal"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:shepherd}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> SHEPHERD = create(key("shepherd"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:test_instance}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> TEST_INSTANCE = create(key("test_instance"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:toolsmith}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> TOOLSMITH = create(key("toolsmith"));
|
||||
|
||||
/**
|
||||
* {@code minecraft:weaponsmith}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TypedKey<PoiType> WEAPONSMITH = create(key("weaponsmith"));
|
||||
|
||||
private PoiTypeKeys() {
|
||||
}
|
||||
|
||||
private static TypedKey<PoiType> create(final Key key) {
|
||||
return TypedKey.create(RegistryKey.POINT_OF_INTEREST_TYPE, key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.papermc.paper.registry.keys.tags;
|
||||
|
||||
import static net.kyori.adventure.key.Key.key;
|
||||
|
||||
import io.papermc.paper.annotation.GeneratedClass;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Vanilla tag keys for {@link RegistryKey#POINT_OF_INTEREST_TYPE}.
|
||||
*
|
||||
* @apiNote The fields provided here are a direct representation of
|
||||
* what is available from the vanilla game source. They may be
|
||||
* changed (including removals) on any Minecraft version
|
||||
* bump, so cross-version compatibility is not provided on the
|
||||
* same level as it is on most of the other API.
|
||||
*/
|
||||
@SuppressWarnings({
|
||||
"unused",
|
||||
"SpellCheckingInspection"
|
||||
})
|
||||
@NullMarked
|
||||
@GeneratedClass
|
||||
public final class PoiTypeTagKeys {
|
||||
/**
|
||||
* {@code #minecraft:acquirable_job_site}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TagKey<PoiType> ACQUIRABLE_JOB_SITE = create(key("acquirable_job_site"));
|
||||
|
||||
/**
|
||||
* {@code #minecraft:bee_home}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TagKey<PoiType> BEE_HOME = create(key("bee_home"));
|
||||
|
||||
/**
|
||||
* {@code #minecraft:village}
|
||||
*
|
||||
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
|
||||
*/
|
||||
public static final TagKey<PoiType> VILLAGE = create(key("village"));
|
||||
|
||||
private PoiTypeTagKeys() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tag key for {@link PoiType} in the registry {@code minecraft:point_of_interest_type}.
|
||||
*
|
||||
* @param key the tag key's key
|
||||
* @return a new tag key
|
||||
*/
|
||||
public static TagKey<PoiType> create(final Key key) {
|
||||
return TagKey.create(RegistryKey.POINT_OF_INTEREST_TYPE, key);
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public class TimingHistory {
|
||||
}
|
||||
}
|
||||
return pair(
|
||||
worldMap.get(world.getKey().toString()),
|
||||
worldMap.get(world.key().asString()),
|
||||
toArrayMapper(regions.values(),new Function<RegionData, Object>() {
|
||||
@NotNull
|
||||
@Override
|
||||
|
||||
@@ -125,10 +125,11 @@ public class MaterialTags {
|
||||
|
||||
/**
|
||||
* Covers all dyes.
|
||||
*
|
||||
* @deprecated in favour of {@link Tag#ITEMS_DYES}
|
||||
*/
|
||||
public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes"))
|
||||
.endsWith("_DYE")
|
||||
.ensureSize("DYES", 16).lock();
|
||||
@Deprecated(since = "26.1")
|
||||
public static final MaterialSetTag DYES = replacedBy(Tag.ITEMS_DYES);
|
||||
|
||||
/**
|
||||
* Covers all variants of gates.
|
||||
|
||||
@@ -75,7 +75,7 @@ public final class NamespacedTag implements com.destroystokyo.paper.Namespaced {
|
||||
Preconditions.checkArgument(key != null, "Key cannot be null");
|
||||
|
||||
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
|
||||
this.key = key.toLowerCase().toLowerCase(Locale.ROOT);
|
||||
this.key = key.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Check validity after normalization
|
||||
Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
|
||||
|
||||
+8
-1
@@ -9,9 +9,16 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when processing a player's attack on an entity when the player's attack strength cooldown is reset
|
||||
* Called when processing a player's attack on an entity when the player's attack strength cooldown is reset.
|
||||
*
|
||||
* @deprecated In modern Minecraft, this does not properly represent spear attacks and additionally does not
|
||||
* cover the wide range of ways that the cooldown may be reset.
|
||||
* <p>
|
||||
* Additionally, the cancellation of event is misleading as the client will reset the cooldown manually.
|
||||
* So there is no way for the server to control this.
|
||||
*/
|
||||
@NullMarked
|
||||
@Deprecated(since = "26.1", forRemoval = true)
|
||||
public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
@@ -257,16 +257,16 @@ public interface PlayerProfile extends org.bukkit.profile.PlayerProfile, PlayerH
|
||||
|
||||
@Override
|
||||
default void applySkinToPlayerHeadContents(final PlayerHeadObjectContents.Builder builder) {
|
||||
if (this.getProperties().isEmpty() && (this.getName() != null) != (this.getId() != null)) {
|
||||
if (this.getProperties().isEmpty()) {
|
||||
if (this.getId() != null) {
|
||||
builder.id(this.getId());
|
||||
} else {
|
||||
} else if (this.getName() != null) {
|
||||
builder.name(this.getName());
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
builder.id(this.getId())
|
||||
.name(this.getName())
|
||||
.profileProperties(this.getProperties().stream().map(prop -> property(prop.getName(), prop.getValue(), prop.getSignature())).toList());
|
||||
}
|
||||
builder.id(this.getId())
|
||||
.name(this.getName())
|
||||
.profileProperties(this.getProperties().stream().map(prop -> property(prop.getName(), prop.getValue(), prop.getSignature())).toList());
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package io.papermc.paper;
|
||||
import com.destroystokyo.paper.SkinParts;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.datacomponent.item.ResolvableProfile;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.world.damagesource.CombatEntry;
|
||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||
import java.util.Set;
|
||||
@@ -52,6 +53,14 @@ public interface InternalAPIBridge {
|
||||
*/
|
||||
DamageEffect getDamageEffect(String key);
|
||||
|
||||
/**
|
||||
* Creates an occupancy instance for the passed enum entry name.
|
||||
*
|
||||
* @param enumNameEntry the enum entry
|
||||
* @return the occupancy
|
||||
*/
|
||||
PoiType.Occupancy createOccupancy(String enumNameEntry);
|
||||
|
||||
/**
|
||||
* Constructs the legacy custom biome instance for the biome enum.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.index.qual.Positive;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -23,7 +24,7 @@ public interface UseCooldown {
|
||||
* @return builder
|
||||
*/
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
static UseCooldown.Builder useCooldown(final float seconds) {
|
||||
static UseCooldown.Builder useCooldown(final @Positive float seconds) {
|
||||
return ItemComponentTypesBridge.bridge().useCooldown(seconds);
|
||||
}
|
||||
|
||||
@@ -33,7 +34,7 @@ public interface UseCooldown {
|
||||
* @return cooldown seconds
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
float seconds();
|
||||
@Positive float seconds();
|
||||
|
||||
/**
|
||||
* The unique resource location to identify this cooldown group.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -23,7 +24,7 @@ public interface Weapon {
|
||||
*
|
||||
* @return durability
|
||||
*/
|
||||
int itemDamagePerAttack();
|
||||
@NonNegative int itemDamagePerAttack();
|
||||
|
||||
/**
|
||||
* The number of seconds that blocking is disabled.
|
||||
@@ -46,7 +47,7 @@ public interface Weapon {
|
||||
* @return the builder for chaining
|
||||
* @see #itemDamagePerAttack()
|
||||
*/
|
||||
Builder itemDamagePerAttack(int damage);
|
||||
Builder itemDamagePerAttack(@NonNegative int damage);
|
||||
|
||||
/**
|
||||
* Sets the disable blocking duration (in seconds).
|
||||
|
||||
+2
-3
@@ -27,8 +27,7 @@ public interface ItemDamageFunction {
|
||||
*
|
||||
* @return the threshold
|
||||
*/
|
||||
@NonNegative
|
||||
float threshold();
|
||||
@NonNegative float threshold();
|
||||
|
||||
/**
|
||||
* Get the constant amount of damage applied to the item, if threshold is passed.
|
||||
@@ -60,7 +59,7 @@ public interface ItemDamageFunction {
|
||||
interface Builder extends DataComponentBuilder<ItemDamageFunction> {
|
||||
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
ItemDamageFunction.Builder threshold(@NonNegative final float threshold);
|
||||
ItemDamageFunction.Builder threshold(final @NonNegative float threshold);
|
||||
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
ItemDamageFunction.Builder base(final float base);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.papermc.paper.entity.poi;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Holds the result of searching for a point of interest.
|
||||
*
|
||||
* @see World#locateAllPoiInRange(Location, Predicate, int)
|
||||
* @see World#locateAllPoiInRange(Location, Predicate, int, PoiType.Occupancy)
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PoiSearchResult {
|
||||
|
||||
/**
|
||||
* Returns the {@link PoiType}.
|
||||
*
|
||||
* @return the {@link PoiType}
|
||||
*/
|
||||
PoiType poiType();
|
||||
|
||||
/**
|
||||
* Return the location of the {@link PoiType}.
|
||||
*
|
||||
* @return the location the {@link PoiType} was found at
|
||||
*/
|
||||
Location location();
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package io.papermc.paper.entity.poi;
|
||||
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Represents a point of interest (POI).
|
||||
* <p>
|
||||
* Many PoiTypes act as a marker vs storing occupants examples of this are most
|
||||
* explicitly {@link PoiTypes#NETHER_PORTAL}. This state can be checked using the method
|
||||
* {@link #hasOccupants()} which will return {@code true} if the PoiType can have occupants.
|
||||
*
|
||||
* @see PoiTypes
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PoiType extends Keyed {
|
||||
|
||||
/**
|
||||
* Determines whether the provided BlockState is relevant to this
|
||||
* point of interest.
|
||||
*
|
||||
* @param data the BlockData to check
|
||||
* @return {@code true} if the BlockState is relevant, otherwise {@code false}
|
||||
*/
|
||||
boolean is(BlockData data);
|
||||
|
||||
/**
|
||||
* Determines whether this PoiType can actually hold occupants.
|
||||
*
|
||||
* @return {@code true} if this PoiType can hold occupants
|
||||
*/
|
||||
boolean hasOccupants();
|
||||
|
||||
/**
|
||||
* Determines the type of occupancy the point of interest has.
|
||||
* <p>
|
||||
* A PoiType occupancy is defined by how much "space" a point of interest
|
||||
* has.
|
||||
* <p>
|
||||
* With context to a Villager workstation if a villager is currently using
|
||||
* a workstation as a source of its profession the occupancy would be
|
||||
* {@link Occupancy#IS_OCCUPIED}, however, if no villager was attached to
|
||||
* a workstation its occupancy would be {@link Occupancy#HAS_SPACE}.
|
||||
*/
|
||||
interface Occupancy {
|
||||
|
||||
/**
|
||||
* The poi has space.
|
||||
*/
|
||||
Occupancy HAS_SPACE = occupancy("HAS_SPACE");
|
||||
/**
|
||||
* The poi is occupied.
|
||||
*/
|
||||
Occupancy IS_OCCUPIED = occupancy("IS_OCCUPIED");
|
||||
/**
|
||||
* The poi is either occupied or has space.
|
||||
*/
|
||||
Occupancy ANY = occupancy("ANY");
|
||||
|
||||
private static Occupancy occupancy(final String enumEntryName) {
|
||||
return InternalAPIBridge.get().createOccupancy(enumEntryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package io.papermc.paper.entity.poi;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import org.bukkit.Registry;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* All the built-in point of interest types.
|
||||
*/
|
||||
@NullMarked
|
||||
public final class PoiTypes {
|
||||
|
||||
// Start generate - PoiTypes
|
||||
public static final PoiType ARMORER = get("armorer");
|
||||
|
||||
public static final PoiType BEE_NEST = get("bee_nest");
|
||||
|
||||
public static final PoiType BEEHIVE = get("beehive");
|
||||
|
||||
public static final PoiType BUTCHER = get("butcher");
|
||||
|
||||
public static final PoiType CARTOGRAPHER = get("cartographer");
|
||||
|
||||
public static final PoiType CLERIC = get("cleric");
|
||||
|
||||
public static final PoiType FARMER = get("farmer");
|
||||
|
||||
public static final PoiType FISHERMAN = get("fisherman");
|
||||
|
||||
public static final PoiType FLETCHER = get("fletcher");
|
||||
|
||||
public static final PoiType HOME = get("home");
|
||||
|
||||
public static final PoiType LEATHERWORKER = get("leatherworker");
|
||||
|
||||
public static final PoiType LIBRARIAN = get("librarian");
|
||||
|
||||
public static final PoiType LIGHTNING_ROD = get("lightning_rod");
|
||||
|
||||
public static final PoiType LODESTONE = get("lodestone");
|
||||
|
||||
public static final PoiType MASON = get("mason");
|
||||
|
||||
public static final PoiType MEETING = get("meeting");
|
||||
|
||||
public static final PoiType NETHER_PORTAL = get("nether_portal");
|
||||
|
||||
public static final PoiType SHEPHERD = get("shepherd");
|
||||
|
||||
public static final PoiType TEST_INSTANCE = get("test_instance");
|
||||
|
||||
public static final PoiType TOOLSMITH = get("toolsmith");
|
||||
|
||||
public static final PoiType WEAPONSMITH = get("weaponsmith");
|
||||
// End generate - PoiTypes
|
||||
|
||||
private static PoiType get(@KeyPattern.Value final String key) {
|
||||
return Registry.POINT_OF_INTEREST_TYPE.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||
}
|
||||
|
||||
private PoiTypes() {
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
package io.papermc.paper.event.player;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.connection.PlayerConfigurationConnection;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
@@ -52,7 +53,7 @@ public class AsyncPlayerSpawnLocationEvent extends Event {
|
||||
* @return the spawn location
|
||||
*/
|
||||
public Location getSpawnLocation() {
|
||||
return this.spawnLocation;
|
||||
return this.spawnLocation.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,8 @@ public class AsyncPlayerSpawnLocationEvent extends Event {
|
||||
* @param location the spawn location
|
||||
*/
|
||||
public void setSpawnLocation(final Location location) {
|
||||
Preconditions.checkArgument(location != null, "Location cannot be null");
|
||||
Preconditions.checkArgument(location.getWorld() != null, "World cannot be null");
|
||||
this.spawnLocation = location.clone();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.papermc.paper.registry;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
@@ -92,6 +93,11 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
|
||||
* @see io.papermc.paper.registry.keys.VillagerProfessionKeys
|
||||
*/
|
||||
RegistryKey<Villager.Profession> VILLAGER_PROFESSION = create("villager_profession");
|
||||
/**
|
||||
* Built-in registry for poi types.
|
||||
* @see io.papermc.paper.registry.keys.PoiTypeKeys
|
||||
*/
|
||||
RegistryKey<PoiType> POINT_OF_INTEREST_TYPE = create("point_of_interest_type");
|
||||
/**
|
||||
* Built-in registry for villager types.
|
||||
* @see io.papermc.paper.registry.keys.VillagerTypeKeys
|
||||
|
||||
+3
-2
@@ -12,6 +12,7 @@ import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.EquipmentSlotGroup;
|
||||
import org.bukkit.inventory.ItemType;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Range;
|
||||
@@ -99,7 +100,7 @@ public interface EnchantmentRegistryEntry {
|
||||
*
|
||||
* @return the anvil cost of this enchantment
|
||||
*/
|
||||
@Range(from = 0, to = Integer.MAX_VALUE) int anvilCost();
|
||||
@NonNegative int anvilCost();
|
||||
|
||||
/**
|
||||
* Provides a list of slot groups this enchantment may be active in.
|
||||
@@ -245,7 +246,7 @@ public interface EnchantmentRegistryEntry {
|
||||
* @see Enchantment#getAnvilCost()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder anvilCost(@Range(from = 0, to = Integer.MAX_VALUE) int anvilCost);
|
||||
Builder anvilCost(@NonNegative int anvilCost);
|
||||
|
||||
/**
|
||||
* Configures the list of slot groups this enchantment may be active in.
|
||||
|
||||
@@ -2,9 +2,9 @@ package io.papermc.paper.registry.data;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import org.bukkit.GameEvent;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
/**
|
||||
* A data-centric version-specific registry entry for the {@link GameEvent} type.
|
||||
@@ -19,7 +19,7 @@ public interface GameEventRegistryEntry {
|
||||
* @return the range of blocks, represented as an int.
|
||||
* @see GameEvent#getRange()
|
||||
*/
|
||||
@Range(from = 0, to = Integer.MAX_VALUE) int range();
|
||||
@NonNegative int range();
|
||||
|
||||
/**
|
||||
* A mutable builder for the {@link GameEventRegistryEntry} plugins may change in applicable registry events.
|
||||
@@ -42,6 +42,6 @@ public interface GameEventRegistryEntry {
|
||||
* @see GameEvent#getRange()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder range(@Range(from = 0, to = Integer.MAX_VALUE) int range);
|
||||
Builder range(@NonNegative int range);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Event object for {@link RegistryEventProvider#compose()}. This
|
||||
@@ -32,6 +33,19 @@ public interface RegistryComposeEvent<T, B extends RegistryBuilder<T>> extends R
|
||||
* @param tagKey the tag key
|
||||
* @return the tag
|
||||
* @param <V> the tag value type
|
||||
* @deprecated use {@link #retriever()}
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey); // TODO remove Keyed
|
||||
@Deprecated(forRemoval = true)
|
||||
default <V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey) { // TODO remove Keyed
|
||||
return this.retriever().getOrCreateTag(tagKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registry retriever, which can be used to retrieve or create
|
||||
* entries in the registry.
|
||||
*
|
||||
* @return the registry retriever
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
RegistryRetriever retriever();
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Event object for {@link RegistryEventProvider#entryAdd()}. This
|
||||
@@ -40,6 +41,19 @@ public interface RegistryEntryAddEvent<T, B extends RegistryBuilder<T>> extends
|
||||
* @param tagKey the tag key
|
||||
* @return the tag
|
||||
* @param <V> the tag value type
|
||||
* @deprecated use {@link #retriever()}
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey);
|
||||
@Deprecated(forRemoval = true)
|
||||
default <V extends Keyed> Tag<V> getOrCreateTag(final TagKey<V> tagKey) { // TODO remove Keyed
|
||||
return this.retriever().getOrCreateTag(tagKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registry retriever, which can be used to retrieve or create
|
||||
* entries in the registry.
|
||||
*
|
||||
* @return the registry retriever
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
RegistryRetriever retriever();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.papermc.paper.registry.event;
|
||||
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public interface RegistryRetriever {
|
||||
|
||||
/**
|
||||
* Gets or creates a tag for the given tag key. This tag
|
||||
* is then required to be filled either from the built-in or
|
||||
* custom datapack.
|
||||
*
|
||||
* @param tagKey the tag key
|
||||
* @param <V> the tag value type
|
||||
* @return the tag
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey); // TODO remove Keyed
|
||||
|
||||
/**
|
||||
* Gets or creates an empty instance of the given {@link TypedKey}.
|
||||
* <br>
|
||||
* Can only create instances if the applicable registry still supports adding
|
||||
* new references. If the registry doesn't, this method will throw an exception.
|
||||
*
|
||||
* @param key the key to get or create an instance for
|
||||
* @param <V> the type of the value associated with the key
|
||||
* @return an instance of the given key, or a new instance if it does not exist
|
||||
* @throws IllegalStateException if this registry does not support adding new references and the key does not exist
|
||||
*/
|
||||
<V extends Keyed> V getOrCreate(TypedKey<V> key); // TODO remove Keyed
|
||||
}
|
||||
@@ -857,11 +857,15 @@ public final class Bukkit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world with the given name.
|
||||
* Gets the world with the given legacy Bukkit name.
|
||||
*
|
||||
* @param name the name of the world to retrieve
|
||||
* @return a world with the given name, or null if none exists
|
||||
* <p>This method is considered obsolete and is a candidate for future deprecation.
|
||||
* Prefer using {@link #getWorld(NamespacedKey)}.</p>
|
||||
*
|
||||
* @param name the legacy Bukkit name of the world to retrieve
|
||||
* @return a world with the given legacy Bukkit name, or null if none exists
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
@Nullable
|
||||
public static World getWorld(@NotNull String name) {
|
||||
return server.getWorld(name);
|
||||
@@ -877,7 +881,7 @@ public final class Bukkit {
|
||||
public static World getWorld(@NotNull UUID uid) {
|
||||
return server.getWorld(uid);
|
||||
}
|
||||
// Paper start
|
||||
|
||||
/**
|
||||
* Gets the world from the given NamespacedKey
|
||||
*
|
||||
@@ -899,7 +903,6 @@ public final class Bukkit {
|
||||
public static World getWorld(@NotNull net.kyori.adventure.key.Key worldKey) {
|
||||
return server.getWorld(worldKey);
|
||||
}
|
||||
// Paper end
|
||||
|
||||
/**
|
||||
* Create a new virtual {@link WorldBorder}.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.math.FinePosition;
|
||||
import io.papermc.paper.math.Rotation;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import io.papermc.paper.math.FinePosition;
|
||||
import io.papermc.paper.math.Rotation;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -574,7 +574,7 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
|
||||
} else if (o.getWorld() == null || getWorld() == null) {
|
||||
throw new IllegalArgumentException("Cannot measure distance to a null world");
|
||||
} else if (o.getWorld() != getWorld()) {
|
||||
throw new IllegalArgumentException("Cannot measure distance between " + getWorld().getKey() + " and " + o.getWorld().getKey());
|
||||
throw new IllegalArgumentException("Cannot measure distance between " + getWorld().key().asString() + " and " + o.getWorld().key().asString());
|
||||
}
|
||||
|
||||
return NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z);
|
||||
@@ -1186,10 +1186,11 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
|
||||
@Utility
|
||||
@NotNull
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
|
||||
if (this.world != null) {
|
||||
data.put("world_key", getWorld().getKey().toString());
|
||||
World world = this.getWorld();
|
||||
if (world != null) {
|
||||
data.put("world_key", world.key().asString());
|
||||
}
|
||||
|
||||
data.put("x", this.x);
|
||||
@@ -1219,7 +1220,8 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
|
||||
requiresWorld = true;
|
||||
}
|
||||
if (args.containsKey("world_key")) {
|
||||
world = Bukkit.getWorld(NamespacedKey.fromString((String) args.get("world_key")));
|
||||
NamespacedKey key = NamespacedKey.fromString((String) args.get("world_key"));
|
||||
world = key == null ? null : Bukkit.getWorld(key);
|
||||
requiresWorld = true;
|
||||
}
|
||||
|
||||
@@ -1227,7 +1229,6 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
|
||||
throw new IllegalArgumentException("unknown world");
|
||||
}
|
||||
|
||||
|
||||
return new Location(world, NumberConversions.toDouble(args.get("x")), NumberConversions.toDouble(args.get("y")), NumberConversions.toDouble(args.get("z")), NumberConversions.toFloat(args.get("yaw")), NumberConversions.toFloat(args.get("pitch")));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import io.papermc.paper.world.MoonPhase;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -526,12 +527,12 @@ public interface RegionAccessor extends Keyed, io.papermc.paper.world.flag.Featu
|
||||
@NotNull
|
||||
public <T extends Entity> T addEntity(@NotNull T entity);
|
||||
|
||||
// Paper start
|
||||
/**
|
||||
* @return the current moon phase at the current time in the world
|
||||
* @apiNote the returned value may be inaccurate in custom biome using environmental attribute override
|
||||
*/
|
||||
@NotNull
|
||||
io.papermc.paper.world.MoonPhase getMoonPhase();
|
||||
MoonPhase getMoonPhase();
|
||||
|
||||
/**
|
||||
* Get the world's key
|
||||
@@ -559,5 +560,4 @@ public interface RegionAccessor extends Keyed, io.papermc.paper.world.flag.Featu
|
||||
* @return collides or not
|
||||
*/
|
||||
boolean hasCollisionsIn(@NotNull org.bukkit.util.BoundingBox boundingBox);
|
||||
// Paper end
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
@@ -280,6 +281,12 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
|
||||
* @see Villager.Profession
|
||||
*/
|
||||
Registry<Villager.Profession> VILLAGER_PROFESSION = registryFor(RegistryKey.VILLAGER_PROFESSION);
|
||||
/**
|
||||
* Point of interest types.
|
||||
*
|
||||
* @see PoiType
|
||||
*/
|
||||
Registry<PoiType> POINT_OF_INTEREST_TYPE = registryFor(RegistryKey.POINT_OF_INTEREST_TYPE);
|
||||
/**
|
||||
* Villager type.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.bukkit;
|
||||
|
||||
import io.papermc.paper.entity.poi.PoiSearchResult;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
@@ -43,6 +45,7 @@ import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.StructureSearchResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.checkerframework.checker.index.qual.Positive;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -2091,10 +2094,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
*
|
||||
* @param time The new absolute time to set this world to
|
||||
* @see #setTime(long) Sets the relative time of this world
|
||||
* @deprecated all overworlds share the same world clock by default now
|
||||
* @throws IllegalArgumentException if this world does not have a world clock (e.g. the nether)
|
||||
*/
|
||||
@Deprecated // TODO world clock API with links to it
|
||||
public void setFullTime(long time);
|
||||
|
||||
// Paper start
|
||||
@@ -2769,10 +2770,11 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
/**
|
||||
* Gets if this world is natural.
|
||||
* <p>
|
||||
* When false, the moon is not visible and eyeblossoms do not open/close
|
||||
* When true, eyeblossoms cycle open/close, nether portals can spawn
|
||||
* zombified piglins and creaking heart works
|
||||
*
|
||||
* @return true if world is natural
|
||||
* @deprecated replaced by the gameplay/eyeblossom_open and gameplay/creaking_active environment attributes
|
||||
* @deprecated replaced by the gameplay/nether_portal_spawns_piglin, gameplay/eyeblossom_open and gameplay/creaking_active environmental attributes
|
||||
*/
|
||||
@Deprecated(since = "1.21.11")
|
||||
public boolean isNatural();
|
||||
@@ -2784,7 +2786,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* not always be the case.
|
||||
*
|
||||
* @return true if beds work in this world
|
||||
* @deprecated Due to 1.21.11 beds changes, a boolean no longer
|
||||
* @deprecated due to 1.21.11 beds changes, a boolean no longer
|
||||
* represents if they work. There is no replacement API yet
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "1.21.11")
|
||||
@@ -2809,6 +2811,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* transforming to zombified piglins.
|
||||
*
|
||||
* @return true if piglins will not transform to zombified piglins
|
||||
* @apiNote the returned value may be inaccurate in custom biome using environmental attribute override
|
||||
*/
|
||||
public boolean isPiglinSafe();
|
||||
|
||||
@@ -2816,6 +2819,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* Gets if this world allows players to charge and use respawn anchors.
|
||||
*
|
||||
* @return true if players can charge and use respawn anchors
|
||||
* @apiNote the returned value may be inaccurate in custom biome using environmental attribute override
|
||||
*/
|
||||
public boolean isRespawnAnchorWorks();
|
||||
|
||||
@@ -2824,6 +2828,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* raid.
|
||||
*
|
||||
* @return true if raids will be triggered
|
||||
* @apiNote the returned value may be inaccurate in custom biome using environmental attribute override
|
||||
*/
|
||||
public boolean hasRaids();
|
||||
|
||||
@@ -2837,7 +2842,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* </ul>
|
||||
*
|
||||
* @return true if this world has the above mechanics
|
||||
* @deprecated as of 1.21.11, ultra warm is replaced by the WATER_EVAPORATES, FAST_LAVA, and DEFAULT_DRIPSTONE_PARTICLE environment attributes.
|
||||
* @deprecated replaced by the gameplay/water_evaporates and gameplay/fast_lava environmental attributes
|
||||
*/
|
||||
@Deprecated(since = "1.21.11")
|
||||
public boolean isUltraWarm();
|
||||
@@ -4295,6 +4300,69 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
return java.util.Optional.ofNullable(this.locateNearestBiome(origin, radius, step, step, biome)).map(BiomeSearchResult::getLocation).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the nearest point of interest closest to the given location
|
||||
* without any occupancy restriction.
|
||||
*
|
||||
* @param origin where to start looking for a new point of interest at
|
||||
* @param poiType the poi type to find
|
||||
* @param radius the radius
|
||||
* @return a location at the nearest PoiType or {@code null} if no poi was found
|
||||
*/
|
||||
@Nullable
|
||||
default Location locateNearestPoi(@NotNull Location origin, @NotNull PoiType poiType, @Positive int radius) {
|
||||
return this.locateNearestPoi(origin, poiType, radius, PoiType.Occupancy.ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the nearest point of interest closest to the given location.
|
||||
* <p>
|
||||
* {@link PoiType} that return {@code false} for {@link PoiType#hasOccupants()}
|
||||
* may not behave as expected for given occupancies other than
|
||||
* {@link PoiType.Occupancy#ANY}.
|
||||
*
|
||||
* @param origin where to start looking for a new point of interest at
|
||||
* @param poiType the poi type to find
|
||||
* @param radius the radius
|
||||
* @param occupancy the current required occupancy of the point of interest
|
||||
* @return a location at the nearest PoiType or {@code null} if no poi was found
|
||||
*/
|
||||
@Nullable
|
||||
Location locateNearestPoi(@NotNull Location origin, @NotNull PoiType poiType, @Positive int radius, @NotNull PoiType.Occupancy occupancy);
|
||||
|
||||
/**
|
||||
* Finds all valid {@link PoiType} in the provided radius and returns them
|
||||
* in a list format without any occupancy restriction.
|
||||
*
|
||||
* @param origin the center point of the radius
|
||||
* @param poiTypePredicate the predicate to test whether a PoiType
|
||||
* can be collected into the result
|
||||
* @param radius the radius
|
||||
* @return a list of search results containing all found Poi's in the range
|
||||
*/
|
||||
@NotNull
|
||||
default List<PoiSearchResult> locateAllPoiInRange(@NotNull Location origin, @NotNull Predicate<PoiType> poiTypePredicate, @Positive int radius) {
|
||||
return this.locateAllPoiInRange(origin, poiTypePredicate, radius, PoiType.Occupancy.ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all valid {@link PoiType} in the provided radius and returns them
|
||||
* in a list format.
|
||||
* <p>
|
||||
* {@link PoiType} that return false for {@link PoiType#hasOccupants()}
|
||||
* may not behave as expected for given occupancies other than
|
||||
* {@link PoiType.Occupancy#ANY}.
|
||||
*
|
||||
* @param origin the center point of the radius
|
||||
* @param poiTypePredicate the predicate to test whether a PoiType
|
||||
* can be collected into the result
|
||||
* @param radius the radius
|
||||
* @param occupancy the current required occupancy of the point of interest
|
||||
* @return a list of search results containing all found Poi's in the range
|
||||
*/
|
||||
@NotNull
|
||||
List<PoiSearchResult> locateAllPoiInRange(@NotNull Location origin, @NotNull Predicate<PoiType> poiTypePredicate, @Positive int radius, @NotNull PoiType.Occupancy occupancy);
|
||||
|
||||
/**
|
||||
* Gets the coordinate scaling of this world.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Random;
|
||||
import io.papermc.paper.math.Position;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
@@ -26,6 +27,10 @@ public class WorldCreator {
|
||||
private boolean hardcore = false;
|
||||
private boolean bonusChest = false;
|
||||
|
||||
private @Nullable Position spawnPositionOverride;
|
||||
private @Nullable Float spawnYawOverride;
|
||||
private @Nullable Float spawnPitchOverride;
|
||||
|
||||
/**
|
||||
* Creates an empty WorldCreationOptions for the given world name.
|
||||
*
|
||||
@@ -261,6 +266,80 @@ public class WorldCreator {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the forced spawn position for the world created by this {@link WorldCreator}.
|
||||
* <p>
|
||||
* This overrides vanilla and custom generator behavior without loading any chunks.
|
||||
* When a forced spawn is specified, the bonus chest will not be generated.
|
||||
*
|
||||
* @param position the spawn position
|
||||
* @param yaw the yaw rotation at spawn
|
||||
* @param pitch the pitch rotation at spawn
|
||||
* @return this object, for chaining
|
||||
*/
|
||||
@NotNull
|
||||
public WorldCreator forcedSpawnPosition(@NotNull Position position, float yaw, float pitch) {
|
||||
this.spawnPositionOverride = position; // If you set this to null, it wont do anything!
|
||||
this.spawnYawOverride = yaw;
|
||||
this.spawnPitchOverride = pitch;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any previously forced spawn position.
|
||||
* <p>
|
||||
* After calling this, vanilla spawn selection behavior is used.
|
||||
*
|
||||
* @return this object, for chaining
|
||||
*/
|
||||
@NotNull
|
||||
public WorldCreator clearForcedSpawnPosition() {
|
||||
this.spawnPositionOverride = null;
|
||||
this.spawnYawOverride = null;
|
||||
this.spawnPitchOverride = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the forced spawn position that will be applied when this world is created.
|
||||
* <p>
|
||||
* If this returns {@code null}, vanilla or custom generator behavior will be used
|
||||
* to determine the spawn position.
|
||||
*
|
||||
* @return the forced spawn position, or {@code null} for the vanilla behavior
|
||||
*/
|
||||
public @Nullable Position forcedSpawnPosition() {
|
||||
return this.spawnPositionOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the forced spawn yaw that will be applied when this world is created.
|
||||
* <p>
|
||||
* If this returns {@code null}, the spawn yaw will be determined by vanilla behavior
|
||||
* or the world generator.
|
||||
* <p>
|
||||
* This value is only meaningful if a forced spawn position is present.
|
||||
*
|
||||
* @return the forced spawn yaw, or {@code null} for the vanilla behavior
|
||||
*/
|
||||
public @Nullable Float forcedSpawnYaw() {
|
||||
return this.spawnYawOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the forced spawn pitch that will be applied when this world is created.
|
||||
* <p>
|
||||
* If this returns {@code null}, the spawn pitch will be determined by vanilla behavior
|
||||
* or the world generator.
|
||||
* <p>
|
||||
* This value is only meaningful if a forced spawn position is present.
|
||||
*
|
||||
* @return the forced spawn pitch, or {@code null} for the vanilla behavior
|
||||
*/
|
||||
public @Nullable Float forcedSpawnPitch() {
|
||||
return this.spawnPitchOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generator that will be used to create or load the world.
|
||||
* <p>
|
||||
|
||||
@@ -2,12 +2,15 @@ package org.bukkit.entity;
|
||||
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.bukkit.event.entity.EntityRegainHealthEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents an {@link Entity} that has health and can take damage.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface Damageable extends Entity {
|
||||
/**
|
||||
* Deals the given amount of damage to this entity.
|
||||
@@ -32,7 +35,24 @@ public interface Damageable extends Entity {
|
||||
* @param amount amount of damage to deal
|
||||
* @param damageSource source to which the damage should be attributed
|
||||
*/
|
||||
void damage(double amount, @NotNull DamageSource damageSource);
|
||||
void damage(double amount, DamageSource damageSource);
|
||||
|
||||
/**
|
||||
* Sets the entity's health to 0 and kill the entity with a generic DamageSource.
|
||||
*
|
||||
* @throws IllegalStateException if is used in world generation
|
||||
*/
|
||||
default void kill() {
|
||||
this.kill(DamageSource.builder(DamageType.GENERIC_KILL).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity's health to 0 and kill the entity with the specified DamageSource.
|
||||
*
|
||||
* @param damageSource the DamageSource to use for the kill
|
||||
* @throws IllegalStateException if is used in world generation
|
||||
*/
|
||||
void kill(DamageSource damageSource);
|
||||
|
||||
/**
|
||||
* Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead.
|
||||
@@ -57,7 +77,7 @@ public interface Damageable extends Entity {
|
||||
* @param amount heal amount
|
||||
*/
|
||||
default void heal(final double amount) {
|
||||
this.heal(amount, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.CUSTOM);
|
||||
this.heal(amount, EntityRegainHealthEvent.RegainReason.CUSTOM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +86,7 @@ public interface Damageable extends Entity {
|
||||
* @param amount heal amount
|
||||
* @param reason heal reason
|
||||
*/
|
||||
void heal(double amount, @NotNull org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason reason);
|
||||
void heal(double amount, EntityRegainHealthEvent.RegainReason reason);
|
||||
|
||||
/**
|
||||
* Gets the entity's absorption amount.
|
||||
|
||||
@@ -3349,8 +3349,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Get the player's current client side view distance.
|
||||
* <br>
|
||||
* Will default to the server view distance if the client has not yet
|
||||
* communicated this information,
|
||||
* Will default to 2 if the client has not yet communicated this information.
|
||||
*
|
||||
* @return client view distance as above
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
package org.bukkit.event.block;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when a redstone current changes
|
||||
* Called when a redstone current changes.
|
||||
* <p>
|
||||
* It includes the relevant mutation of the {@code powered} and {@code power}
|
||||
* properties even if the block is not able to produce a redstone signal.
|
||||
* For the {@code powered} property, a high state will be considered as
|
||||
* a current of 15 and a low state as 0. Setting the new current to a different
|
||||
* value will prevent most action in this case.
|
||||
*/
|
||||
@NullMarked
|
||||
public class BlockRedstoneEvent extends BlockEvent {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
@@ -16,46 +25,45 @@ public class BlockRedstoneEvent extends BlockEvent {
|
||||
private int newCurrent;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public BlockRedstoneEvent(@NotNull final Block block, final int oldCurrent, final int newCurrent) {
|
||||
public BlockRedstoneEvent(final Block block, final int oldCurrent, final int newCurrent) {
|
||||
super(block);
|
||||
this.oldCurrent = oldCurrent;
|
||||
this.newCurrent = newCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the old current of this block
|
||||
* Gets the old current of this block.
|
||||
*
|
||||
* @return The previous current
|
||||
* @return the previous current
|
||||
*/
|
||||
public int getOldCurrent() {
|
||||
public @IntRange(from = 0, to = 15) int getOldCurrent() {
|
||||
return this.oldCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new current of this block
|
||||
* Gets the new current of this block.
|
||||
*
|
||||
* @return The new current
|
||||
* @return the new current
|
||||
*/
|
||||
public int getNewCurrent() {
|
||||
public @IntRange(from = 0, to = 15) int getNewCurrent() {
|
||||
return this.newCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new current of this block
|
||||
* Sets the new current of this block.
|
||||
*
|
||||
* @param newCurrent The new current to set
|
||||
* @param newCurrent the new current to set
|
||||
*/
|
||||
public void setNewCurrent(int newCurrent) {
|
||||
public void setNewCurrent(@IntRange(from = 0, to = 15) int newCurrent) {
|
||||
Preconditions.checkArgument(newCurrent >= 0 && newCurrent <= 15, "New current must be a redstone signal between 0 and 15 (was %s)", newCurrent);
|
||||
this.newCurrent = newCurrent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ public class EntityUnleashEvent extends EntityEvent implements Cancellable {
|
||||
* When the entity's leashholder is more than 10 blocks away
|
||||
*/
|
||||
DISTANCE,
|
||||
/**
|
||||
* When the leashed entity is removed from the game
|
||||
*/
|
||||
LEASHED_GONE,
|
||||
UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,30 @@
|
||||
package org.bukkit.event.hanging;
|
||||
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Hanging;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Triggered when a hanging entity is removed by an entity
|
||||
*/
|
||||
@NullMarked
|
||||
public class HangingBreakByEntityEvent extends HangingBreakEvent {
|
||||
|
||||
private final Entity remover;
|
||||
private final DamageSource damageSource;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public HangingBreakByEntityEvent(@NotNull final Hanging hanging, @NotNull final Entity remover) {
|
||||
this(hanging, remover, HangingBreakEvent.RemoveCause.ENTITY);
|
||||
public HangingBreakByEntityEvent(final Hanging hanging, final Entity remover, final DamageSource damageSource) {
|
||||
this(hanging, remover, damageSource, HangingBreakEvent.RemoveCause.ENTITY);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public HangingBreakByEntityEvent(@NotNull final Hanging hanging, @NotNull final Entity remover, @NotNull final HangingBreakEvent.RemoveCause cause) {
|
||||
public HangingBreakByEntityEvent(final Hanging hanging, final Entity remover, final DamageSource damageSource, final HangingBreakEvent.RemoveCause cause) {
|
||||
super(hanging, cause);
|
||||
this.remover = remover;
|
||||
this.damageSource = damageSource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,8 +32,16 @@ public class HangingBreakByEntityEvent extends HangingBreakEvent {
|
||||
*
|
||||
* @return the entity that removed the hanging entity
|
||||
*/
|
||||
@NotNull
|
||||
public Entity getRemover() {
|
||||
return this.remover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link DamageSource} that caused the hanging entity to be removed.
|
||||
*
|
||||
* @return the damage source
|
||||
*/
|
||||
public DamageSource getDamageSource() {
|
||||
return this.damageSource;
|
||||
}
|
||||
}
|
||||
@@ -6,24 +6,26 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Called when a player gets kicked from the server
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private Component kickReason;
|
||||
private Component leaveMessage;
|
||||
private @Nullable Component leaveMessage;
|
||||
private final Cause cause;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true)
|
||||
public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) {
|
||||
public PlayerKickEvent(final Player playerKicked, final String kickReason, final String leaveMessage) {
|
||||
super(playerKicked);
|
||||
this.kickReason = LegacyComponentSerializer.legacySection().deserialize(kickReason);
|
||||
this.leaveMessage = LegacyComponentSerializer.legacySection().deserialize(leaveMessage);
|
||||
@@ -32,7 +34,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true)
|
||||
public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final Component kickReason, @NotNull final Component leaveMessage) {
|
||||
public PlayerKickEvent(final Player playerKicked, final Component kickReason, final Component leaveMessage) {
|
||||
super(playerKicked);
|
||||
this.kickReason = kickReason;
|
||||
this.leaveMessage = leaveMessage;
|
||||
@@ -40,7 +42,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final Component kickReason, @NotNull final Component leaveMessage, @NotNull final Cause cause) {
|
||||
public PlayerKickEvent(final Player playerKicked, final Component kickReason, final Component leaveMessage, final Cause cause) {
|
||||
super(playerKicked);
|
||||
this.kickReason = kickReason;
|
||||
this.leaveMessage = leaveMessage;
|
||||
@@ -52,7 +54,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
*
|
||||
* @return string kick reason
|
||||
*/
|
||||
public @NotNull Component reason() {
|
||||
public Component reason() {
|
||||
return this.kickReason;
|
||||
}
|
||||
|
||||
@@ -61,7 +63,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
*
|
||||
* @param kickReason kick reason
|
||||
*/
|
||||
public void reason(@NotNull Component kickReason) {
|
||||
public void reason(Component kickReason) {
|
||||
this.kickReason = kickReason;
|
||||
}
|
||||
|
||||
@@ -71,7 +73,6 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
* @return string kick reason
|
||||
* @deprecated in favour of {@link #reason()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public String getReason() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.kickReason);
|
||||
@@ -81,10 +82,10 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
* Sets the reason why the player is getting kicked
|
||||
*
|
||||
* @param kickReason kick reason
|
||||
* @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)}
|
||||
* @deprecated in favour of {@link #reason(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setReason(@NotNull String kickReason) {
|
||||
public void setReason(String kickReason) {
|
||||
this.kickReason = LegacyComponentSerializer.legacySection().deserialize(kickReason);
|
||||
}
|
||||
|
||||
@@ -93,16 +94,16 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
*
|
||||
* @return string kick reason
|
||||
*/
|
||||
public @NotNull Component leaveMessage() {
|
||||
public @Nullable Component leaveMessage() {
|
||||
return this.leaveMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the leave message send to all online players
|
||||
*
|
||||
* @param leaveMessage leave message
|
||||
* @param leaveMessage leave message. If {@code null}, no message will be sent
|
||||
*/
|
||||
public void leaveMessage(@NotNull Component leaveMessage) {
|
||||
public void leaveMessage(@Nullable Component leaveMessage) {
|
||||
this.leaveMessage = leaveMessage;
|
||||
}
|
||||
|
||||
@@ -112,28 +113,26 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
* @return string kick reason
|
||||
* @deprecated in favour of {@link #leaveMessage()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public String getLeaveMessage() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.leaveMessage);
|
||||
public @Nullable String getLeaveMessage() {
|
||||
return LegacyComponentSerializer.legacySection().serializeOrNull(this.leaveMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the leave message send to all online players
|
||||
*
|
||||
* @param leaveMessage leave message
|
||||
* @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)}
|
||||
* @param leaveMessage leave message. If {@code null}, no message will be sent
|
||||
* @deprecated in favour of {@link #leaveMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setLeaveMessage(@NotNull String leaveMessage) {
|
||||
this.leaveMessage = LegacyComponentSerializer.legacySection().deserialize(leaveMessage);
|
||||
public void setLeaveMessage(@Nullable String leaveMessage) {
|
||||
this.leaveMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(leaveMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause of this kick
|
||||
*/
|
||||
@NotNull
|
||||
public org.bukkit.event.player.PlayerKickEvent.Cause getCause() {
|
||||
public PlayerKickEvent.Cause getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
|
||||
@@ -147,13 +146,11 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.event.vehicle;
|
||||
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.event.Cancellable;
|
||||
@@ -15,18 +16,30 @@ public class VehicleDamageEvent extends VehicleEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final DamageSource damageSource;
|
||||
private final Entity attacker;
|
||||
private double damage;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public VehicleDamageEvent(@NotNull final Vehicle vehicle, @Nullable final Entity attacker, final double damage) {
|
||||
public VehicleDamageEvent(final @NotNull Vehicle vehicle, final @NotNull DamageSource damageSource, final @Nullable Entity attacker, final double damage) {
|
||||
super(vehicle);
|
||||
this.damageSource = damageSource;
|
||||
this.attacker = attacker;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DamageSource that caused the damage.
|
||||
*
|
||||
* @return the DamageSource that caused the damage
|
||||
*/
|
||||
@NotNull
|
||||
public DamageSource getDamageSource() {
|
||||
return this.damageSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Entity that is attacking the vehicle
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.event.vehicle;
|
||||
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.event.Cancellable;
|
||||
@@ -17,15 +18,27 @@ public class VehicleDestroyEvent extends VehicleEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final DamageSource damageSource;
|
||||
private final Entity attacker;
|
||||
private boolean cancelled;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public VehicleDestroyEvent(@NotNull final Vehicle vehicle, @Nullable final Entity attacker) {
|
||||
public VehicleDestroyEvent(final @NotNull Vehicle vehicle, final @NotNull DamageSource damageSource, final @Nullable Entity attacker) {
|
||||
super(vehicle);
|
||||
this.damageSource = damageSource;
|
||||
this.attacker = attacker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DamageSource that has destroyed the vehicle.
|
||||
*
|
||||
* @return the DamageSource that has destroyed the vehicle
|
||||
*/
|
||||
@NotNull
|
||||
public DamageSource getDamageSource() {
|
||||
return this.damageSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Entity that has destroyed the vehicle, potentially null
|
||||
*
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.bukkit.event.world;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when the time skips for a world clock.
|
||||
* <p>
|
||||
* If the event is cancelled the time will not change.
|
||||
*/
|
||||
// TODO - snapshot - 26.1 clock
|
||||
@ApiStatus.Experimental
|
||||
@NullMarked
|
||||
public class ClockTimeSkipEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final SkipReason skipReason;
|
||||
private long skipAmount;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ClockTimeSkipEvent(final SkipReason skipReason, final long skipAmount) {
|
||||
this.skipReason = skipReason;
|
||||
this.skipAmount = skipAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reason why the time has skipped.
|
||||
*
|
||||
* @return a SkipReason value detailing why the time has skipped
|
||||
*/
|
||||
public SkipReason getSkipReason() {
|
||||
return this.skipReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of time that was skipped.
|
||||
*
|
||||
* @return Amount of time skipped
|
||||
*/
|
||||
public long getSkipAmount() {
|
||||
return this.skipAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of time to skip.
|
||||
*
|
||||
* @param skipAmount Amount of time to skip
|
||||
*/
|
||||
public void setSkipAmount(long skipAmount) {
|
||||
this.skipAmount = skipAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum specifying the reason the time skipped.
|
||||
*/
|
||||
public enum SkipReason {
|
||||
|
||||
/**
|
||||
* When time is changed using the vanilla /time command.
|
||||
*/
|
||||
COMMAND,
|
||||
/**
|
||||
* When time is changed by a plugin.
|
||||
*/
|
||||
CUSTOM,
|
||||
/**
|
||||
* When time is changed by all players sleeping in their beds and the
|
||||
* night skips.
|
||||
*/
|
||||
NIGHT_SKIP
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.bukkit.event.world;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -10,60 +9,29 @@ import org.jetbrains.annotations.NotNull;
|
||||
* Called when the time skips in a world.
|
||||
* <p>
|
||||
* If the event is cancelled the time will not change.
|
||||
*
|
||||
* @see ClockTimeSkipEvent for changing of clocks that affect all worlds
|
||||
*/
|
||||
// TODO - snapshot - 26.1 API needed for clock!
|
||||
public class TimeSkipEvent extends WorldEvent implements Cancellable {
|
||||
public class TimeSkipEvent extends ClockTimeSkipEvent {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final SkipReason skipReason;
|
||||
private long skipAmount;
|
||||
|
||||
private boolean cancelled;
|
||||
private final World world;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public TimeSkipEvent(@NotNull World world, @NotNull SkipReason skipReason, long skipAmount) {
|
||||
super(world);
|
||||
this.skipReason = skipReason;
|
||||
this.skipAmount = skipAmount;
|
||||
super(skipReason, skipAmount);
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reason why the time has skipped.
|
||||
* Returns the world that time is skipped in.
|
||||
*
|
||||
* @return a SkipReason value detailing why the time has skipped
|
||||
* @return world that time is skipped in
|
||||
*/
|
||||
@NotNull
|
||||
public SkipReason getSkipReason() {
|
||||
return this.skipReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of time that was skipped.
|
||||
*
|
||||
* @return Amount of time skipped
|
||||
*/
|
||||
public long getSkipAmount() {
|
||||
return this.skipAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of time to skip.
|
||||
*
|
||||
* @param skipAmount Amount of time to skip
|
||||
*/
|
||||
public void setSkipAmount(long skipAmount) {
|
||||
this.skipAmount = skipAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -76,24 +44,4 @@ public class TimeSkipEvent extends WorldEvent implements Cancellable {
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum specifying the reason the time skipped.
|
||||
*/
|
||||
public enum SkipReason {
|
||||
|
||||
/**
|
||||
* When time is changed using the vanilla /time command.
|
||||
*/
|
||||
COMMAND,
|
||||
/**
|
||||
* When time is changed by a plugin.
|
||||
*/
|
||||
CUSTOM,
|
||||
/**
|
||||
* When time is changed by all players sleeping in their beds and the
|
||||
* night skips.
|
||||
*/
|
||||
NIGHT_SKIP
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.bukkit.inventory.meta.components;
|
||||
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
@@ -14,14 +15,14 @@ public interface FoodComponent extends ConfigurationSerializable {
|
||||
*
|
||||
* @return nutrition value
|
||||
*/
|
||||
int getNutrition();
|
||||
@NonNegative int getNutrition();
|
||||
|
||||
/**
|
||||
* Sets the food restored by this item when eaten.
|
||||
*
|
||||
* @param nutrition new nutrition value, must be non-negative
|
||||
*/
|
||||
void setNutrition(int nutrition);
|
||||
void setNutrition(@NonNegative int nutrition);
|
||||
|
||||
/**
|
||||
* Gets the saturation restored by this item when eaten.
|
||||
|
||||
@@ -133,26 +133,74 @@ public class PotionEffect implements ConfigurationSerializable {
|
||||
}
|
||||
|
||||
// Paper start
|
||||
/**
|
||||
* Returns a new potion effect with the provided type and this effect's
|
||||
* duration, amplifier, ambient, particles, and icon.
|
||||
*
|
||||
* @param type effect type
|
||||
* @return a new potion effect with the provided type
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withType(@NotNull PotionEffectType type) {
|
||||
return new PotionEffect(type, duration, amplifier, ambient, particles, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potion effect with the provided duration and this effect's
|
||||
* type, amplifier, ambient, particles, and icon.
|
||||
*
|
||||
* @param duration measured in ticks, see {@link
|
||||
* PotionEffect#getDuration()}
|
||||
* @return a new potion effect with the provided duration
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withDuration(int duration) {
|
||||
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potion effect with the provided amplifier and this effect's
|
||||
* type, duration, ambient, particles, and icon.
|
||||
*
|
||||
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
|
||||
* @return a new potion effect with the provided amplifier
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withAmplifier(int amplifier) {
|
||||
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potion effect with the provided ambient and this effect's
|
||||
* type, duration, amplifier, particles, and icon.
|
||||
*
|
||||
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
|
||||
* @return a new potion effect with the provided ambient
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withAmbient(boolean ambient) {
|
||||
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potion effect with the provided particles and this effect's
|
||||
* type, duration, amplifier, ambient, and icon.
|
||||
*
|
||||
* @param particles the particle status, see {@link PotionEffect#hasParticles()}
|
||||
* @return a new potion effect with the provided particles
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withParticles(boolean particles) {
|
||||
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potion effect with the provided icon and this effect's
|
||||
* type, duration, amplifier, ambient, and particles.
|
||||
*
|
||||
* @param icon the icon status, see {@link PotionEffect#hasIcon()}
|
||||
* @return a new potion effect with the provided icon
|
||||
*/
|
||||
@NotNull
|
||||
public PotionEffect withIcon(boolean icon) {
|
||||
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.spigotmc.event.player;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.Warning;
|
||||
@@ -49,6 +50,8 @@ public class PlayerSpawnLocationEvent extends PlayerEvent {
|
||||
* @param location the spawn location
|
||||
*/
|
||||
public void setSpawnLocation(@NotNull Location location) {
|
||||
Preconditions.checkArgument(location != null, "Location cannot be null");
|
||||
Preconditions.checkArgument(location.getWorld() != null, "World cannot be null");
|
||||
this.spawnLocation = location.clone();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import io.papermc.paper.datacomponent.item.SwingAnimation;
|
||||
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.item.MapPostProcessing;
|
||||
import io.papermc.paper.entity.poi.PoiTypes;
|
||||
import io.papermc.paper.world.WeatheringCopperState;
|
||||
import io.papermc.typewriter.preset.EnumCloneRewriter;
|
||||
import io.papermc.typewriter.preset.model.EnumValue;
|
||||
@@ -231,6 +232,7 @@ public final class Rewriters {
|
||||
.register("PigSoundVariant", Pig.SoundVariant.class, new RegistryFieldRewriter<>(Registries.PIG_SOUND_VARIANT, "getSoundVariant"))
|
||||
.register("ZombieNautilusVariant", ZombieNautilus.Variant.class, new RegistryFieldRewriter<>(Registries.ZOMBIE_NAUTILUS_VARIANT, "getVariant"))
|
||||
.register("Dialog", Dialog.class, new RegistryFieldRewriter<>(Registries.DIALOG, "getDialog"))
|
||||
.register("PoiTypes", PoiTypes.class, new RegistryFieldRewriter<>(Registries.POINT_OF_INTEREST_TYPE, "get"))
|
||||
.register("MemoryKey", MemoryKey.class, new MemoryKeyRewriter())
|
||||
// .register("ItemType", org.bukkit.inventory.ItemType.class, new io.papermc.generator.rewriter.types.simple.ItemTypeRewriter()) - disable for now, lynx want the generic type
|
||||
.register("BlockType", BlockType.class, new BlockTypeRewriter())
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.papermc.generator.utils.ClassHelper;
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.entity.poi.PoiTypes;
|
||||
import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
|
||||
import io.papermc.paper.registry.data.CatTypeRegistryEntry;
|
||||
import io.papermc.paper.registry.data.ChickenVariantRegistryEntry;
|
||||
@@ -175,7 +176,8 @@ public final class RegistryEntries {
|
||||
entry(Registries.FLUID, Fluids.class, Fluid.class),
|
||||
entry(Registries.SOUND_EVENT, SoundEvents.class, Sound.class).allowDirect().apiRegistryField("SOUNDS").apiRegistryBuilder(SoundEventRegistryEntry.Builder.class, "PaperSoundEventRegistryEntry.PaperBuilder", RegistryEntry.RegistryModificationApiSupport.NONE),
|
||||
entry(Registries.DATA_COMPONENT_TYPE, DataComponents.class, DataComponentType.class, "Paper").preload(DataComponentTypes.class).apiAccessName("of"),
|
||||
entry(Registries.GAME_RULE, GameRules.class, GameRule.class).genericArgCount(1)/*.preload(org.bukkit.GameRules.class)*/ // only preload once the old names are removed
|
||||
entry(Registries.GAME_RULE, GameRules.class, GameRule.class).genericArgCount(1)/*.preload(org.bukkit.GameRules.class)*/, // only preload once the old names are removed
|
||||
entry(Registries.POINT_OF_INTEREST_TYPE, PoiTypes.class, io.papermc.paper.entity.poi.PoiType.class, "Paper").preload(io.papermc.paper.entity.poi.PoiTypes.class)
|
||||
);
|
||||
|
||||
public static final List<RegistryEntry<?>> DATA_DRIVEN = List.of(
|
||||
|
||||
@@ -15,7 +15,7 @@ val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||
|
||||
dependencies {
|
||||
mache("io.papermc:mache:26.1.2+build.1")
|
||||
paperclip("io.papermc:paperclip:3.0.3")
|
||||
paperclip("io.papermc:paperclip:3.0.4")
|
||||
}
|
||||
|
||||
paperweight {
|
||||
|
||||
@@ -23277,10 +23277,10 @@ index 1cd5901c8e4eb4114ab347a393fc37095c8642d2..fadce1c051e6c7bc0c3d041c0cc8ecd7
|
||||
+}
|
||||
diff --git a/io/papermc/paper/command/subcommands/ChunkDebugCommand.java b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9b89a6fb3
|
||||
index 0000000000000000000000000000000000000000..d86bd11e0155f767c3bf66ac05fa4acf6d2bfccb
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
||||
@@ -0,0 +1,277 @@
|
||||
@@ -0,0 +1,269 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import ca.spottedleaf.moonrise.common.util.JsonUtil;
|
||||
@@ -23301,6 +23301,8 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+import net.minecraft.world.level.chunk.LevelChunk;
|
||||
+import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -23327,44 +23329,33 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ switch (subCommand) {
|
||||
+ case "debug" -> {
|
||||
+ return switch (subCommand) {
|
||||
+ case "debug":
|
||||
+ if (args.length == 1) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, "help", "chunks");
|
||||
+ yield CommandUtil.getListMatchingLast(sender, args, "help", "chunks");
|
||||
+ }
|
||||
+ }
|
||||
+ case "holderinfo" -> {
|
||||
+ List<String> worldNames = new ArrayList<>();
|
||||
+ worldNames.add("*");
|
||||
+ for (org.bukkit.World world : Bukkit.getWorlds()) {
|
||||
+ worldNames.add(world.getKey().toString());
|
||||
+ case "chunkinfo", "holderinfo":
|
||||
+ if (args.length >= 1 && (args.length == 1 || !args[0].equals("*"))) {
|
||||
+ yield CommandUtil.getListMatchingLast(
|
||||
+ sender,
|
||||
+ args,
|
||||
+ CommandUtil.getWorldSuggestions(sender.getServer(), args.length == 1)
|
||||
+ );
|
||||
+ }
|
||||
+ if (args.length == 1) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, worldNames);
|
||||
+ }
|
||||
+ }
|
||||
+ case "chunkinfo" -> {
|
||||
+ List<String> worldNames = new ArrayList<>();
|
||||
+ worldNames.add("*");
|
||||
+ for (org.bukkit.World world : Bukkit.getWorlds()) {
|
||||
+ worldNames.add(world.getKey().toString());
|
||||
+ }
|
||||
+ if (args.length == 1) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, worldNames);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return Collections.emptyList();
|
||||
+ default:
|
||||
+ yield Collections.emptyList();
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ private void doChunkInfo(final CommandSender sender, final String[] args) {
|
||||
+ List<org.bukkit.World> worlds;
|
||||
+ List<World> worlds;
|
||||
+ if (args.length < 1 || args[0].equals("*")) {
|
||||
+ worlds = Bukkit.getWorlds();
|
||||
+ worlds = Bukkit.getServer().getWorlds();
|
||||
+ } else {
|
||||
+ worlds = new ArrayList<>(args.length);
|
||||
+ for (final String arg : args) {
|
||||
+ org.bukkit.@Nullable World world = Bukkit.getWorld(arg);
|
||||
+ @Nullable NamespacedKey key = NamespacedKey.fromString(arg);
|
||||
+ @Nullable World world = key == null ? null : sender.getServer().getWorld(key);
|
||||
+ if (world == null) {
|
||||
+ sender.sendMessage(text("World '" + arg + "' is invalid", RED));
|
||||
+ return;
|
||||
@@ -23379,7 +23370,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+ int accumulatedTicking = 0;
|
||||
+ int accumulatedEntityTicking = 0;
|
||||
+
|
||||
+ for (final org.bukkit.World bukkitWorld : worlds) {
|
||||
+ for (final World bukkitWorld : worlds) {
|
||||
+ final ServerLevel world = ((CraftWorld) bukkitWorld).getHandle();
|
||||
+
|
||||
+ int total = 0;
|
||||
@@ -23390,7 +23381,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+
|
||||
+ for (final NewChunkHolder holder : ((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolders()) {
|
||||
+ final NewChunkHolder.ChunkCompletion completion = holder.getLastChunkCompletion();
|
||||
+ final ChunkAccess chunk = completion == null ? null : completion.chunk();
|
||||
+ final @Nullable ChunkAccess chunk = completion == null ? null : completion.chunk();
|
||||
+
|
||||
+ if (!(chunk instanceof LevelChunk fullChunk)) {
|
||||
+ continue;
|
||||
@@ -23424,7 +23415,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+ accumulatedTicking += blockTicking;
|
||||
+ accumulatedEntityTicking += entityTicking;
|
||||
+
|
||||
+ sender.sendMessage(text().append(text("Chunks in ", BLUE), text(bukkitWorld.key().toString(), GREEN), text(":")));
|
||||
+ sender.sendMessage(text().append(text("Chunks in ", BLUE), text(bukkitWorld.key().asString(), GREEN), text(":")));
|
||||
+ sender.sendMessage(text().color(DARK_AQUA).append(
|
||||
+ text("Total: ", BLUE), text(total),
|
||||
+ text(" Inactive: ", BLUE), text(inactive),
|
||||
@@ -23446,13 +23437,14 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+ }
|
||||
+
|
||||
+ private void doHolderInfo(final CommandSender sender, final String[] args) {
|
||||
+ List<org.bukkit.World> worlds;
|
||||
+ List<World> worlds;
|
||||
+ if (args.length < 1 || args[0].equals("*")) {
|
||||
+ worlds = Bukkit.getWorlds();
|
||||
+ worlds = Bukkit.getServer().getWorlds();
|
||||
+ } else {
|
||||
+ worlds = new ArrayList<>(args.length);
|
||||
+ for (final String arg : args) {
|
||||
+ org.bukkit.@Nullable World world = Bukkit.getWorld(arg);
|
||||
+ @Nullable NamespacedKey key = NamespacedKey.fromString(arg);
|
||||
+ @Nullable World world = key == null ? null : sender.getServer().getWorld(key);
|
||||
+ if (world == null) {
|
||||
+ sender.sendMessage(text("World '" + arg + "' is invalid", RED));
|
||||
+ return;
|
||||
@@ -23468,7 +23460,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+ int accumulatedProtoChunk = 0;
|
||||
+ int accumulatedFullChunk = 0;
|
||||
+
|
||||
+ for (final org.bukkit.World bukkitWorld : worlds) {
|
||||
+ for (final World bukkitWorld : worlds) {
|
||||
+ final ServerLevel world = ((CraftWorld) bukkitWorld).getHandle();
|
||||
+
|
||||
+ int total = 0;
|
||||
@@ -23480,7 +23472,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+
|
||||
+ for (final NewChunkHolder holder : ((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolders()) {
|
||||
+ final NewChunkHolder.ChunkCompletion completion = holder.getLastChunkCompletion();
|
||||
+ final ChunkAccess chunk = completion == null ? null : completion.chunk();
|
||||
+ final @Nullable ChunkAccess chunk = completion == null ? null : completion.chunk();
|
||||
+
|
||||
+ ++total;
|
||||
+
|
||||
@@ -23506,7 +23498,7 @@ index 0000000000000000000000000000000000000000..09f1a74740f898559edc8892ae59aca9
|
||||
+ accumulatedProtoChunk += protoChunk;
|
||||
+ accumulatedFullChunk += fullChunk;
|
||||
+
|
||||
+ sender.sendMessage(text().append(text("Chunks in ", BLUE), text(bukkitWorld.getKey().toString(), GREEN), text(":")));
|
||||
+ sender.sendMessage(text().append(text("Chunks in ", BLUE), text(bukkitWorld.key().asString(), GREEN), text(":")));
|
||||
+ sender.sendMessage(text().color(DARK_AQUA).append(
|
||||
+ text("Total: ", BLUE), text(total),
|
||||
+ text(" Unloadable: ", BLUE), text(canUnload),
|
||||
@@ -23838,7 +23830,7 @@ index 3c1490ac7c259da04031db2f170e0c0a5f512191..470d7c770ae9d045b97e2df145cfe3cf
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf164195b730e22 100644
|
||||
index d22f55c63eb950e1b979280612eb9f155e986406..93690b360e5eb1b8d2f8ab2198aa087c9be7ffe2 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -191,7 +191,7 @@ import net.minecraft.world.scores.ScoreboardSaveData;
|
||||
@@ -23943,7 +23935,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
|
||||
public MinecraftServer(
|
||||
// CraftBukkit start
|
||||
@@ -843,7 +929,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -853,7 +939,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
level.setSpawnSettings(level.isSpawningMonsters()); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean))
|
||||
this.updateEffectiveRespawnData();
|
||||
this.forceTicks = false; // CraftBukkit
|
||||
@@ -23952,7 +23944,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
new org.bukkit.event.world.WorldLoadEvent(level.getWorld()).callEvent(); // Paper - call WorldLoadEvent
|
||||
}
|
||||
|
||||
@@ -866,6 +952,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -876,6 +962,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public abstract boolean shouldRconBroadcast();
|
||||
|
||||
public boolean saveAllChunks(final boolean silent, final boolean flush, final boolean force) {
|
||||
@@ -23964,7 +23956,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
this.scoreboard.storeToSaveDataIfDirty(this.getDataStorage().computeIfAbsent(ScoreboardSaveData.TYPE));
|
||||
boolean result = false;
|
||||
|
||||
@@ -874,7 +965,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -884,7 +975,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
LOGGER.info("Saving chunks for level '{}'/{}", level, level.dimension().identifier());
|
||||
}
|
||||
|
||||
@@ -23973,7 +23965,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
result = true;
|
||||
}
|
||||
|
||||
@@ -971,7 +1062,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -981,7 +1072,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23982,7 +23974,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND;
|
||||
|
||||
for (ServerLevel levelx : this.getAllLevels()) {
|
||||
@@ -982,17 +1073,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -992,17 +1083,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.waitUntilNextTick();
|
||||
}
|
||||
|
||||
@@ -24007,7 +23999,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
|
||||
this.isSaving = false;
|
||||
this.savedDataStorage.close();
|
||||
@@ -1013,6 +1101,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1023,6 +1111,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.services().nameToIdCache().save(false); // Paper - Perf: Async GameProfileCache saving
|
||||
}
|
||||
// Spigot end
|
||||
@@ -24022,7 +24014,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
// Paper start - Improved watchdog support - move final shutdown items here
|
||||
Util.shutdownExecutors();
|
||||
this.onServerExit();
|
||||
@@ -1107,16 +1203,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1117,16 +1213,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// execute small amounts of other tasks just in case the number of tasks we are
|
||||
// draining is large - chunk system and packet processing may be latency sensitive
|
||||
|
||||
@@ -24057,7 +24049,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
profiler.pop(); // moonrise:run_all_chunk
|
||||
profiler.pop(); // moonrise:run_all_tasks
|
||||
|
||||
@@ -1417,6 +1528,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1427,6 +1538,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
private boolean pollTaskInternal() {
|
||||
if (super.pollTask()) {
|
||||
@@ -24065,7 +24057,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
return true;
|
||||
} else {
|
||||
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
@@ -1558,6 +1670,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1568,6 +1680,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Paper - improve tick loop - moved into runAllTasksAtTickStart
|
||||
this.runAllTasksAtTickStart(); // Paper - improve tick loop
|
||||
this.tickServer(sprinting ? () -> false : this::haveTime);
|
||||
@@ -24079,7 +24071,7 @@ index ceb6d955ef275802e549fb9d3e653cc3dda92dad..b4bd3b788a86458ece580693baf16419
|
||||
this.tickFrame.end();
|
||||
this.recordEndOfTick(); // Paper - improve tick loop
|
||||
profiler.pop();
|
||||
@@ -2600,6 +2719,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2618,6 +2737,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26479,7 +26471,7 @@ index 045d4b0ab26622e2763d1583e1e8fcb83ba44427..ddffd36d8213a40dc3f6cbb0ef0f33a0
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 319335341617051c5b78578465f2224f78c3ea3d..fcb23814c2539f4e31ed5191e03cc28f4e7f9c2d 100644
|
||||
index bf8496c8cadb29db9c46015e202e7d59e2ed2f5e..f4e033fb5e5b116245dd4a381366c4e749a73f93 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -54,7 +54,7 @@ import net.minecraft.world.level.storage.SavedDataStorage;
|
||||
@@ -27004,7 +26996,7 @@ index de75dda2e6f17f0ae6e7f6a5620fd3eac9d389e5..6774d12d04fa848624fb8bf7a3c2b8bc
|
||||
List<Entity> passengers = this.entity.getPassengers();
|
||||
if (!passengers.equals(this.lastPassengers)) {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f4597103e7a111 100644
|
||||
index f39d48821d728232472ebc5bd6868e6a0d644721..91d27b90a9c9c348d3f93624ff8dbff8a70f522c 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -182,7 +182,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||
@@ -27025,7 +27017,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
private final GameEventDispatcher gameEventDispatcher;
|
||||
public boolean noSave;
|
||||
private final SleepStatus sleepStatus;
|
||||
@@ -275,12 +275,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -276,12 +276,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
public final void loadChunksForMoveAsync(AABB box, ca.spottedleaf.concurrentutil.util.Priority priority,
|
||||
java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
|
||||
@@ -27039,7 +27031,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
int minBlockX = Mth.floor(box.minX - 1.0E-7) - 3;
|
||||
int minBlockZ = Mth.floor(box.minZ - 1.0E-7) - 3;
|
||||
|
||||
@@ -299,30 +294,171 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -300,30 +295,171 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
public final void loadChunks(int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ,
|
||||
ca.spottedleaf.concurrentutil.util.Priority priority,
|
||||
java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
|
||||
@@ -27227,7 +27219,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,16 +472,135 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -337,16 +473,135 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27370,7 +27362,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
|
||||
public ServerLevel(
|
||||
final MinecraftServer server,
|
||||
@@ -409,18 +664,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -416,18 +671,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// CraftBukkit end
|
||||
boolean syncWrites = server.forceSynchronousWrites();
|
||||
DataFixer fixerUpper = server.getFixerUpper();
|
||||
@@ -27390,7 +27382,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
this.chunkSource = new ServerChunkCache(
|
||||
this,
|
||||
levelStorage,
|
||||
@@ -431,7 +675,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -438,7 +682,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.spigotConfig.viewDistance, // Spigot
|
||||
this.spigotConfig.simulationDistance, // Spigot
|
||||
syncWrites,
|
||||
@@ -27399,7 +27391,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
() -> server.overworld().getDataStorage()
|
||||
, savedDataStorage // Paper - initialize SavedDataStorage earlier
|
||||
);
|
||||
@@ -471,6 +715,20 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -478,6 +722,20 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.waypointManager = new ServerWaypointManager(this); // Paper - optimize ServerWaypointManager with locator bar disabled
|
||||
this.environmentAttributes = EnvironmentAttributeSystem.builder().addDefaultLayers(this).build();
|
||||
this.updateSkyBrightness();
|
||||
@@ -27420,7 +27412,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
}
|
||||
|
||||
@@ -607,8 +865,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -614,8 +872,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
profiler.push("checkDespawn");
|
||||
entity.checkDespawn();
|
||||
profiler.pop();
|
||||
@@ -27430,7 +27422,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
Entity vehicle = entity.getVehicle();
|
||||
if (vehicle != null) {
|
||||
if (!vehicle.isRemoved() && vehicle.hasPassenger(entity)) {
|
||||
@@ -632,7 +889,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -642,7 +899,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
profiler.push("entityManagement");
|
||||
@@ -27439,7 +27431,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
profiler.pop();
|
||||
profiler.push("debugSynchronizers");
|
||||
if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) {
|
||||
@@ -649,7 +906,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -659,7 +916,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
@Override
|
||||
public boolean shouldTickBlocksAt(final long chunkPos) {
|
||||
@@ -27451,7 +27443,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
protected void tickTime() {
|
||||
@@ -673,7 +933,60 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -683,7 +943,60 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList()).forEach(player -> player.stopSleepInBed(false, false));
|
||||
}
|
||||
|
||||
@@ -27512,7 +27504,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
int minX = chunkPos.getMinBlockX();
|
||||
int minZ = chunkPos.getMinBlockZ();
|
||||
@@ -682,7 +995,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -692,7 +1005,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
|
||||
for (int i = 0; i < tickSpeed; i++) {
|
||||
@@ -27521,7 +27513,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
this.tickPrecipitation(this.getBlockRandomPos(minX, 0, minZ, 15));
|
||||
}
|
||||
}
|
||||
@@ -690,31 +1003,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -700,31 +1013,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
profiler.popPush("tickBlocks");
|
||||
if (tickSpeed > 0) {
|
||||
@@ -27554,7 +27546,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
@@ -1037,6 +1326,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1047,6 +1336,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
if (fluidState.is(type)) {
|
||||
fluidState.tick(this, pos, blockState);
|
||||
}
|
||||
@@ -27567,7 +27559,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
private void tickBlock(final BlockPos pos, final Block type) {
|
||||
@@ -1044,6 +1339,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1054,6 +1349,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
if (state.is(type)) {
|
||||
state.tick(this, pos, this.random);
|
||||
}
|
||||
@@ -27580,7 +27572,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
// Paper start - log detailed entity tick information
|
||||
@@ -1128,6 +1429,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1138,6 +1439,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
public void save(final @Nullable ProgressListener progressListener, final boolean flush, final boolean noSave) {
|
||||
@@ -27592,7 +27584,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
ServerChunkCache chunkSource = this.getChunkSource();
|
||||
if (!noSave) {
|
||||
new org.bukkit.event.world.WorldSaveEvent(this.getWorld()).callEvent(); // CraftBukkit
|
||||
@@ -1140,13 +1446,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1150,13 +1456,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
progressListener.progressStage(Component.translatable("menu.savingChunks"));
|
||||
}
|
||||
|
||||
@@ -27616,7 +27608,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
private void saveLevelData(final boolean sync) {
|
||||
@@ -1267,7 +1578,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1277,7 +1588,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.removePlayerImmediately((ServerPlayer)existing, Entity.RemovalReason.DISCARDED);
|
||||
}
|
||||
|
||||
@@ -27625,7 +27617,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -1298,7 +1609,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1308,7 +1619,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -27634,7 +27626,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1309,7 +1620,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1319,7 +1630,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
public boolean tryAddFreshEntityWithPassengers(final Entity entity, final org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
// CraftBukkit end
|
||||
@@ -27643,7 +27635,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
return false;
|
||||
} else {
|
||||
this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
|
||||
@@ -2103,7 +2414,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2112,7 +2423,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27652,7 +27644,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
output.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size()));
|
||||
output.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count()));
|
||||
output.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count()));
|
||||
@@ -2121,13 +2432,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2130,13 +2441,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
Path chunks = rootDir.resolve("chunks.csv");
|
||||
|
||||
try (Writer output = Files.newBufferedWriter(chunks)) {
|
||||
@@ -27668,7 +27660,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
Path entities = rootDir.resolve("entities.csv");
|
||||
@@ -2222,8 +2533,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2231,8 +2542,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
Locale.ROOT,
|
||||
"players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s",
|
||||
this.players.size(),
|
||||
@@ -27679,7 +27671,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
this.blockEntityTickers.size(),
|
||||
getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType),
|
||||
this.getBlockTicks().count(),
|
||||
@@ -2256,15 +2567,25 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2265,15 +2576,25 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
|
||||
@@ -27708,7 +27700,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
public void startTickingChunk(final LevelChunk levelChunk) {
|
||||
@@ -2281,8 +2602,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2290,8 +2611,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
public void waitForEntities(final ChunkPos centerChunk, final int radius) {
|
||||
List<ChunkPos> chunks = ChunkPos.rangeClosed(centerChunk, radius).toList();
|
||||
@@ -27719,7 +27711,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
|
||||
for (ChunkPos chunk : chunks) {
|
||||
if (!this.areEntitiesLoaded(chunk.pack())) {
|
||||
@@ -2303,28 +2624,38 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2312,28 +2633,38 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
@@ -27764,7 +27756,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
public boolean anyPlayerCloseEnoughForSpawning(final BlockPos pos) {
|
||||
@@ -2341,7 +2672,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2350,7 +2681,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
public boolean canSpawnEntitiesInChunk(final ChunkPos pos) {
|
||||
@@ -27776,7 +27768,7 @@ index bc545cb3fc519aa1f5136e420264fea2239fc4c1..3cd2fcc38f3989bb5124ba5bc2f45971
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2389,7 +2723,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2398,7 +2732,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
public CrashReportCategory fillReportDetails(final CrashReport report) {
|
||||
CrashReportCategory category = super.fillReportDetails(report);
|
||||
WeatherData weatherData = this.getWeatherData();
|
||||
@@ -28487,11 +28479,11 @@ index 83af9ee3ba150da85b9b694cd76a5fabb5b2d8ef..1fb40837bd02672850ec9adc2797190d
|
||||
PrepareSpawnTask.this.loadListener.updateFocus(this.spawnLevel.dimension(), spawnChunk);
|
||||
}
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 0c4de29676732f5e84d7584e1f89d508addc1cc4..0613b053f4a75c0884280011ee092d9d108b3857 100644
|
||||
index eff42b94fd182abace988d9649952e04dc35b268..02605ebe6ef10727badadbf7fc4cec52583df965 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -983,8 +983,8 @@ public abstract class PlayerList {
|
||||
player.connection.send(this.server.clockManager().createFullSyncPacket());
|
||||
@@ -982,8 +982,8 @@ public abstract class PlayerList {
|
||||
player.connection.send(level.clockManager().createFullSyncPacket(player)); // Paper - per-world time; per-player time
|
||||
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getRespawnData()));
|
||||
// Paper start - view distances
|
||||
- player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level)));
|
||||
@@ -28501,7 +28493,7 @@ index 0c4de29676732f5e84d7584e1f89d508addc1cc4..0613b053f4a75c0884280011ee092d9d
|
||||
// Paper end - view distances
|
||||
if (level.isRaining()) {
|
||||
// CraftBukkit start - handle player weather
|
||||
@@ -1201,7 +1201,7 @@ public abstract class PlayerList {
|
||||
@@ -1200,7 +1200,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setViewDistance(final int viewDistance) {
|
||||
this.viewDistance = viewDistance;
|
||||
@@ -28510,7 +28502,7 @@ index 0c4de29676732f5e84d7584e1f89d508addc1cc4..0613b053f4a75c0884280011ee092d9d
|
||||
|
||||
for (ServerLevel level : this.server.getAllLevels()) {
|
||||
level.getChunkSource().setViewDistance(viewDistance);
|
||||
@@ -1210,7 +1210,7 @@ public abstract class PlayerList {
|
||||
@@ -1209,7 +1209,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setSimulationDistance(final int simulationDistance) {
|
||||
this.simulationDistance = simulationDistance;
|
||||
@@ -28893,7 +28885,7 @@ index 1ceb7e4a3abd4d9de5133d182d3267d2164918f6..eb2fa32cff6824c14f865c8731df7d08
|
||||
+ // Paper end - block counting
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e3980bced 100644
|
||||
index 29896cb17fcf8ab967a937e9b0e102a8354b6889..e087d5596979044fe7fbcf7f2cccdae4e81a3d3a 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -167,7 +167,7 @@ public abstract class Entity
|
||||
@@ -29366,7 +29358,7 @@ index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e
|
||||
}
|
||||
|
||||
public InteractionResult interact(final Player player, final InteractionHand hand, final Vec3 location) {
|
||||
@@ -4364,15 +4601,17 @@ public abstract class Entity
|
||||
@@ -4363,15 +4600,17 @@ public abstract class Entity
|
||||
}
|
||||
|
||||
public Iterable<Entity> getIndirectPassengers() {
|
||||
@@ -29392,7 +29384,7 @@ index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e
|
||||
}
|
||||
|
||||
public int countPlayerPassengers() {
|
||||
@@ -4683,6 +4922,15 @@ public abstract class Entity
|
||||
@@ -4682,6 +4921,15 @@ public abstract class Entity
|
||||
}
|
||||
|
||||
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
|
||||
@@ -29408,7 +29400,7 @@ index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e
|
||||
if (!checkPosition(this, x, y, z)) {
|
||||
return;
|
||||
}
|
||||
@@ -4832,6 +5080,12 @@ public abstract class Entity
|
||||
@@ -4831,6 +5079,12 @@ public abstract class Entity
|
||||
|
||||
@Override
|
||||
public final void setRemoved(final Entity.RemovalReason reason, org.bukkit.event.entity.EntityRemoveEvent.@Nullable Cause cause) { // CraftBukkit - add Bukkit remove cause
|
||||
@@ -29421,7 +29413,7 @@ index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
|
||||
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
|
||||
if (this.removalReason == null) {
|
||||
@@ -4842,7 +5096,7 @@ public abstract class Entity
|
||||
@@ -4841,7 +5095,7 @@ public abstract class Entity
|
||||
this.stopRiding();
|
||||
}
|
||||
|
||||
@@ -29430,7 +29422,7 @@ index 3d7bc43e3e367a2328601ac6b74f99361b4be57e..f7b4da570ee28b7128b4d2cd1c67b89e
|
||||
this.levelCallback.onRemove(reason);
|
||||
this.onRemoval(reason);
|
||||
// Paper start - Folia schedulers
|
||||
@@ -4876,7 +5130,7 @@ public abstract class Entity
|
||||
@@ -4875,7 +5129,7 @@ public abstract class Entity
|
||||
public boolean shouldBeSaved() {
|
||||
return (this.removalReason == null || this.removalReason.shouldSave())
|
||||
&& !this.isPassenger()
|
||||
@@ -30053,7 +30045,7 @@ index e07a7bda45146686a6ac2d20507df9fc8630514f..f84e651e2a34e76a0a71993332e4be1b
|
||||
|
||||
// Paper start - Affects Spawning API
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003ef8bb694 100644
|
||||
index 838bad640b7f8e42fc8972918cfc7c1d9807e2b3..c0f901c4ac61a0aa2b480f102feb3669b111f4c0 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -87,6 +87,7 @@ import net.minecraft.world.level.storage.LevelData;
|
||||
@@ -30725,10 +30717,10 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
+ this.maxSectionY = this.maxY >> 4;
|
||||
+ this.sectionsCount = this.maxSectionY - this.minSectionY + 1;
|
||||
+ // Paper end - getblock optimisations - cache world height/sections
|
||||
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, CraftNamespacedKey.fromMinecraft(dimension.identifier())); // Spigot
|
||||
final org.bukkit.NamespacedKey worldKey = CraftNamespacedKey.fromMinecraft(dimension.identifier()); // Paper
|
||||
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, worldKey); // Spigot
|
||||
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
|
||||
this.generator = generator;
|
||||
@@ -230,6 +863,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -231,6 +864,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.registryAccess = registryAccess;
|
||||
this.palettedContainerFactory = PalettedContainerFactory.create(registryAccess);
|
||||
this.damageSources = new DamageSources(registryAccess);
|
||||
@@ -30736,7 +30728,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
}
|
||||
|
||||
// Paper start - Cancel hit for vanished players
|
||||
@@ -511,7 +1145,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -512,7 +1146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.setBlocksDirty(pos, blockState, blockState1);
|
||||
}
|
||||
|
||||
@@ -30745,7 +30737,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
this.sendBlockUpdated(pos, blockState, state, flags);
|
||||
}
|
||||
|
||||
@@ -844,6 +1478,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -846,6 +1480,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// Paper - Fix MC-117075 use removeAll - remove iterator in favour of indexed for loop, ensuring compile error if something uses iter incorrectly
|
||||
boolean tickBlockEntities = this.tickRateManager().runsNormally();
|
||||
|
||||
@@ -30753,7 +30745,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
// Paper start - Fix MC-117075 use removeAll
|
||||
final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<@Nullable TickingBlockEntity> toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>();
|
||||
toRemove.add(null);
|
||||
@@ -854,6 +1489,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -856,6 +1491,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
toRemove.add(ticker); // Paper - Fix MC-117075 use removeAll
|
||||
} else if (tickBlockEntities && this.shouldTickBlocksAt(ticker.getPos())) {
|
||||
ticker.tick();
|
||||
@@ -30765,7 +30757,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,6 +1513,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -874,6 +1514,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
// Paper end - Prevent block entity and entity crashes
|
||||
}
|
||||
@@ -30773,7 +30765,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
}
|
||||
|
||||
// Paper start - Option to prevent armor stands from doing entity lookups
|
||||
@@ -880,7 +1521,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -881,7 +1522,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean noCollision(@Nullable Entity entity, AABB box) {
|
||||
if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups)
|
||||
return false;
|
||||
@@ -30789,7 +30781,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
}
|
||||
// Paper end - Option to prevent armor stands from doing entity lookups
|
||||
|
||||
@@ -1025,7 +1673,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -1026,7 +1674,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (!this.isInValidBounds(pos)) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -30798,7 +30790,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
? null
|
||||
: this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE);
|
||||
}
|
||||
@@ -1105,20 +1753,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -1106,20 +1754,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@Override
|
||||
public List<Entity> getEntities(final @Nullable Entity except, final AABB bb, final Predicate<? super Entity> selector) {
|
||||
Profiler.get().incrementCounter("getEntities");
|
||||
@@ -30826,7 +30818,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1134,33 +1777,94 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -1135,33 +1778,94 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.getEntities(type, bb, selector, output, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@@ -30941,7 +30933,7 @@ index 81c3f9f04040b6cfa014ce55e517bd9b374ec252..0958fe0438c3e934b885acf78a0f8003
|
||||
|
||||
public <T extends Entity> boolean hasEntities(final EntityTypeTest<Entity, T> type, final AABB bb, final Predicate<? super T> selector) {
|
||||
Profiler.get().incrementCounter("hasEntities");
|
||||
@@ -1465,13 +2169,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -1466,13 +2170,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
// Paper start - allow patching this logic
|
||||
public final int getEntityCount() {
|
||||
@@ -32693,7 +32685,7 @@ index 54d57f80b1cca351cac2aa59477a0e57334816e7..94652b00e18ffcbe02f1ad0578d671e2
|
||||
public @Nullable BlockEntity getBlockEntity(final BlockPos pos) {
|
||||
return this.wrapped.getBlockEntity(pos);
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 1bbb8ca0c4a5087cf35c8af8362d867ef868cbd3..b5b514b292f9fdbe410aba5facec1638682c9075 100644
|
||||
index d747e7058f78ac1fd02f3dc8e06670ed484cd42b..c0c212fd50cf97ae311035b370e8b4d40d82229e 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -64,7 +64,7 @@ import net.minecraft.world.ticks.TickContainerAccess;
|
||||
@@ -33593,7 +33585,7 @@ index cc5d366f7b485f98901572b1aaf57d8b650d521f..7adb4be57bd9fdc9980b5b7e91e9d9ca
|
||||
private final Long2ObjectLinkedOpenHashMap<CompletableFuture<BitSet>> regionCacheForBlender = new Long2ObjectLinkedOpenHashMap<>();
|
||||
private static final int REGION_CACHE_SIZE = 1024;
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 728ec122b7af090427cc7511a168336d539835a1..5149635679ec03d881e63effbd79fc193d7e52c8 100644
|
||||
index 9409cc5c8dbd12ce6bdf34843da70170ebce41bd..c9acbdce97cb605a45124bb9d3944070396adc03 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
@@ -33625,7 +33617,7 @@ index 728ec122b7af090427cc7511a168336d539835a1..5149635679ec03d881e63effbd79fc19
|
||||
+ // Paper end - rewrite chunk system
|
||||
+
|
||||
public RegionFile(final RegionStorageInfo info, final Path path, final Path externalFileDir, final boolean sync) throws IOException {
|
||||
this(info, path, externalFileDir, RegionFileVersion.getCompressionFormat(), sync); // Paper - Configurable region compression format
|
||||
this(info, path, externalFileDir, RegionFileVersion.getSelected(), sync);
|
||||
}
|
||||
@@ -201,6 +216,15 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
|
||||
@@ -33491,7 +33491,7 @@ index 109d7b563ee799d998a5773c5a36e61ca3607d46..747755082639436731989d3ee4b3c30a
|
||||
return structureTemplate.save(new CompoundTag());
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 1b064f00c33712c3d2d85ed8520f1eda02abfbf9..65a971379f35c4b1b519b93787f690d891e29523 100644
|
||||
index e11862c7e0617acfb36212cfe349bdade3a5164b..7ae2d491a3b2f379df99ccc649b8bb8cbf2304b9 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -299,6 +299,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
+13
-12
@@ -28,7 +28,7 @@ and then catch exceptions and close if they fire.
|
||||
Part of this commit was authored by: Spottedleaf, sandtechnology
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6b33beff8 100644
|
||||
index 1511cbd2e6123a00d22694353ee4989d539fe0f0..104976b3eb04d80e5be5bd020cf16c647b1cde27 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -65,7 +65,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -40,7 +40,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
public Channel channel;
|
||||
public SocketAddress address;
|
||||
// Spigot start
|
||||
@@ -123,6 +123,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -124,6 +124,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public boolean handledLegacyLoginEvent; // Paper - playerloginevent
|
||||
public net.minecraft.server.level.@Nullable ServerPlayer savedPlayerForLegacyEvents; // Paper - playerloginevent & PlayerSpawnLocationEvent
|
||||
public org.bukkit.event.player.PlayerResourcePackStatusEvent.@Nullable Status resourcePackStatus; // Paper
|
||||
@@ -51,7 +51,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
|
||||
public Connection(final PacketFlow receiving) {
|
||||
this.receiving = receiving;
|
||||
@@ -393,11 +397,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -394,11 +398,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void send(final Packet<?> packet, final @Nullable ChannelFutureListener listener, final boolean flush) {
|
||||
@@ -93,7 +93,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +437,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -407,7 +438,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
this.flushQueue();
|
||||
action.accept(this);
|
||||
} else {
|
||||
@@ -102,7 +102,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,21 +451,41 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -421,21 +452,42 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
private void doSendPacket(final Packet<?> packet, final @Nullable ChannelFutureListener listener, final boolean flush) {
|
||||
@@ -133,7 +133,8 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
+ }
|
||||
+ } catch (final Exception e) {
|
||||
+ LOGGER.error("NetworkException: {}", player, e);
|
||||
+ this.disconnect(Component.translatable("disconnect.genericReason", "Internal Exception: " + e.getMessage()));
|
||||
+ Component reason = Component.translatable("disconnect.genericReason", "Internal Exception: " + e.getMessage());
|
||||
+ this.send(new ClientboundDisconnectPacket(reason), PacketSendListener.thenRun(() -> this.disconnect(reason)));
|
||||
+ packet.onPacketDispatchFinish(player, null);
|
||||
}
|
||||
+ // Paper end - Optimize network
|
||||
@@ -148,7 +149,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,16 +497,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -447,16 +499,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +212,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
|
||||
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
|
||||
private static int joinAttemptsThisTick; // Paper - Buffer joins to world
|
||||
@@ -525,6 +617,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -526,6 +619,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
public void disconnect(final DisconnectionDetails details) {
|
||||
this.preparing = false; // Spigot
|
||||
@@ -219,7 +220,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
if (this.channel == null) {
|
||||
this.delayedDisconnect = details;
|
||||
}
|
||||
@@ -714,7 +807,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -715,7 +809,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public void handleDisconnection() {
|
||||
if (this.channel != null && !this.channel.isOpen()) {
|
||||
if (this.disconnectionHandled) {
|
||||
@@ -228,7 +229,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
} else {
|
||||
this.disconnectionHandled = true;
|
||||
PacketListener packetListener = this.getPacketListener();
|
||||
@@ -725,7 +818,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -726,7 +820,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
);
|
||||
disconnectListener.onDisconnect(details);
|
||||
}
|
||||
@@ -237,7 +238,7 @@ index 0bc6ab5e498f82c5b3cbdf8dddfed6c8406ad511..9cd6ec17981da310be1d35054af080d6
|
||||
// Paper start - Add PlayerConnectionCloseEvent
|
||||
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
|
||||
/* Player was logged in, either game listener or configuration listener */
|
||||
@@ -760,4 +853,96 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -761,4 +855,96 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public void setBandwidthLogger(final LocalSampleLogger bandwidthLogger) {
|
||||
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwidthLogger);
|
||||
}
|
||||
@@ -371,7 +372,7 @@ index 1480d0db90f5797e3dee19503e52d1e783493ac3..bd76e55ea56dd7c1e232806d1d13a747
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerConnectionListener.java b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index b0445b4ad9adb6d2dec08537559d2ed243ca69bb..b266e4f7b437578356568d86910e3b428ee66523 100644
|
||||
index 387ac8a4e67ef07df73ce98d0add0937314ee497..9ae7c79e5088d9e1e3fb7e0dca00bb15fee118b6 100644
|
||||
--- a/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -52,11 +52,13 @@ public class ServerConnectionListener {
|
||||
|
||||
@@ -354,10 +354,10 @@ index 0000000000000000000000000000000000000000..ce6b57eeeeb1bd652f4bb53c19dcfbc0
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 3cd2fcc38f3989bb5124ba5bc2f4597103e7a111..6d847ff3646b27fe9bc75e792d813a7f611ab3e5 100644
|
||||
index 91d27b90a9c9c348d3f93624ff8dbff8a70f522c..f4bbccee849ee3711a3b838884e4bcf4e24da039 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -857,6 +857,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -864,6 +864,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ index 3cd2fcc38f3989bb5124ba5bc2f4597103e7a111..6d847ff3646b27fe9bc75e792d813a7f
|
||||
this.entityTickList
|
||||
.forEach(
|
||||
entity -> {
|
||||
@@ -1373,12 +1374,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1383,12 +1384,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
entity.totalEntityAge++; // Paper - age-like counter for all entities
|
||||
profiler.push(entity.typeHolder()::getRegisteredName);
|
||||
profiler.incrementCounter("tickNonPassenger");
|
||||
@@ -382,7 +382,7 @@ index 3cd2fcc38f3989bb5124ba5bc2f4597103e7a111..6d847ff3646b27fe9bc75e792d813a7f
|
||||
}
|
||||
// Paper start - log detailed entity tick information
|
||||
} finally {
|
||||
@@ -1389,7 +1393,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1399,7 +1403,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// Paper end - log detailed entity tick information
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ index 3cd2fcc38f3989bb5124ba5bc2f4597103e7a111..6d847ff3646b27fe9bc75e792d813a7f
|
||||
if (entity.isRemoved() || entity.getVehicle() != vehicle) {
|
||||
entity.stopRiding();
|
||||
} else if (entity instanceof Player || this.entityTickList.contains(entity)) {
|
||||
@@ -1399,12 +1403,21 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1409,12 +1413,21 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push(entity.typeHolder()::getRegisteredName);
|
||||
profiler.incrementCounter("tickPassenger");
|
||||
@@ -462,7 +462,7 @@ index 0df8332933203a904bd9ef9efb3c9bce21e65441..1a502cbd8acea9420fa6dd8d716018b5
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index f7b4da570ee28b7128b4d2cd1c67b89e3980bced..93d3fb313d538cc1067b1db010458169a1320122 100644
|
||||
index e087d5596979044fe7fbcf7f2cccdae4e81a3d3a..fea6c3b48c4eb162fbdc099fa775bc3161a4dd4e 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -382,6 +382,15 @@ public abstract class Entity
|
||||
@@ -521,10 +521,10 @@ index f7b4da570ee28b7128b4d2cd1c67b89e3980bced..93d3fb313d538cc1067b1db010458169
|
||||
delta = this.maybeBackOffFromEdge(delta, moverType);
|
||||
Vec3 movement = this.collide(delta);
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index c4da41f3b5ba6d8492d3776654b1ce62a5015895..6a0ebbdfcc0bc07915574c1cf87463e82213ca7e 100644
|
||||
index 8b0abe9c7a3907419f6e4d55ea22fb9bc749f28b..36c0081e3e8f8776293ae619156cd0828fe5b21d 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3385,6 +3385,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
@@ -3372,6 +3372,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
protected void playAttackSound() {
|
||||
}
|
||||
|
||||
@@ -540,10 +540,10 @@ index c4da41f3b5ba6d8492d3776654b1ce62a5015895..6a0ebbdfcc0bc07915574c1cf87463e8
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index c7c53ef16e104ebc48aeb8719783fb4c45d39fc2..90eaa775dc134041647618c3b965334a9bb9fd3b 100644
|
||||
index c7c53ef16e104ebc48aeb8719783fb4c45d39fc2..5bbb5cbb51953399c7bce547cd6968eb3c6bd130 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -211,6 +211,19 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
@@ -211,6 +211,20 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
return this.lookControl;
|
||||
}
|
||||
|
||||
@@ -551,6 +551,7 @@ index c7c53ef16e104ebc48aeb8719783fb4c45d39fc2..90eaa775dc134041647618c3b965334a
|
||||
+ @Override
|
||||
+ public void inactiveTick() {
|
||||
+ super.inactiveTick();
|
||||
+ if (!this.aware) return; // Paper - Do not tick AI for inactive unaware mobs
|
||||
+ if (this.goalSelector.inactiveTick()) {
|
||||
+ this.goalSelector.tick();
|
||||
+ }
|
||||
@@ -673,7 +674,7 @@ index c482c3348267ca2b88109e34291aa860e0cde916..b11b59d80e37d272770ab51a63028fdd
|
||||
public void tick() {
|
||||
if (this.getItem().isEmpty()) {
|
||||
diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
index a80e6a23cf29cb44943339101f15565dbc19af1f..f481fd661440f77c98940cbde4a8b95818e4a22c 100644
|
||||
index a80e6a23cf29cb44943339101f15565dbc19af1f..26108ac0543c7b4195f149c07d8348b5b15b8bdb 100644
|
||||
--- a/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
@@ -244,11 +244,35 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
||||
@@ -687,7 +688,7 @@ index a80e6a23cf29cb44943339101f15565dbc19af1f..f481fd661440f77c98940cbde4a8b958
|
||||
+ if (this.getUnhappyCounter() > 0) {
|
||||
+ this.setUnhappyCounter(this.getUnhappyCounter() - 1);
|
||||
+ }
|
||||
+ if (this.isEffectiveAi()) {
|
||||
+ if (this.aware && this.isEffectiveAi()) { // Paper - Do not tick AI for inactive unaware mobs
|
||||
+ if (this.level().spigotConfig.tickInactiveVillagers) {
|
||||
+ this.customServerAiStep(this.level().getMinecraftWorld());
|
||||
+ } else {
|
||||
@@ -816,7 +817,7 @@ index 3a590d4dc980a2912e9cc043d8c8db4cf9d60803..06ab7c48b18c03af494ab10fc2b584ce
|
||||
+
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 0958fe0438c3e934b885acf78a0f8003ef8bb694..31c7223d2d01573c24d4ad83737fa2c2752db028 100644
|
||||
index c0f901c4ac61a0aa2b480f102feb3669b111f4c0..07c301ba02c7f2c032a29a0ae3bdf95fc522c03b 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -155,6 +155,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
|
||||
+6
-6
@@ -266,10 +266,10 @@ index 319325e741cc314b84844bb49ea569aaf014f319..20b5cfe1ce36d74cd6b2f95566a1bc34
|
||||
+ // Paper end - Use Velocity cipher
|
||||
}
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 9cd6ec17981da310be1d35054af080d6b33beff8..d7ed1621709c491525daaf7adc8e9f0d781c93e1 100644
|
||||
index 104976b3eb04d80e5be5bd020cf16c647b1cde27..5a23f95aff982ecc58d2e2bc994f4e495285069c 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -738,11 +738,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -740,11 +740,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ index 9cd6ec17981da310be1d35054af080d6b33beff8..d7ed1621709c491525daaf7adc8e9f0d
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return this.encrypted;
|
||||
@@ -780,16 +791,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -782,16 +793,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
public void setupCompression(final int threshold, final boolean validateDecompressed) {
|
||||
if (threshold >= 0) {
|
||||
@@ -318,7 +318,7 @@ index 9cd6ec17981da310be1d35054af080d6b33beff8..d7ed1621709c491525daaf7adc8e9f0d
|
||||
this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper - Add Channel initialization listeners
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/network/ServerConnectionListener.java b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index b266e4f7b437578356568d86910e3b428ee66523..0b57e3bcd0319e4e9571fddbcb85db5a3105b8b2 100644
|
||||
index 391435cf3d279c8f5a889702b50f57626864c7bb..19a77c8269c3f1998985d533d9099c7e6cf76af4 100644
|
||||
--- a/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -77,6 +77,10 @@ public class ServerConnectionListener {
|
||||
@@ -333,10 +333,10 @@ index b266e4f7b437578356568d86910e3b428ee66523..0b57e3bcd0319e4e9571fddbcb85db5a
|
||||
.add(
|
||||
new ServerBootstrap()
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 8203765d5570644b4c8f6790f361bca2c7066b25..718f00ad9c587a4b0c12f351c10d462113f16ac3 100644
|
||||
index c1edad046cbdd1627edba58bc06aef5c058e79eb..3a0d47a716ce5c5345640ed67ac306101791892b 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -245,11 +245,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@@ -251,11 +251,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
}
|
||||
|
||||
SecretKey secretKey = packet.getSecretKey(serverPrivateKey);
|
||||
|
||||
@@ -9,7 +9,7 @@ creating too large of a packet to sed.
|
||||
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
|
||||
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
index 2bfc4cb47fc51345fc733b6ab3b19ace4f8bc171..dad2b89355b05900251955d015451fe195bfdb49 100644
|
||||
index 6ecda939755534ce0f35680be16a04c0a0e0a312..488d5654f5414c9950f19e86a791507366366e01 100644
|
||||
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
@@ -32,6 +32,14 @@ public class ClientboundLevelChunkPacketData {
|
||||
|
||||
@@ -19,12 +19,14 @@ Co-authored-by: egg82 <eggys82@gmail.com>
|
||||
|
||||
diff --git a/io/papermc/paper/redstone/RedstoneWireTurbo.java b/io/papermc/paper/redstone/RedstoneWireTurbo.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ff747a1ecdf3c888bca0d69de4f85dcd810b6139
|
||||
index 0000000000000000000000000000000000000000..8e03419df1469c6fecfaa82fcb319a58635b39f3
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/redstone/RedstoneWireTurbo.java
|
||||
@@ -0,0 +1,954 @@
|
||||
@@ -0,0 +1,949 @@
|
||||
+package io.papermc.paper.redstone;
|
||||
+
|
||||
+import com.google.common.collect.Lists;
|
||||
+import com.google.common.collect.Maps;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.concurrent.ThreadLocalRandom;
|
||||
@@ -36,11 +38,7 @@ index 0000000000000000000000000000000000000000..ff747a1ecdf3c888bca0d69de4f85dcd
|
||||
+import net.minecraft.world.level.block.Block;
|
||||
+import net.minecraft.world.level.block.RedStoneWireBlock;
|
||||
+import net.minecraft.world.level.block.state.BlockState;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.event.block.BlockRedstoneEvent;
|
||||
+
|
||||
+import com.google.common.collect.Lists;
|
||||
+import com.google.common.collect.Maps;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+
|
||||
+public final class RedstoneWireTurbo {
|
||||
+ /*
|
||||
@@ -914,12 +912,9 @@ index 0000000000000000000000000000000000000000..ff747a1ecdf3c888bca0d69de4f85dcd
|
||||
+ // always be in the range of 0 to 15, the following if will correct that.
|
||||
+ if (k > j) j = k;
|
||||
+
|
||||
+ // egg82's amendment
|
||||
+ // Adding Bukkit's BlockRedstoneEvent - er.. event.
|
||||
+ // [egg82] Adding Bukkit's BlockRedstoneEvent.
|
||||
+ if (i != j) {
|
||||
+ BlockRedstoneEvent event = new BlockRedstoneEvent(CraftBlock.at(worldIn, upd.self), i, j);
|
||||
+ worldIn.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ j = event.getNewCurrent();
|
||||
+ j = CraftEventFactory.callRedstoneChange(worldIn, upd.self, i, j).getNewCurrent();
|
||||
+ }
|
||||
+
|
||||
+ if (i != j) {
|
||||
@@ -978,10 +973,10 @@ index 0000000000000000000000000000000000000000..ff747a1ecdf3c888bca0d69de4f85dcd
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec43794be07d7e 100644
|
||||
index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a00002774755eb90a0b772fe742b30a5e09452cf 100644
|
||||
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -269,6 +269,60 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -269,6 +269,56 @@ public class RedStoneWireBlock extends Block {
|
||||
return relativeState.isFaceSturdy(level, relativePos, Direction.UP) || relativeState.is(Blocks.HOPPER);
|
||||
}
|
||||
|
||||
@@ -1021,12 +1016,8 @@ index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec4379
|
||||
+ int oldPower = state.getValue(POWER);
|
||||
+ int newPower = ((DefaultRedstoneWireEvaluator) evaluator).calculateTargetStrength(level, pos);
|
||||
+ if (oldPower != newPower) {
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent event = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), oldPower, newPower);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ newPower = event.getNewCurrent();
|
||||
+
|
||||
+ if (level.getBlockState(pos) == state) {
|
||||
+ newPower = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower).getNewCurrent();
|
||||
+ state = state.setValue(POWER, newPower);
|
||||
+ // [Space Walker] suppress shape updates and emit those manually to
|
||||
+ // bypass the new neighbor update stack.
|
||||
@@ -1042,7 +1033,7 @@ index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec4379
|
||||
private void updatePowerStrength(
|
||||
final Level level,
|
||||
final BlockPos pos,
|
||||
@@ -303,7 +357,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -303,7 +353,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@Override
|
||||
protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) {
|
||||
if (!oldState.is(state.getBlock()) && !level.isClientSide()) {
|
||||
@@ -1051,7 +1042,7 @@ index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec4379
|
||||
|
||||
for (Direction direction : Direction.Plane.VERTICAL) {
|
||||
level.updateNeighborsAt(pos.relative(direction), this);
|
||||
@@ -320,7 +374,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -320,7 +370,7 @@ public class RedStoneWireBlock extends Block {
|
||||
level.updateNeighborsAt(pos.relative(direction), this);
|
||||
}
|
||||
|
||||
@@ -1060,7 +1051,7 @@ index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec4379
|
||||
this.updateNeighborsOfNeighboringWires(level, pos);
|
||||
}
|
||||
}
|
||||
@@ -347,7 +401,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -347,7 +397,7 @@ public class RedStoneWireBlock extends Block {
|
||||
if (!level.isClientSide()) {
|
||||
if (block != this || !useExperimentalEvaluator(level)) {
|
||||
if (state.canSurvive(level, pos)) {
|
||||
@@ -1070,10 +1061,10 @@ index 0ee7bc3a10896a4f59fa94df158bce741aea0464..a677c3bfddfa0b7947394a3975ec4379
|
||||
dropResources(state, level, pos);
|
||||
level.removeBlock(pos, false);
|
||||
diff --git a/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java b/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
|
||||
index fe52dd304bc03b172654b89acb382c7f410d7946..afdcbb9e5a4c859d82bfb33a1d253514c17eed39 100644
|
||||
index 45c3586a653f4ec22b9fb859b2869503d0b6c5b3..81b7b625dbfe69f2a9d74dac000a0e60a75db839 100644
|
||||
--- a/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
|
||||
+++ b/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
|
||||
@@ -47,7 +47,7 @@ public class DefaultRedstoneWireEvaluator extends RedstoneWireEvaluator {
|
||||
@@ -44,7 +44,7 @@ public class DefaultRedstoneWireEvaluator extends RedstoneWireEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-20
@@ -22,30 +22,25 @@ Alternate Current's wire handler.
|
||||
|
||||
diff --git a/alternate/current/wire/LevelHelper.java b/alternate/current/wire/LevelHelper.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ff663d3089627e75221aa128aff4bf5cc459addb
|
||||
index 0000000000000000000000000000000000000000..dd533953f33aacfc91a8acad6c9a9d601df0bd86
|
||||
--- /dev/null
|
||||
+++ b/alternate/current/wire/LevelHelper.java
|
||||
@@ -0,0 +1,66 @@
|
||||
@@ -0,0 +1,61 @@
|
||||
+package alternate.current.wire;
|
||||
+
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.event.block.BlockRedstoneEvent;
|
||||
+
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.world.level.block.Block;
|
||||
+import net.minecraft.world.level.block.state.BlockState;
|
||||
+import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
+import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
+import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
+import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+
|
||||
+class LevelHelper {
|
||||
+
|
||||
+ static int doRedstoneEvent(ServerLevel level, BlockPos pos, int prevPower, int newPower) {
|
||||
+ BlockRedstoneEvent event = new BlockRedstoneEvent(CraftBlock.at(level, pos), prevPower, newPower);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ return event.getNewCurrent();
|
||||
+ return CraftEventFactory.callRedstoneChange(level, pos, prevPower, newPower).getNewCurrent();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
@@ -2326,18 +2321,18 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 6d847ff3646b27fe9bc75e792d813a7f611ab3e5..cfc30654917703a9278143a2c36d37eb719ee061 100644
|
||||
index f4bbccee849ee3711a3b838884e4bcf4e24da039..0b9fbf0ae658f0b3e9c6106a42fb70948b6fb9be 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -232,6 +232,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
public final WorldGenSettings worldGenSettings;
|
||||
@@ -233,6 +233,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
private @Nullable ServerClockManager clockManager;
|
||||
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
||||
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
+ private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
|
||||
|
||||
@Override
|
||||
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
@@ -2766,6 +2767,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -2775,6 +2776,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
return this.debugSynchronizers;
|
||||
}
|
||||
|
||||
@@ -2352,10 +2347,10 @@ index 6d847ff3646b27fe9bc75e792d813a7f611ab3e5..cfc30654917703a9278143a2c36d37eb
|
||||
return toLevel.dimension() != Level.NETHER || this.getGameRules().get(GameRules.ALLOW_ENTERING_NETHER_USING_PORTALS);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 31c7223d2d01573c24d4ad83737fa2c2752db028..8df070a7135411806d42ea692b566c4d8389a47b 100644
|
||||
index 07c301ba02c7f2c032a29a0ae3bdf95fc522c03b..7e4cf8a13e0ff2198cb7b6d80fb3fa343339943b 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -2152,6 +2152,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -2153,6 +2153,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
return this.palettedContainerFactory;
|
||||
}
|
||||
|
||||
@@ -2374,7 +2369,7 @@ index 31c7223d2d01573c24d4ad83737fa2c2752db028..8df070a7135411806d42ea692b566c4d
|
||||
NONE("none"),
|
||||
BLOCK("block"),
|
||||
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index a677c3bfddfa0b7947394a3975ec43794be07d7e..ed471efa3ab705de62aec81c3940c1b9c5acdbc5 100644
|
||||
index a00002774755eb90a0b772fe742b30a5e09452cf..1e863e97bd1dc99ed6e2c0602f78f457ac618965 100644
|
||||
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -269,7 +269,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -2386,7 +2381,7 @@ index a677c3bfddfa0b7947394a3975ec43794be07d7e..ed471efa3ab705de62aec81c3940c1b9
|
||||
// The bulk of the new functionality is found in RedstoneWireTurbo.java
|
||||
io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo(this);
|
||||
|
||||
@@ -357,7 +357,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -353,7 +353,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@Override
|
||||
protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) {
|
||||
if (!oldState.is(state.getBlock()) && !level.isClientSide()) {
|
||||
@@ -2401,7 +2396,7 @@ index a677c3bfddfa0b7947394a3975ec43794be07d7e..ed471efa3ab705de62aec81c3940c1b9
|
||||
|
||||
for (Direction direction : Direction.Plane.VERTICAL) {
|
||||
level.updateNeighborsAt(pos.relative(direction), this);
|
||||
@@ -374,7 +380,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -370,7 +376,13 @@ public class RedStoneWireBlock extends Block {
|
||||
level.updateNeighborsAt(pos.relative(direction), this);
|
||||
}
|
||||
|
||||
@@ -2416,7 +2411,7 @@ index a677c3bfddfa0b7947394a3975ec43794be07d7e..ed471efa3ab705de62aec81c3940c1b9
|
||||
this.updateNeighborsOfNeighboringWires(level, pos);
|
||||
}
|
||||
}
|
||||
@@ -399,9 +411,15 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -395,9 +407,15 @@ public class RedStoneWireBlock extends Block {
|
||||
final BlockState state, final Level level, final BlockPos pos, final Block block, final @Nullable Orientation orientation, final boolean movedByPiston
|
||||
) {
|
||||
if (!level.isClientSide()) {
|
||||
|
||||
+5
-5
@@ -55,7 +55,7 @@ index a6f9435a8e2a6c8cc05bd3873cb6fc0ec98973b8..d44fd9eea0ccb09c894d6431ede8a4c2
|
||||
this.used.set(position, position + size);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index fc712f9dbc893a6dee8ccecc54d0af07659dee62..b4a59b855b45018853e8122a5829a48ebd220a5f 100644
|
||||
index 5e77906d77da82b23fbd6e8d16fbd0847c83f4da..e077797cefffcb9db627cab12c7d88245e5baa69 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -47,6 +47,363 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@@ -760,7 +760,7 @@ index 5fa64ff30b8252f139ca7f77c14352c384c8c0e5..eae4963b6d18c5f92871477b93f81c2c
|
||||
|
||||
return var4;
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java b/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
index 97d3da90c270a06d85e70d261658f71d97ae4e3c..11b65c688144e7ef5b7cba603949843a11ccd084 100644
|
||||
index ea229f63f81c5638ded74c28e1e13d8948f2e5e0..d991fccfc3d2cc51611f802a6d40429024e21d9a 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
|
||||
@@ -21,7 +21,7 @@ import org.slf4j.Logger;
|
||||
@@ -771,7 +771,7 @@ index 97d3da90c270a06d85e70d261658f71d97ae4e3c..11b65c688144e7ef5b7cba603949843a
|
||||
+ public static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>(); // Paper - private -> public
|
||||
private static final Object2ObjectMap<String, RegionFileVersion> VERSIONS_BY_NAME = new Object2ObjectOpenHashMap<>();
|
||||
public static final RegionFileVersion VERSION_GZIP = register(
|
||||
new RegionFileVersion(1, null, in -> new FastBufferedInputStream(new GZIPInputStream(in)), out -> new BufferedOutputStream(new GZIPOutputStream(out)))
|
||||
new RegionFileVersion(1, "gzip", in -> new FastBufferedInputStream(new GZIPInputStream(in)), out -> new BufferedOutputStream(new GZIPOutputStream(out))) // Paper - Enable for Configurable region compression format
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionStorageInfo.java b/net/minecraft/world/level/chunk/storage/RegionStorageInfo.java
|
||||
index 590bd1ca60956e5c5be58481f97401e55f9e1aeb..4e0c9fa1eecfa9f21285b7911e25830bbcbc8d86 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionStorageInfo.java
|
||||
@@ -791,7 +791,7 @@ index 590bd1ca60956e5c5be58481f97401e55f9e1aeb..4e0c9fa1eecfa9f21285b7911e25830b
|
||||
return new RegionStorageInfo(this.level, this.dimension, this.type + suffix);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
index 22a83f312d357176a5489e5b6b71c3ef3e737df7..74158a5d7ea8058c99ab215265987746aa043fc7 100644
|
||||
index 1e0afa9590de7fe492cf29aded96be3db498c51e..df0bb06176ad5cce3ed8785d22d68b2dcbf5a8ca 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
@@ -120,6 +120,18 @@ public record SerializableChunkData(
|
||||
@@ -823,7 +823,7 @@ index 22a83f312d357176a5489e5b6b71c3ef3e737df7..74158a5d7ea8058c99ab215265987746
|
||||
tag.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(this.chunkStatus).toString());
|
||||
tag.storeNullable("blending_data", BlendingData.Packed.CODEC, this.blendingData);
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
index 884fa9545a93008fa92863c845aef8f18d88e25a..15da3686bb1b5fddd388a88a7b300aa221c83f58 100644
|
||||
index 6e55cb304fd9a5a01bbe7666dddb882e684cdcf1..6d954064f409ddd2cb7cfd0d0c428ac186f5ca4d 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||
@@ -34,6 +34,7 @@ public class SimpleRegionStorage implements ca.spottedleaf.moonrise.patches.chun
|
||||
|
||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index def29f67aa4d901fd61cb546f65b763b3da09131..a3edf217dd2ffce19dc1111402975ba12bb86bad 100644
|
||||
index 248a01f06ec822737a741873166aa4e502a7ba07..c4eb56fc227afd7e9631624537dd8e67ae3a8bea 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -958,7 +958,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -968,7 +968,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
public boolean saveAllChunks(final boolean silent, final boolean flush, final boolean force, final boolean close) {
|
||||
// Paper end - add close param
|
||||
@@ -17,7 +17,7 @@ index def29f67aa4d901fd61cb546f65b763b3da09131..a3edf217dd2ffce19dc1111402975ba1
|
||||
boolean result = false;
|
||||
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
@@ -970,13 +970,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -980,13 +980,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
result = true;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ index def29f67aa4d901fd61cb546f65b763b3da09131..a3edf217dd2ffce19dc1111402975ba1
|
||||
|
||||
if (flush) {
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
@@ -990,11 +984,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1000,11 +994,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ index def29f67aa4d901fd61cb546f65b763b3da09131..a3edf217dd2ffce19dc1111402975ba1
|
||||
boolean result = this.saveAllChunks(silent, flush, force);
|
||||
this.warnOnLowDiskSpace();
|
||||
var5 = result;
|
||||
@@ -1641,9 +1649,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1651,9 +1659,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
this.ticksUntilAutosave--;
|
||||
@@ -94,10 +94,10 @@ index def29f67aa4d901fd61cb546f65b763b3da09131..a3edf217dd2ffce19dc1111402975ba1
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
this.server.spark.executeMainThreadTasks(); // Paper - spark
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index cfc30654917703a9278143a2c36d37eb719ee061..78021db10860396fef4eb2e01926fbad123916fa 100644
|
||||
index 0b9fbf0ae658f0b3e9c6106a42fb70948b6fb9be..bbeb0f673f2b23d1748e33364dc12ac16528d4c4 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1441,6 +1441,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -1451,6 +1451,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
public boolean mayInteract(final Entity entity, final BlockPos pos) {
|
||||
return !(entity instanceof Player player && (this.server.isUnderSpawnProtection(this, pos, player) || !this.getWorldBorder().isWithinBounds(pos)));
|
||||
}
|
||||
@@ -126,7 +126,7 @@ index 41816ca8d4ef3d959d2b88cd4b2eedaaa541e612..82e87270d1ad89ad7aa56e028ced6b99
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||
private static final int FLY_STAT_RECORDING_SPEED = 25;
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 0613b053f4a75c0884280011ee092d9d108b3857..b69bcaa1e27a4fbe9a9568f3c9e1843167abe1f5 100644
|
||||
index 02605ebe6ef10727badadbf7fc4cec52583df965..3d62e4d275f32c8604a1bdaefb6b9b1d4ea6e21f 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -418,6 +418,7 @@ public abstract class PlayerList {
|
||||
@@ -137,7 +137,7 @@ index 0613b053f4a75c0884280011ee092d9d108b3857..b69bcaa1e27a4fbe9a9568f3c9e18431
|
||||
this.playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats(); // CraftBukkit
|
||||
if (stats != null) {
|
||||
@@ -951,10 +952,24 @@ public abstract class PlayerList {
|
||||
@@ -950,10 +951,24 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
|
||||
+9
-9
@@ -6,10 +6,10 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
|
||||
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54cd6255ff 100644
|
||||
index fad017de5d9fc31988aa4edf97fb3f9bcbee56c8..06132bde0aed9dd9088c884ee31056b9176b6f90 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -634,6 +634,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -633,6 +633,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
vehicle.move(MoverType.PLAYER, new Vec3(xDist, yDist, zDist));
|
||||
@@ -17,7 +17,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
double oyDist = yDist;
|
||||
xDist = targetX - vehicle.getX();
|
||||
yDist = targetY - vehicle.getY();
|
||||
@@ -649,7 +650,17 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -648,7 +649,17 @@ public class ServerGamePacketListenerImpl
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", vehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(movedDist));
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
vehicle.absSnapTo(oldX, oldY, oldZ, targetYRot, targetXRot);
|
||||
this.send(ClientboundMoveVehiclePacket.fromEntity(vehicle));
|
||||
vehicle.removeLatestMovementRecording();
|
||||
@@ -728,9 +739,32 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -727,9 +738,32 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
private boolean noBlocksAround(final Entity entity) {
|
||||
@@ -72,7 +72,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1542,7 +1576,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1541,7 +1575,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
xDist = targetX - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
||||
yDist = targetY - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
||||
zDist = targetZ - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
|
||||
@@ -1581,6 +1615,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1580,6 +1614,7 @@ public class ServerGamePacketListenerImpl
|
||||
boolean playerStandsOnSomething = this.player.verticalCollisionBelow;
|
||||
this.player.move(MoverType.PLAYER, new Vec3(xDist, yDist, zDist));
|
||||
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
||||
@@ -89,7 +89,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
// Paper start - prevent position desync
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
||||
@@ -1614,7 +1649,17 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1613,7 +1648,17 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
// Paper start - Add fail move event
|
||||
@@ -108,7 +108,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
if (!allowMovement) {
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, false);
|
||||
@@ -1752,7 +1797,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1751,7 +1796,7 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
private boolean updateAwaitingTeleport() {
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
@@ -117,7 +117,7 @@ index 05a700ffc844b41f4fa129226f78dc6c52520f32..1d93a864c5fc040b5ec7c48b4db0bd54
|
||||
this.awaitingTeleportTime = this.tickCount;
|
||||
this.teleport(
|
||||
this.awaitingPositionFromClient.x,
|
||||
@@ -1771,6 +1816,34 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1770,6 +1815,34 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ average over the last 5 seconds of keepalive transactions.
|
||||
|
||||
diff --git a/io/papermc/paper/util/KeepAlive.java b/io/papermc/paper/util/KeepAlive.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4a2520f554c2ee74faf86d7c93baccf0f391a6b3
|
||||
index 0000000000000000000000000000000000000000..66d6af2833d76af28fbeb2ce70c194a559572460
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/util/KeepAlive.java
|
||||
@@ -0,0 +1,67 @@
|
||||
@@ -0,0 +1,84 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+public class KeepAlive {
|
||||
@@ -34,6 +34,14 @@ index 0000000000000000000000000000000000000000..4a2520f554c2ee74faf86d7c93baccf0
|
||||
+ public final PingCalculator pingCalculator1m = new PingCalculator(java.util.concurrent.TimeUnit.MINUTES.toNanos(1L));
|
||||
+ public final PingCalculator pingCalculator5s = new PingCalculator(java.util.concurrent.TimeUnit.SECONDS.toNanos(5L));
|
||||
+
|
||||
+ public KeepAlive copyForListenerHandoff() {
|
||||
+ KeepAlive copy = new KeepAlive();
|
||||
+ copy.lastKeepAliveTx = this.lastKeepAliveTx;
|
||||
+ copy.pingCalculator1m.copyFrom(this.pingCalculator1m);
|
||||
+ copy.pingCalculator5s.copyFrom(this.pingCalculator5s);
|
||||
+ return copy;
|
||||
+ }
|
||||
+
|
||||
+ public static final class PingCalculator {
|
||||
+
|
||||
+ private final long intervalNS;
|
||||
@@ -47,6 +55,15 @@ index 0000000000000000000000000000000000000000..4a2520f554c2ee74faf86d7c93baccf0
|
||||
+ this.intervalNS = intervalNS;
|
||||
+ }
|
||||
+
|
||||
+ private void copyFrom(PingCalculator other) {
|
||||
+ for (KeepAliveResponse response : other.responses) {
|
||||
+ this.responses.add(response);
|
||||
+ }
|
||||
+ this.timeSumNS = other.timeSumNS;
|
||||
+ this.timeSumCount = other.timeSumCount;
|
||||
+ this.lastAverageNS = other.lastAverageNS;
|
||||
+ }
|
||||
+
|
||||
+ public void update(KeepAliveResponse response) {
|
||||
+ long currTime = response.txTimeNS;
|
||||
+
|
||||
@@ -100,7 +117,7 @@ index d87a00ee3cd04ce25dbe46ae6b386b7f0799102c..ace440c2b82a6368aa27a85ff433ba2c
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d0e890508 100644
|
||||
index abeca4714053fd0a4fa489d496e2e0b844de40a8..7ed50fc00c58c7781c958df1d828a67adf696f3e 100644
|
||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -39,12 +39,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -121,7 +138,7 @@ index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
// CraftBukkit start
|
||||
public final org.bukkit.craftbukkit.CraftServer cserver;
|
||||
@@ -61,13 +62,14 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -60,13 +61,14 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
public ServerCommonPacketListenerImpl(final MinecraftServer server, final Connection connection, final CommonListenerCookie cookie) {
|
||||
this.server = server;
|
||||
this.connection = connection;
|
||||
@@ -137,7 +154,7 @@ index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@@ -100,13 +102,41 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -99,13 +101,35 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(final ServerboundKeepAlivePacket packet) {
|
||||
@@ -167,25 +184,19 @@ index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d
|
||||
+ if (ka.challengeId() == packet.getId()) {
|
||||
+ itr.remove();
|
||||
+
|
||||
+ if (!this.processedDisconnect) {
|
||||
+ LOGGER.info("Disconnecting {} for sending keepalive response ({}) out-of-order!", this.playerProfile().name(), packet.getId());
|
||||
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT);
|
||||
+ return;
|
||||
+ }
|
||||
+ break;
|
||||
+ LOGGER.info("Disconnecting {} for sending keepalive response ({}) out-of-order!", this.playerProfile().name(), packet.getId());
|
||||
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ if (!this.processedDisconnect) {
|
||||
+ LOGGER.info("Disconnecting {} for sending keepalive response ({}) without matching challenge!", this.playerProfile().name(), packet.getId());
|
||||
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT);
|
||||
+ return;
|
||||
+ }
|
||||
+ LOGGER.info("Disconnecting {} for sending keepalive response ({}) without matching challenge!", this.playerProfile().name(), packet.getId());
|
||||
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT);
|
||||
+ // Paper end - improve keepalives
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,20 +263,23 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -232,20 +256,23 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
protected void keepConnectionAlive() {
|
||||
Profiler.get().push("keepAlive");
|
||||
long now = Util.getMillis();
|
||||
@@ -204,7 +215,7 @@ index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d
|
||||
- this.keepAliveChallenge = now;
|
||||
- this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
|
||||
+ // Paper start - improve keepalives
|
||||
+ if (this.checkIfClosed(now) && !this.processedDisconnect) {
|
||||
+ if (this.checkIfClosed(now)) {
|
||||
+ long currTime = System.nanoTime();
|
||||
+
|
||||
+ if ((currTime - this.keepAlive.lastKeepAliveTx) >= java.util.concurrent.TimeUnit.SECONDS.toNanos(1L)) {
|
||||
@@ -223,11 +234,21 @@ index f54d99c59bbca7fb5e0615f8fee9c3f6fbffa18a..d9b6f3826e2126d339e926afed782f6d
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +457,6 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -420,6 +447,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
}
|
||||
|
||||
protected CommonListenerCookie createCookie(final ClientInformation clientInformation) {
|
||||
- return new CommonListenerCookie(this.playerProfile(), this.latency, clientInformation, this.transferred, this.playerBrand, this.pluginMessagerChannels); // Paper
|
||||
+ return new CommonListenerCookie(this.playerProfile(), this.latency, clientInformation, this.transferred, this.playerBrand, this.pluginMessagerChannels, this.keepAlive); // Paper // Paper
|
||||
+ // Paper start - listener handoff should reset pending keepalive expectations
|
||||
+ return new CommonListenerCookie(
|
||||
+ this.playerProfile(),
|
||||
+ this.latency,
|
||||
+ clientInformation,
|
||||
+ this.transferred,
|
||||
+ this.playerBrand,
|
||||
+ this.pluginMessagerChannels,
|
||||
+ this.keepAlive.copyForListenerHandoff()
|
||||
+ );
|
||||
+ // Paper end - listener handoff should reset pending keepalive expectations
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ index 2bc436cdf5180a7943c45fabb9fbbedae6f7db56..f312a7f5b1b2a777ab36b94ce7cbf387
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index a3edf217dd2ffce19dc1111402975ba12bb86bad..2b6717833b56c3e33f3ac656a376dd5c841dc1bc 100644
|
||||
index 8c4b40362f77cdea6e57315a6639006ac7ab27c7..a5217deb236ee922d020a7a6a03141a5f67acd77 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1784,32 +1784,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1794,32 +1794,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,10 @@ index a3edf217dd2ffce19dc1111402975ba12bb86bad..2b6717833b56c3e33f3ac656a376dd5c
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 93d3fb313d538cc1067b1db010458169a1320122..9cd46a8619e575a865f4d00ce71d249c9b028b2f 100644
|
||||
index fea6c3b48c4eb162fbdc099fa775bc3161a4dd4e..82f6582a92f17bdeb3218c4c1fcac86981fd9c37 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -5147,6 +5147,11 @@ public abstract class Entity
|
||||
@@ -5146,6 +5146,11 @@ public abstract class Entity
|
||||
this.getBukkitEntity().taskScheduler.retire();
|
||||
}
|
||||
// Paper end - Folia schedulers
|
||||
|
||||
@@ -42,10 +42,10 @@ index d2877c20f389d0131e1dd208b464f590671e5d82..27bdc70d861ca39487ad16cb3afb89d6
|
||||
updateComponent(root, "minecraft:trim", hiddenComponents);
|
||||
updateComponent(root, "minecraft:unbreakable", hiddenComponents);
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index ae140a514e1e3200f52c5933f886cc9e820b818a..4a1146cc54bd9272466ffc9bb64f600c40f0c0f4 100644
|
||||
index 06132bde0aed9dd9088c884ee31056b9176b6f90..08374da2d9b84e8ff13c670d7f45867fb0bdd897 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1820,9 +1820,14 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1819,9 +1819,14 @@ public class ServerGamePacketListenerImpl
|
||||
private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
|
||||
final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
||||
final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
|
||||
@@ -62,10 +62,10 @@ index ae140a514e1e3200f52c5933f886cc9e820b818a..4a1146cc54bd9272466ffc9bb64f600c
|
||||
);
|
||||
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 8df070a7135411806d42ea692b566c4d8389a47b..06451a21c4bfbcd95063f96246013d63f65af8a3 100644
|
||||
index fa3809be5c0488c5a1d2639579d68619b0a55de9..c332d48f5cac2f3be93201c66f4f7cdba916cbac 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -1528,7 +1528,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -1529,7 +1529,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups)
|
||||
return false;
|
||||
// Paper start - optimise collisions
|
||||
|
||||
@@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 2b6717833b56c3e33f3ac656a376dd5c841dc1bc..2142757965b7345a011a92de08038473fa8ae320 100644
|
||||
index af1f5e83bd24e671399af2a9aadc8e11959ec5f4..b9efed1df74651c894a416f1d3db320d4ab20401 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1836,6 +1836,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1850,6 +1850,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
level.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
||||
level.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
||||
level.updateLagCompensationTick(); // Paper - lag compensation
|
||||
|
||||
@@ -155,10 +155,10 @@ index a94e6ca1d396b6b0781de5d550c4a804274ee003..a1018e9ca9dfb978d6e6633577abd7d5
|
||||
|
||||
private ClientboundLevelChunkWithLightPacket(final RegistryFriendlyByteBuf input) {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 78021db10860396fef4eb2e01926fbad123916fa..3f02da2014ed8e4169f4bb819b4d9e61154b7b06 100644
|
||||
index 4ac7ef5a1ed1fac04a9fd246212f59919deb498c..e562aec4366d7724f915e3dd5ae440a77e0947c5 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -630,7 +630,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
@@ -631,7 +631,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
savedDataStorage.set(io.papermc.paper.world.saveddata.PaperWorldPDC.TYPE, loadedWorldData.pdc() == null ? io.papermc.paper.world.saveddata.PaperWorldPDC.TYPE.constructor().get() : loadedWorldData.pdc());
|
||||
final GameRules gameRules = new GameRules(server.getWorldData().enabledFeatures(), savedDataStorage.computeIfAbsent(net.minecraft.world.level.gamerules.GameRuleMap.TYPE));
|
||||
this.gameRules = gameRules;
|
||||
@@ -196,7 +196,7 @@ index ec40f02032f965f548b0c0a29aa9d9bbad6f439b..373da9d604cfb1614a0618d856aefd2b
|
||||
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), connection.getPlayer().getBukkitEntity()).callEvent();
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index b69bcaa1e27a4fbe9a9568f3c9e1843167abe1f5..9218322801c41657c00928ef90b0de99df1670f6 100644
|
||||
index 5e11abcfd681d86b1c0e282cf901108822766ce2..3020a3208b14bb483b08cf59a796fb83c2403d1c 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -331,7 +331,7 @@ public abstract class PlayerList {
|
||||
@@ -209,7 +209,7 @@ index b69bcaa1e27a4fbe9a9568f3c9e1843167abe1f5..9218322801c41657c00928ef90b0de99
|
||||
}
|
||||
// Paper end - Send empty chunk
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 06451a21c4bfbcd95063f96246013d63f65af8a3..e34e901dce06c6bc6060418593010dcfb38e9396 100644
|
||||
index 829bb616e5d72b955248bbc150254c239176ce64..4b228b5c563e40b6f301df22b5c8a7f7988cb072 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -145,6 +145,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -230,7 +230,7 @@ index 06451a21c4bfbcd95063f96246013d63f65af8a3..e34e901dce06c6bc6060418593010dcf
|
||||
) {
|
||||
// Paper start - getblock optimisations - cache world height/sections
|
||||
final DimensionType dimType = dimensionTypeRegistration.value();
|
||||
@@ -870,6 +872,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -871,6 +873,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
this.palettedContainerFactory = PalettedContainerFactory.create(registryAccess);
|
||||
this.damageSources = new DamageSources(registryAccess);
|
||||
this.entityLookup = new ca.spottedleaf.moonrise.patches.chunk_system.level.entity.dfl.DefaultEntityLookup(this); // Paper - rewrite chunk system
|
||||
@@ -238,7 +238,7 @@ index 06451a21c4bfbcd95063f96246013d63f65af8a3..e34e901dce06c6bc6060418593010dcf
|
||||
}
|
||||
|
||||
// Paper start - Cancel hit for vanished players
|
||||
@@ -1084,6 +1087,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
@@ -1085,6 +1088,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
}
|
||||
// CraftBukkit end - capture blockstates
|
||||
BlockState oldState = chunk.setBlockState(pos, blockState, updateFlags);
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 20 Apr 2026 02:56:22 -0700
|
||||
Subject: [PATCH] Delay open/close callbacks for chests
|
||||
|
||||
The logic for chests may invoke block updates, which may not
|
||||
be safe to perform. For example, inventory closing due to
|
||||
player logout (which restricts chunk loading due to being
|
||||
inside an entity status callback) or during shutdown (which has
|
||||
chunk loading restrictions due to the chunk system being halted).
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index 9eb6cb86ff70f04863cae3def1006f82bcb4fa6b..da5fdf77dd26d97c8b92bac9a6af8d922c31eb9c 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -66,6 +66,13 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
Objects.requireNonNull(BarrelBlockEntity.this);
|
||||
}
|
||||
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
+
|
||||
@Override
|
||||
protected void onOpen(final Level level, final BlockPos pos, final BlockState state) {
|
||||
BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_OPEN);
|
||||
diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index 81a293cc13653a9a0336cb25d75273969fee4d16..8ebcce4c4971a11d367fb39e9c7fd280f63594e3 100644
|
||||
--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -35,6 +35,13 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
Objects.requireNonNull(ChestBlockEntity.this);
|
||||
}
|
||||
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
+
|
||||
@Override
|
||||
protected void onOpen(final Level level, final BlockPos pos, final BlockState blockState) {
|
||||
if (blockState.getBlock() instanceof ChestBlock chestBlock) {
|
||||
diff --git a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
index baa8b5aba0500981a191626553d66650c7304b88..52737172ccfa0c7c977e4f2fe1db242e0bb92d25 100644
|
||||
--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
@@ -37,11 +37,23 @@ public abstract class ContainerOpenersCounter {
|
||||
|
||||
protected abstract void openerCountChanged(final Level level, final BlockPos pos, final BlockState blockState, int previous, int current);
|
||||
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ public boolean delayCallbacks() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
+
|
||||
public abstract boolean isOwnContainer(final Player player);
|
||||
|
||||
public void incrementOpeners(
|
||||
final LivingEntity entity, final Level level, final BlockPos pos, final BlockState blockState, final double maxInteractionRange
|
||||
) {
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ if (this.delayCallbacks()) {
|
||||
+ scheduleRecheck(level, pos, blockState, 1);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
int previous = this.openCount++;
|
||||
|
||||
// Paper start - Call BlockRedstoneEvent
|
||||
@@ -66,6 +78,12 @@ public abstract class ContainerOpenersCounter {
|
||||
}
|
||||
|
||||
public void decrementOpeners(final LivingEntity entity, final Level level, final BlockPos pos, final BlockState blockState) {
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ if (this.delayCallbacks()) {
|
||||
+ scheduleRecheck(level, pos, blockState, 1);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
if (this.openCount == 0) return; // Paper - Prevent ContainerOpenersCounter openCount from going negative
|
||||
int previous = this.openCount--;
|
||||
|
||||
@@ -151,6 +169,11 @@ public abstract class ContainerOpenersCounter {
|
||||
}
|
||||
|
||||
private static void scheduleRecheck(final Level level, final BlockPos blockPos, final BlockState blockState) {
|
||||
- level.scheduleTick(blockPos, blockState.getBlock(), 5);
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ scheduleRecheck(level, blockPos, blockState, 5);
|
||||
+ }
|
||||
+ private static void scheduleRecheck(final Level level, final BlockPos blockPos, final BlockState blockState, final int delay) {
|
||||
+ level.scheduleTick(blockPos, blockState.getBlock(), delay);
|
||||
+ // Paper end - delay open/close callbacks
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
index eeac644f60760570244380d3c454fd33e37b5a7f..751625124a87de63d933d9c7809e46361e3136a5 100644
|
||||
--- a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
@@ -18,6 +18,13 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity
|
||||
Objects.requireNonNull(EnderChestBlockEntity.this);
|
||||
}
|
||||
|
||||
+ // Paper start - delay open/close callbacks
|
||||
+ @Override
|
||||
+ public boolean delayCallbacks() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - delay open/close callbacks
|
||||
+
|
||||
@Override
|
||||
protected void onOpen(final Level level, final BlockPos pos, final BlockState blockState) {
|
||||
level.playSound(
|
||||
+138
-133
@@ -8,13 +8,14 @@ and shapeless recipes.
|
||||
|
||||
diff --git a/io/papermc/paper/inventory/recipe/ItemOrExact.java b/io/papermc/paper/inventory/recipe/ItemOrExact.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ce745e49cd54fe3ae187785563a1bd311d14b5b2
|
||||
index 0000000000000000000000000000000000000000..9e621873454cc2edc2e59e6c7554d8116cd32bc1
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/inventory/recipe/ItemOrExact.java
|
||||
@@ -0,0 +1,63 @@
|
||||
@@ -0,0 +1,64 @@
|
||||
+package io.papermc.paper.inventory.recipe;
|
||||
+
|
||||
+import net.minecraft.core.Holder;
|
||||
+import net.minecraft.core.component.DataComponents;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+
|
||||
+public sealed interface ItemOrExact permits ItemOrExact.Item, ItemOrExact.Exact {
|
||||
@@ -26,12 +27,12 @@ index 0000000000000000000000000000000000000000..ce745e49cd54fe3ae187785563a1bd31
|
||||
+ record Item(Holder<net.minecraft.world.item.Item> item) implements ItemOrExact {
|
||||
+
|
||||
+ public Item(final ItemStack stack) {
|
||||
+ this(stack.getItemHolder());
|
||||
+ this(stack.typeHolder());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.item.value().getDefaultMaxStackSize();
|
||||
+ return this.item.components().getOrDefault(DataComponents.MAX_STACK_SIZE, 1);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
@@ -150,119 +151,119 @@ index 0000000000000000000000000000000000000000..f47c12e9dd6cfa857ca07a764edc22de
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/recipebook/ServerPlaceRecipe.java b/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
index 6d3e3ec045d5b15a435f7217369968b33e082724..b7a3758af337270737041f84d10eb43784e42279 100644
|
||||
index 31f8aa58b48aeb64e57480490a449b6c46913880..b7ee9fe694ea37eeb58b5dded7967e7d0f338d0d 100644
|
||||
--- a/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
+++ b/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
@@ -40,6 +40,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
@@ -41,6 +41,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
return RecipeBookMenu.PostPlaceAction.NOTHING;
|
||||
} else {
|
||||
StackedItemContents stackedItemContents = new StackedItemContents();
|
||||
+ stackedItemContents.initializeExtras(recipe.value(), null); // Paper - Improve exact choice recipe ingredients
|
||||
inventory.fillStackedContents(stackedItemContents);
|
||||
menu.fillCraftSlotsStackedContents(stackedItemContents);
|
||||
return serverPlaceRecipe.tryPlaceRecipe(recipe, stackedItemContents);
|
||||
@@ -99,7 +100,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
StackedItemContents availableItems = new StackedItemContents();
|
||||
+ availableItems.initializeExtras(recipe.value(), null); // Paper - Improve exact choice recipe ingredients
|
||||
inventory.fillStackedContents(availableItems);
|
||||
menu.fillCraftSlotsStackedContents(availableItems);
|
||||
return placer.tryPlaceRecipe(recipe, availableItems);
|
||||
@@ -100,7 +101,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
|
||||
int i = this.calculateAmountToCraft(biggestCraftableStack, flag);
|
||||
- List<Holder<Item>> list = new ArrayList<>();
|
||||
+ List<io.papermc.paper.inventory.recipe.ItemOrExact> list = new ArrayList<>(); // Paper - Improve exact choice recipe ingredients
|
||||
if (stackedItemContents.canCraft(recipe.value(), i, list::add)) {
|
||||
int i1 = clampToMaxStackSize(i, list);
|
||||
if (i1 != i) {
|
||||
@@ -114,7 +115,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
this.gridWidth, this.gridHeight, recipe.value(), recipe.value().placementInfo().slotsToIngredientIndex(), (item1, slot1, x, y) -> {
|
||||
if (item1 != -1) {
|
||||
Slot slot2 = this.inputGridSlots.get(slot1);
|
||||
- Holder<Item> holder = list.get(item1);
|
||||
+ io.papermc.paper.inventory.recipe.ItemOrExact holder = list.get(item1); // Paper - Improve exact choice recipe ingredients
|
||||
int i2 = i1;
|
||||
int amountToCraft = this.calculateAmountToCraft(biggestCraftableStack, recipeMatchesPlaced);
|
||||
- List<Holder<Item>> itemsUsedPerIngredient = new ArrayList<>();
|
||||
+ List<io.papermc.paper.inventory.recipe.ItemOrExact> itemsUsedPerIngredient = new ArrayList<>(); // Paper - Improve exact choice recipe ingredients
|
||||
if (availableItems.canCraft(recipe.value(), amountToCraft, itemsUsedPerIngredient::add)) {
|
||||
int adjustedAmountToCraft = clampToMaxStackSize(amountToCraft, itemsUsedPerIngredient);
|
||||
if (adjustedAmountToCraft != amountToCraft) {
|
||||
@@ -119,7 +120,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
(ingredientIndex, gridIndex, gridXPos, gridYPos) -> {
|
||||
if (ingredientIndex != -1) {
|
||||
Slot targetGridSlot = this.inputGridSlots.get(gridIndex);
|
||||
- Holder<Item> itemUsed = itemsUsedPerIngredient.get(ingredientIndex);
|
||||
+ io.papermc.paper.inventory.recipe.ItemOrExact itemUsed = itemsUsedPerIngredient.get(ingredientIndex); // Paper - Improve exact choice recipe ingredients
|
||||
int remainingCount = adjustedAmountToCraft;
|
||||
|
||||
while (i2 > 0) {
|
||||
@@ -129,9 +130,11 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
while (remainingCount > 0) {
|
||||
@@ -134,9 +135,11 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
- private static int clampToMaxStackSize(int amount, List<Holder<Item>> items) {
|
||||
- for (Holder<Item> holder : items) {
|
||||
- amount = Math.min(amount, holder.value().getDefaultMaxStackSize());
|
||||
- private static int clampToMaxStackSize(int value, final List<Holder<Item>> items) {
|
||||
- for (Holder<Item> item : items) {
|
||||
- value = Math.min(value, item.components().getOrDefault(DataComponents.MAX_STACK_SIZE, 1));
|
||||
+ // Paper start - Improve exact choice recipe ingredients
|
||||
+ private static int clampToMaxStackSize(int amount, List<io.papermc.paper.inventory.recipe.ItemOrExact> items) {
|
||||
+ for (io.papermc.paper.inventory.recipe.ItemOrExact holder : items) {
|
||||
+ amount = Math.min(amount, holder.getMaxStackSize());
|
||||
+ private static int clampToMaxStackSize(int value, final List<io.papermc.paper.inventory.recipe.ItemOrExact> items) {
|
||||
+ for (io.papermc.paper.inventory.recipe.ItemOrExact item : items) {
|
||||
+ value = Math.min(value, item.getMaxStackSize());
|
||||
+ // Paper end - Improve exact choice recipe ingredients
|
||||
}
|
||||
|
||||
return amount;
|
||||
@@ -160,7 +163,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
return value;
|
||||
@@ -165,7 +168,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
- private int moveItemToGrid(Slot slot, Holder<Item> item, int count) {
|
||||
+ private int moveItemToGrid(Slot slot, io.papermc.paper.inventory.recipe.ItemOrExact item, int count) { // Paper - Improve exact choice recipe ingredients
|
||||
ItemStack item1 = slot.getItem();
|
||||
int i = this.inventory.findSlotMatchingCraftingIngredient(item, item1);
|
||||
if (i == -1) {
|
||||
- private int moveItemToGrid(final Slot targetSlot, final Holder<Item> itemInInventory, final int count) {
|
||||
+ private int moveItemToGrid(final Slot targetSlot, final io.papermc.paper.inventory.recipe.ItemOrExact itemInInventory, final int count) { // Paper - Improve exact choice recipe ingredients
|
||||
ItemStack itemInTargetSlot = targetSlot.getItem();
|
||||
int inventorySlotId = this.inventory.findSlotMatchingCraftingIngredient(itemInInventory, itemInTargetSlot);
|
||||
if (inventorySlotId == Inventory.NOT_FOUND_INDEX) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index 76eda3bd8c513c7e42ceedf1aa605fb6df8b7019..41e59f3739945ca7f6ab710c993b5c0f15fcd529 100644
|
||||
index da8bab81e135a9b240fbeac0e9e1d2aa12c6212d..f004911c438e6f89d6e079437e3f4104d6cbacbd 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -252,12 +252,12 @@ public class Inventory implements Container, Nameable {
|
||||
return !stack.isDamaged() && !stack.isEnchanted() && !stack.has(DataComponents.CUSTOM_NAME);
|
||||
return !item.isDamaged() && !item.isEnchanted() && !item.has(DataComponents.CUSTOM_NAME);
|
||||
}
|
||||
|
||||
- public int findSlotMatchingCraftingIngredient(Holder<Item> item, ItemStack stack) {
|
||||
+ public int findSlotMatchingCraftingIngredient(io.papermc.paper.inventory.recipe.ItemOrExact item, ItemStack stack) { // Paper - Improve exact choice recipe ingredients
|
||||
- public int findSlotMatchingCraftingIngredient(final Holder<Item> item, final ItemStack existingItem) {
|
||||
+ public int findSlotMatchingCraftingIngredient(final io.papermc.paper.inventory.recipe.ItemOrExact item, final ItemStack existingItem) { // Paper - Improve exact choice recipe ingredients
|
||||
for (int i = 0; i < this.items.size(); i++) {
|
||||
ItemStack itemStack = this.items.get(i);
|
||||
if (!itemStack.isEmpty()
|
||||
- && itemStack.is(item)
|
||||
- && isUsableForCrafting(itemStack)
|
||||
+ && item.matches(itemStack) // Paper - Improve exact choice recipe ingredients
|
||||
+ && (!(item instanceof io.papermc.paper.inventory.recipe.ItemOrExact.Item) || Inventory.isUsableForCrafting(itemStack)) // Paper - Improve exact choice recipe ingredients
|
||||
&& (stack.isEmpty() || ItemStack.isSameItemSameComponents(stack, itemStack))) {
|
||||
ItemStack inventoryItemStack = this.items.get(i);
|
||||
if (!inventoryItemStack.isEmpty()
|
||||
- && inventoryItemStack.is(item)
|
||||
- && isUsableForCrafting(inventoryItemStack)
|
||||
+ && item.matches(inventoryItemStack) // Paper - Improve exact choice recipe ingredients
|
||||
+ && (!(item instanceof io.papermc.paper.inventory.recipe.ItemOrExact.Item) || Inventory.isUsableForCrafting(inventoryItemStack)) // Paper - Improve exact choice recipe ingredients
|
||||
&& (existingItem.isEmpty() || ItemStack.isSameItemSameComponents(existingItem, inventoryItemStack))) {
|
||||
return i;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedContents.java b/net/minecraft/world/entity/player/StackedContents.java
|
||||
index bc4f7d16365dffc87b1eef8aa5791a5cb595ee78..cbb37480c19b210cf83999247c1d670c9df2d150 100644
|
||||
index 889b8e6c3762203deccf657b505f6f29cc893526..6710653d033a48c4b3fc267496f93a2548b5c966 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedContents.java
|
||||
@@ -13,7 +13,7 @@ import java.util.List;
|
||||
@@ -14,7 +14,7 @@ import java.util.Objects;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class StackedContents<T> {
|
||||
- public final Reference2IntOpenHashMap<T> amounts = new Reference2IntOpenHashMap<>();
|
||||
+ public final it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap<T> amounts = new it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap<>(); // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
|
||||
boolean hasAtLeast(T item, int amount) {
|
||||
return this.amounts.getInt(item) >= amount;
|
||||
@@ -49,7 +49,7 @@ public class StackedContents<T> {
|
||||
List<T> getUniqueAvailableIngredientItems(Iterable<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
List<T> list = new ArrayList<>();
|
||||
private boolean hasAtLeast(final T item, final int count) {
|
||||
return this.amounts.getInt(item) >= count;
|
||||
@@ -54,7 +54,7 @@ public class StackedContents<T> {
|
||||
private List<T> getUniqueAvailableIngredientItems(final Iterable<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
List<T> result = new ArrayList<>();
|
||||
|
||||
- for (Entry<T> entry : Reference2IntMaps.fastIterable(this.amounts)) {
|
||||
+ for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T> entry : it.unimi.dsi.fastutil.objects.Object2IntMaps.fastIterable(this.amounts)) { // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
if (entry.getIntValue() > 0 && anyIngredientMatches(ingredients, entry.getKey())) {
|
||||
list.add(entry.getKey());
|
||||
- for (Entry<T> availableItem : Reference2IntMaps.fastIterable(this.amounts)) {
|
||||
+ for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T> availableItem : it.unimi.dsi.fastutil.objects.Object2IntMaps.fastIterable(this.amounts)) { // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
if (availableItem.getIntValue() > 0 && anyIngredientMatches(ingredients, availableItem.getKey())) {
|
||||
result.add(availableItem.getKey());
|
||||
}
|
||||
@@ -71,13 +71,13 @@ public class StackedContents<T> {
|
||||
@@ -76,13 +76,13 @@ public class StackedContents<T> {
|
||||
@VisibleForTesting
|
||||
public int getResultUpperBound(List<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
int i = Integer.MAX_VALUE;
|
||||
- ObjectIterable<Entry<T>> objectIterable = Reference2IntMaps.fastIterable(this.amounts);
|
||||
+ ObjectIterable<it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T>> objectIterable = it.unimi.dsi.fastutil.objects.Object2IntMaps.fastIterable(this.amounts); // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
public int getResultUpperBound(final List<? extends StackedContents.IngredientInfo<T>> ingredients) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
- ObjectIterable<Entry<T>> availableItems = Reference2IntMaps.fastIterable(this.amounts);
|
||||
+ ObjectIterable<it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T>> availableItems = it.unimi.dsi.fastutil.objects.Object2IntMaps.fastIterable(this.amounts); // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
|
||||
label31:
|
||||
for (StackedContents.IngredientInfo<T> ingredientInfo : ingredients) {
|
||||
int i1 = 0;
|
||||
for (StackedContents.IngredientInfo<T> ingredient : ingredients) {
|
||||
int max = 0;
|
||||
|
||||
- for (Entry<T> entry : objectIterable) {
|
||||
+ for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T> entry : objectIterable) { // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
int intValue = entry.getIntValue();
|
||||
if (intValue > i1) {
|
||||
if (ingredientInfo.acceptsItem(entry.getKey())) {
|
||||
- for (Entry<T> entry : availableItems) {
|
||||
+ for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<T> entry : availableItems) { // Paper - Improve exact choice recipe ingredients (don't use "reference" map)
|
||||
int itemCount = entry.getIntValue();
|
||||
if (itemCount > max) {
|
||||
if (ingredient.acceptsItem(entry.getKey())) {
|
||||
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
index e0121e9c8439e32b7ef064c06942ccd5dd74987d..00dbc0d125b2c8c208ffa46f9084c6317efaba90 100644
|
||||
index ffaa8e450a11a01060b6847d1b66a76323f9d8ba..1ace17d8fc7e7b8b4722a1889d49233c0ec55e20 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
@@ -9,9 +9,27 @@ import net.minecraft.world.item.crafting.Recipe;
|
||||
@@ -289,115 +290,119 @@ index e0121e9c8439e32b7ef064c06942ccd5dd74987d..00dbc0d125b2c8c208ffa46f9084c631
|
||||
+ }
|
||||
+ // Paper end - Improve exact choice recipe ingredients
|
||||
|
||||
public void accountSimpleStack(ItemStack stack) {
|
||||
+ if (this.extrasMap != null && this.extrasMap.accountStack(stack, Math.min(64, stack.getCount()))) return; // Paper - Improve exact choice recipe ingredients; max of 64 due to accountStack method below
|
||||
if (Inventory.isUsableForCrafting(stack)) {
|
||||
this.accountStack(stack);
|
||||
public void accountSimpleStack(final ItemStack itemStack) {
|
||||
+ if (this.extrasMap != null && this.extrasMap.accountStack(itemStack, Math.min(itemStack.getMaxStackSize(), itemStack.getCount()))) return; // Paper - Improve exact choice recipe ingredients; Referenced from the accountStack method below
|
||||
if (Inventory.isUsableForCrafting(itemStack)) {
|
||||
this.accountStack(itemStack);
|
||||
}
|
||||
@@ -24,34 +42,35 @@ public class StackedItemContents {
|
||||
public void accountStack(ItemStack stack, int maxStackSize) {
|
||||
if (!stack.isEmpty()) {
|
||||
int min = Math.min(maxStackSize, stack.getCount());
|
||||
- this.raw.account(stack.getItemHolder(), min);
|
||||
+ if (this.extrasMap != null && !stack.getComponentsPatch().isEmpty() && this.extrasMap.accountStack(stack, min)) return; // Paper - Improve exact choice recipe ingredients; if an exact ingredient, don't include it
|
||||
+ this.raw.account(new io.papermc.paper.inventory.recipe.ItemOrExact.Item(stack.getItemHolder()), min);
|
||||
@@ -24,38 +42,39 @@ public class StackedItemContents {
|
||||
public void accountStack(final ItemStack itemStack, final int maxCount) {
|
||||
if (!itemStack.isEmpty()) {
|
||||
int count = Math.min(maxCount, itemStack.getCount());
|
||||
- this.raw.account(itemStack.typeHolder(), count);
|
||||
+ if (this.extrasMap != null && !itemStack.getComponentsPatch().isEmpty() && this.extrasMap.accountStack(itemStack, count)) return; // Paper - Improve exact choice recipe ingredients; if an exact ingredient, don't include it
|
||||
+ this.raw.account(new io.papermc.paper.inventory.recipe.ItemOrExact.Item(itemStack.typeHolder()), count);
|
||||
}
|
||||
}
|
||||
|
||||
- public boolean canCraft(Recipe<?> recipe, StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public boolean canCraft(Recipe<?> recipe, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
- public boolean canCraft(final Recipe<?> recipe, final StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public boolean canCraft(final Recipe<?> recipe, final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
return this.canCraft(recipe, 1, output);
|
||||
}
|
||||
|
||||
- public boolean canCraft(Recipe<?> recipe, int maxCount, StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public boolean canCraft(Recipe<?> recipe, int maxCount, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
- public boolean canCraft(final Recipe<?> recipe, final int amount, final StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public boolean canCraft(final Recipe<?> recipe, final int amount, final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
PlacementInfo placementInfo = recipe.placementInfo();
|
||||
return !placementInfo.isImpossibleToPlace() && this.canCraft(placementInfo.ingredients(), maxCount, output);
|
||||
return !placementInfo.isImpossibleToPlace() && this.canCraft(placementInfo.ingredients(), amount, output);
|
||||
}
|
||||
|
||||
- public boolean canCraft(List<? extends StackedContents.IngredientInfo<Holder<Item>>> ingredients, StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public boolean canCraft(List<? extends StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact>> ingredients, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
return this.canCraft(ingredients, 1, output);
|
||||
public boolean canCraft(
|
||||
- final List<? extends StackedContents.IngredientInfo<Holder<Item>>> contents, final StackedContents.@Nullable Output<Holder<Item>> output
|
||||
+ final List<? extends StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact>> contents, final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output // Paper - Improve exact choice recipe ingredients
|
||||
) {
|
||||
return this.canCraft(contents, 1, output);
|
||||
}
|
||||
|
||||
private boolean canCraft(
|
||||
- List<? extends StackedContents.IngredientInfo<Holder<Item>>> ingredients, int maxCount, StackedContents.@Nullable Output<Holder<Item>> output
|
||||
+ List<? extends StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact>> ingredients, int maxCount, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output // Paper - Improve exact choice recipe ingredients
|
||||
- final List<? extends StackedContents.IngredientInfo<Holder<Item>>> contents,
|
||||
+ final List<? extends StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact>> contents, // Paper - Improve exact choice recipe ingredients
|
||||
final int amount,
|
||||
- final StackedContents.@Nullable Output<Holder<Item>> output
|
||||
+ final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output // Paper - Improve exact choice recipe ingredients
|
||||
) {
|
||||
return this.raw.tryPick(ingredients, maxCount, output);
|
||||
return this.raw.tryPick(contents, amount, output);
|
||||
}
|
||||
|
||||
- public int getBiggestCraftableStack(Recipe<?> recipe, StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public int getBiggestCraftableStack(Recipe<?> recipe, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
- public int getBiggestCraftableStack(final Recipe<?> recipe, final StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public int getBiggestCraftableStack(final Recipe<?> recipe, final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
return this.getBiggestCraftableStack(recipe, Integer.MAX_VALUE, output);
|
||||
}
|
||||
|
||||
- public int getBiggestCraftableStack(Recipe<?> recipe, int maxCount, StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public int getBiggestCraftableStack(Recipe<?> recipe, int maxCount, StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
return this.raw.tryPickAll(recipe.placementInfo().ingredients(), maxCount, output);
|
||||
- public int getBiggestCraftableStack(final Recipe<?> recipe, final int maxSize, final StackedContents.@Nullable Output<Holder<Item>> output) {
|
||||
+ public int getBiggestCraftableStack(final Recipe<?> recipe, final int maxSize, final StackedContents.@Nullable Output<io.papermc.paper.inventory.recipe.ItemOrExact> output) { // Paper - Improve exact choice recipe ingredients
|
||||
return this.raw.tryPickAll(recipe.placementInfo().ingredients(), maxSize, output);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/item/crafting/Ingredient.java b/net/minecraft/world/item/crafting/Ingredient.java
|
||||
index ac4520afe510df9b1dd256d13dcb0768c83edb70..da95f40503f3696c8daa8fd0e947508fe43060ba 100644
|
||||
index 3a8a07712a15167dabd12d4bfd258de11706ce93..1deeb3fd148c5d59250346147681b7e8f2147574 100644
|
||||
--- a/net/minecraft/world/item/crafting/Ingredient.java
|
||||
+++ b/net/minecraft/world/item/crafting/Ingredient.java
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.world.item.Items;
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.display.SlotDisplay;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
-public final class Ingredient implements StackedContents.IngredientInfo<Holder<Item>>, Predicate<ItemStack> {
|
||||
+public final class Ingredient implements StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact>, Predicate<ItemStack> { // Paper - Improve exact choice recipe ingredients
|
||||
-public final class Ingredient implements Predicate<ItemStack>, StackedContents.IngredientInfo<Holder<Item>> {
|
||||
+public final class Ingredient implements Predicate<ItemStack>, StackedContents.IngredientInfo<io.papermc.paper.inventory.recipe.ItemOrExact> { // Paper - Improve exact choice recipe ingredients
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, Ingredient> CONTENTS_STREAM_CODEC = ByteBufCodecs.holderSet(Registries.ITEM)
|
||||
.map(Ingredient::new, ingredient -> ingredient.values);
|
||||
.map(Ingredient::new, i -> i.values);
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Ingredient>> OPTIONAL_CONTENTS_STREAM_CODEC = ByteBufCodecs.holderSet(Registries.ITEM)
|
||||
@@ -35,20 +35,24 @@ public final class Ingredient implements StackedContents.IngredientInfo<Holder<I
|
||||
@@ -34,19 +34,23 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
public static final Codec<Ingredient> CODEC = ExtraCodecs.nonEmptyHolderSet(NON_AIR_HOLDER_SET_CODEC).xmap(Ingredient::new, i -> i.values);
|
||||
public final HolderSet<Item> values;
|
||||
// CraftBukkit start
|
||||
@javax.annotation.Nullable
|
||||
- private java.util.List<ItemStack> itemStacks;
|
||||
+ private java.util.Set<ItemStack> itemStacks; // Paper - Improve exact choice recipe ingredients
|
||||
- private java.util.@org.jspecify.annotations.Nullable List<ItemStack> itemStacks;
|
||||
+ private java.util.@org.jspecify.annotations.Nullable Set<ItemStack> itemStacks; // Paper - Improve exact choice recipe ingredients
|
||||
|
||||
public boolean isExact() {
|
||||
return this.itemStacks != null;
|
||||
}
|
||||
|
||||
@javax.annotation.Nullable
|
||||
- public java.util.List<ItemStack> itemStacks() {
|
||||
+ public java.util.Set<ItemStack> itemStacks() { // Paper - Improve exact choice recipe ingredients
|
||||
- public java.util.@org.jspecify.annotations.Nullable List<ItemStack> itemStacks() {
|
||||
+ public java.util.@org.jspecify.annotations.Nullable Set<ItemStack> itemStacks() { // Paper - Improve exact choice recipe ingredients
|
||||
return this.itemStacks;
|
||||
}
|
||||
|
||||
public static Ingredient ofStacks(java.util.List<ItemStack> stacks) {
|
||||
Ingredient recipe = Ingredient.of(stacks.stream().map(ItemStack::getItem));
|
||||
- recipe.itemStacks = stacks;
|
||||
Ingredient ingredient = Ingredient.of(stacks.stream().map(ItemStack::getItem));
|
||||
- ingredient.itemStacks = stacks;
|
||||
+ // Paper start - Improve exact choice recipe ingredients
|
||||
+ recipe.itemStacks = net.minecraft.world.item.ItemStackLinkedSet.createTypeAndComponentsSet();
|
||||
+ recipe.itemStacks.addAll(stacks);
|
||||
+ recipe.itemStacks = java.util.Collections.unmodifiableSet(recipe.itemStacks);
|
||||
+ ingredient.itemStacks = net.minecraft.world.item.ItemStackLinkedSet.createTypeAndComponentsSet();
|
||||
+ ingredient.itemStacks.addAll(stacks);
|
||||
+ ingredient.itemStacks = java.util.Collections.unmodifiableSet(ingredient.itemStacks);
|
||||
+ // Paper end - Improve exact choice recipe ingredients
|
||||
return recipe;
|
||||
return ingredient;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -81,21 +85,22 @@ public final class Ingredient implements StackedContents.IngredientInfo<Holder<I
|
||||
public boolean test(ItemStack stack) {
|
||||
@@ -79,21 +83,22 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
public boolean test(final ItemStack input) {
|
||||
// CraftBukkit start
|
||||
if (this.isExact()) {
|
||||
- for (ItemStack itemstack1 : this.itemStacks()) {
|
||||
- if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameComponents(stack, itemstack1)) {
|
||||
- for (ItemStack item : this.itemStacks()) {
|
||||
- if (item.getItem() == input.getItem() && ItemStack.isSameItemSameComponents(input, item)) {
|
||||
- return true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ return this.itemStacks.contains(stack); // Paper - Improve exact choice recipe ingredients (hashing FTW!)
|
||||
+ return this.itemStacks.contains(input); // Paper - Improve exact choice recipe ingredients (hashing FTW!)
|
||||
}
|
||||
// CraftBukkit end
|
||||
return stack.is(this.values);
|
||||
return input.is(this.values);
|
||||
}
|
||||
|
||||
+ // Paper start - Improve exact choice recipe ingredients
|
||||
@Override
|
||||
- public boolean acceptsItem(Holder<Item> item) {
|
||||
- public boolean acceptsItem(final Holder<Item> item) {
|
||||
- return this.values.contains(item);
|
||||
+ public boolean acceptsItem(final io.papermc.paper.inventory.recipe.ItemOrExact itemOrExact) {
|
||||
+ return switch (itemOrExact) {
|
||||
@@ -410,26 +415,26 @@ index ac4520afe510df9b1dd256d13dcb0768c83edb70..da95f40503f3696c8daa8fd0e947508f
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,6 +125,11 @@ public final class Ingredient implements StackedContents.IngredientInfo<Holder<I
|
||||
@@ -118,6 +123,11 @@ public final class Ingredient implements Predicate<ItemStack>, StackedContents.I
|
||||
}
|
||||
|
||||
public SlotDisplay display() {
|
||||
+ // Paper start - show exact ingredients in recipe book
|
||||
+ if (this.isExact()) {
|
||||
+ return new SlotDisplay.Composite(this.itemStacks().stream().<SlotDisplay>map(SlotDisplay.ItemStackSlotDisplay::new).toList());
|
||||
+ return new SlotDisplay.Composite(this.itemStacks().stream().map(ItemStackTemplate::fromNonEmptyStack).<SlotDisplay>map(SlotDisplay.ItemStackSlotDisplay::new).toList());
|
||||
+ }
|
||||
+ // Paper end - show exact ingredients in recipe book
|
||||
return (SlotDisplay)this.values
|
||||
.unwrap()
|
||||
.map(SlotDisplay.TagSlotDisplay::new, list -> new SlotDisplay.Composite(list.stream().map(Ingredient::displayForSingleItem).toList()));
|
||||
.map(SlotDisplay.TagSlotDisplay::new, l -> new SlotDisplay.Composite(l.stream().map(Ingredient::displayForSingleItem).toList()));
|
||||
diff --git a/net/minecraft/world/item/crafting/ShapelessRecipe.java b/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
index 43c8b7a027c519196852602d136a31f8c392b786..28d085fce206634ee88c492e06fdbf63a618ee12 100644
|
||||
index d4d4fad66be0f0c0225993026602dc61e10c6bce..53a818f14709d1978dbbc4aa7367be733a8ee47f 100644
|
||||
--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
+++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
@@ -71,13 +71,18 @@ public class ShapelessRecipe implements CraftingRecipe {
|
||||
@@ -74,13 +74,18 @@ public class ShapelessRecipe extends NormalCraftingRecipe {
|
||||
|
||||
@Override
|
||||
public boolean matches(CraftingInput input, Level level) {
|
||||
public boolean matches(final CraftingInput input, final Level level) {
|
||||
+ // Paper start - Improve exact choice recipe ingredients & unwrap ternary
|
||||
if (input.ingredientCount() != this.ingredients.size()) {
|
||||
return false;
|
||||
@@ -12,11 +12,12 @@
|
||||
private volatile @Nullable PacketListener disconnectListener;
|
||||
private volatile @Nullable PacketListener packetListener;
|
||||
private @Nullable DisconnectionDetails disconnectionDetails;
|
||||
@@ -81,6 +_,43 @@
|
||||
@@ -81,6 +_,44 @@
|
||||
private boolean handlingFault;
|
||||
private volatile @Nullable DisconnectionDetails delayedDisconnect;
|
||||
private @Nullable BandwidthDebugMonitor bandwidthDebugMonitor;
|
||||
+ public String hostname = ""; // CraftBukkit - add field
|
||||
+ public boolean handleConnectionDisconnectOnNextTick = false; // Paper - Force kill connection ticking
|
||||
+ // Paper start - NetworkClient implementation
|
||||
+ public int protocolVersion;
|
||||
+ public java.net.InetSocketAddress virtualHost;
|
||||
@@ -220,7 +221,7 @@
|
||||
}
|
||||
|
||||
if (this.tickCount++ % 20 == 0) {
|
||||
@@ -391,12 +_,13 @@
|
||||
@@ -391,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void disconnect(final DisconnectionDetails details) {
|
||||
@@ -228,13 +229,6 @@
|
||||
if (this.channel == null) {
|
||||
this.delayedDisconnect = details;
|
||||
}
|
||||
|
||||
if (this.isConnected()) {
|
||||
- this.channel.close().awaitUninterruptibly();
|
||||
+ this.channel.close(); // We can't wait as this may be called from an event loop.
|
||||
this.disconnectionDetails = details;
|
||||
}
|
||||
}
|
||||
@@ -543,6 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +_,29 @@
|
||||
@@ -44,8 +_,28 @@
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
public void handle() {
|
||||
+ packetProcessing.push(this.listener); // Paper - detailed watchdog information
|
||||
+ try { // Paper - detailed watchdog information
|
||||
+ if (this.listener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // Paper - Don't handle sync packets for kicked players
|
||||
if (this.listener.shouldHandleMessage(this.packet)) {
|
||||
try {
|
||||
this.packet.handle(this.listener);
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
+ // Paper start - Validate Identifier
|
||||
+ // Check for the max network string length (capped at Short.MAX_VALUE) as well as the max bytes of a StringTag (length written as an unsigned short)
|
||||
+ final String id = namespace + ":" + path;
|
||||
+ if (id.length() > Short.MAX_VALUE || io.netty.buffer.ByteBufUtil.utf8MaxBytes(id) > 2 * Short.MAX_VALUE + 1) {
|
||||
+ throw new IdentifierException("Identifier too long: " + id);
|
||||
+ final int length = namespace.length() + path.length() + 1;
|
||||
+ if (length > Short.MAX_VALUE || io.netty.buffer.ByteBufUtil.utf8MaxBytes(length) > 2 * Short.MAX_VALUE + 1) {
|
||||
+ throw new IdentifierException("Identifier too long: " + length);
|
||||
+ }
|
||||
+ // Paper end - Validate Identifier
|
||||
this.namespace = namespace;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
OptionParser parser = new OptionParser();
|
||||
OptionSpec<Void> nogui = parser.accepts("nogui");
|
||||
OptionSpec<Void> initSettings = parser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
|
||||
@@ -89,39 +_,96 @@
|
||||
@@ -89,39 +_,95 @@
|
||||
parser.printHelpOn(System.err);
|
||||
return;
|
||||
}
|
||||
@@ -72,15 +72,14 @@
|
||||
}
|
||||
|
||||
- if (!eula.hasAgreedToEULA()) {
|
||||
+ // Spigot start
|
||||
+ // Paper start - eula system property
|
||||
+ boolean eulaAgreed = Boolean.getBoolean("com.mojang.eula.agree");
|
||||
+ if (eulaAgreed) {
|
||||
+ LOGGER.error("You have used the Spigot command line EULA agreement flag.");
|
||||
+ LOGGER.error("By using this setting you are indicating your agreement to Mojang's EULA (https://aka.ms/MinecraftEULA).");
|
||||
+ LOGGER.error("If you do not agree to the above EULA please stop your server and remove this flag immediately.");
|
||||
+ }
|
||||
+ if (!eula.hasAgreedToEULA() && !eulaAgreed) {
|
||||
+ // Spigot end
|
||||
+ LOGGER.warn("You have used the Paper command line EULA agreement flag.");
|
||||
+ LOGGER.warn("By using this setting you are indicating your agreement to Mojang's EULA (https://aka.ms/MinecraftEULA).");
|
||||
+ LOGGER.warn("If you do not agree to the above EULA please stop your server and remove this flag immediately.");
|
||||
+ } else if (!eula.hasAgreedToEULA()) {
|
||||
+ // Paper end - eula system property
|
||||
LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
if (profiledDuration != null) {
|
||||
profiledDuration.finish(true);
|
||||
}
|
||||
@@ -422,33 +_,140 @@
|
||||
@@ -422,33 +_,150 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,9 +430,9 @@
|
||||
+ );
|
||||
+ }
|
||||
+ this.addLevel(serverLevel);
|
||||
+ this.initWorld(serverLevel);
|
||||
+ this.initWorld(serverLevel, null);
|
||||
+ }
|
||||
+ public void initWorld(ServerLevel overworld) {
|
||||
+ public void initWorld(ServerLevel overworld, org.bukkit.@Nullable WorldCreator worldCreator) {
|
||||
+ final net.minecraft.world.level.storage.ServerLevelData levelData = overworld.serverLevelData;
|
||||
+ final WorldOptions worldOptions = overworld.worldGenSettings.options();
|
||||
+ final boolean isDebug = this.worldData.isDebugWorld();
|
||||
@@ -447,7 +447,17 @@
|
||||
if (!levelData.isInitialized()) {
|
||||
try {
|
||||
- setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, this.levelLoadListener);
|
||||
+ setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, overworld.levelLoadListener); // Paper - per world level load listener
|
||||
+ // Paper start - Allow direct setting spawn location
|
||||
+ if (worldCreator != null && worldCreator.forcedSpawnPosition() != null) {
|
||||
+ levelData.setSpawn(LevelData.RespawnData.of(overworld.dimension(),
|
||||
+ io.papermc.paper.util.MCUtil.toBlockPos(worldCreator.forcedSpawnPosition()),
|
||||
+ Objects.requireNonNullElse(worldCreator.forcedSpawnYaw(), LevelData.RespawnData.DEFAULT.yaw()),
|
||||
+ Objects.requireNonNullElse(worldCreator.forcedSpawnPitch(), LevelData.RespawnData.DEFAULT.pitch())
|
||||
+ ));
|
||||
+ } else {
|
||||
+ setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, overworld.levelLoadListener); // Paper - per world level load listener
|
||||
+ }
|
||||
+ // Paper end - Allow direct setting spawn location
|
||||
levelData.setInitialized(true);
|
||||
if (isDebug) {
|
||||
- this.setupDebugLevel(this.worldData);
|
||||
@@ -491,9 +501,9 @@
|
||||
+ java.util.Random rand = new java.util.Random(level.getSeed());
|
||||
+ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand);
|
||||
+
|
||||
+ if (spawn != null) {
|
||||
+ if (spawn != null && spawn.getWorld() != null) {
|
||||
+ if (spawn.getWorld() != level.getWorld()) {
|
||||
+ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + io.papermc.paper.util.MCUtil.getLevelName(level) + ")");
|
||||
+ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().key().asString() + ")");
|
||||
+ } else {
|
||||
+ levelData.setSpawn(
|
||||
+ net.minecraft.world.level.storage.LevelData.RespawnData.of(
|
||||
@@ -1086,7 +1096,7 @@
|
||||
ObjectArrayList<NameAndId> sample = new ObjectArrayList<>(sampleSize);
|
||||
int offset = Mth.nextInt(this.random, 0, players.size() - sampleSize);
|
||||
|
||||
@@ -1104,6 +_,32 @@
|
||||
@@ -1104,12 +_,46 @@
|
||||
protected void tickChildren(final BooleanSupplier haveTime) {
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
this.getPlayerList().getPlayers().forEach(playerx -> playerx.connection.suspendFlushing());
|
||||
@@ -1119,25 +1129,31 @@
|
||||
profiler.push("commandFunctions");
|
||||
this.getFunctions().tick();
|
||||
profiler.pop();
|
||||
@@ -1115,14 +_,28 @@
|
||||
|
||||
if (this.tickCount % 20 == 0) {
|
||||
profiler.push("timeSync");
|
||||
- this.forceGameTimeSynchronization();
|
||||
+ // Paper start - per-world game time
|
||||
+ for (final ServerLevel level : this.getAllLevels()) {
|
||||
+ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), Map.of()), level);
|
||||
if (this.tickRateManager.runsNormally()) {
|
||||
profiler.push("clocks");
|
||||
- this.clockManager.tick();
|
||||
+ // Paper start - per-world time
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().time.affectsAllWorlds) {
|
||||
+ this.clockManager.tick();
|
||||
+ } else {
|
||||
+ for (ServerLevel level : this.getAllLevels()) {
|
||||
+ level.clockManager().tick();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - per-world game time
|
||||
+ // Paper end - per-world time
|
||||
profiler.pop();
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
@@ -1119,10 +_,20 @@
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ // Run tasks that are waiting on processing
|
||||
+ while (!this.processQueue.isEmpty()) {
|
||||
+ this.processQueue.remove().run();
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
profiler.push("levels");
|
||||
this.updateEffectiveRespawnData();
|
||||
|
||||
@@ -1174,6 +1190,19 @@
|
||||
this.effectiveRespawnData = respawnLevel.getWorldBorderAdjustedRespawnData(respawnData);
|
||||
}
|
||||
|
||||
@@ -1179,7 +_,11 @@
|
||||
public void forceGameTimeSynchronization() {
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("timeSync");
|
||||
- this.playerList.broadcastAll(new ClientboundSetTimePacket(this.overworld().getGameTime(), Map.of()));
|
||||
+ // Paper start - per-world time
|
||||
+ for (ServerLevel level : this.getAllLevels()) {
|
||||
+ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), Map.of()), level);
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -1207,6 +_,22 @@
|
||||
return this.levels.get(dimension);
|
||||
}
|
||||
@@ -1534,7 +1563,7 @@
|
||||
player.connection.send(new ClientboundEntityEventPacket(player, event));
|
||||
}
|
||||
} else if (rule == GameRules.LIMITED_CRAFTING || rule == GameRules.IMMEDIATE_RESPAWN) {
|
||||
@@ -2131,19 +_,21 @@
|
||||
@@ -2131,20 +_,21 @@
|
||||
? ClientboundGameEventPacket.LIMITED_CRAFTING
|
||||
: ClientboundGameEventPacket.IMMEDIATE_RESPAWN;
|
||||
ClientboundGameEventPacket packet = new ClientboundGameEventPacket(eventType, (Boolean)value ? 1.0F : 0.0F);
|
||||
@@ -1556,10 +1585,11 @@
|
||||
- this.updateMobSpawningFlags();
|
||||
+ level.setSpawnSettings(level.isSpawningMonsters()); // Paper - per-world game rules
|
||||
} else if (rule == GameRules.ADVANCE_TIME) {
|
||||
+ // TODO - snapshot - time handling
|
||||
this.getPlayerList().broadcastAll(this.clockManager().createFullSyncPacket());
|
||||
- this.getPlayerList().broadcastAll(this.clockManager().createFullSyncPacket());
|
||||
+ level.players().forEach(player -> player.connection.send(level.clockManager().createFullSyncPacket(player))); // Paper - per-world time; per-player time
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2157,12 +_,14 @@
|
||||
return this.savedDataStorage;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
list.deop(player);
|
||||
count++;
|
||||
- source.sendSuccess(() -> Component.translatable("commands.deop.success", players.iterator().next().name()), true);
|
||||
+ source.sendSuccess(() -> Component.translatable("commands.deop.success", player.name()), true); // Paper - fixes MC-253721
|
||||
+ source.sendSuccess(() -> Component.translatable("commands.deop.success", player.name()), true); // Paper - fixes MC-307513
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +1,108 @@
|
||||
--- a/net/minecraft/server/commands/TimeCommand.java
|
||||
+++ b/net/minecraft/server/commands/TimeCommand.java
|
||||
@@ -170,23 +_,61 @@
|
||||
@@ -119,7 +_,7 @@
|
||||
final CommandSourceStack source, final SuggestionsBuilder builder, final Holder<WorldClock> clock
|
||||
) {
|
||||
return SharedSuggestionProvider.suggestResource(
|
||||
- source.getServer().clockManager().commandTimeMarkersForClock(clock).map(ResourceKey::identifier), builder
|
||||
+ source.getLevel().clockManager().commandTimeMarkersForClock(clock).map(ResourceKey::identifier), builder // Paper - per-world time
|
||||
);
|
||||
}
|
||||
|
||||
@@ -141,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static int queryTime(final CommandSourceStack source, final Holder<WorldClock> clock) {
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long totalTicks = clockManager.getTotalTicks(clock);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.absolute", clock.getRegisteredName(), totalTicks), false);
|
||||
return wrapTime(totalTicks);
|
||||
@@ -151,7 +_,7 @@
|
||||
if (!clock.equals(timeline.value().clock())) {
|
||||
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
|
||||
} else {
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long currentTicks = timeline.value().getCurrentTicks(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline", timeline.getRegisteredName(), currentTicks), false);
|
||||
return wrapTime(currentTicks);
|
||||
@@ -162,33 +_,53 @@
|
||||
if (!clock.equals(timeline.value().clock())) {
|
||||
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
|
||||
} else {
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager(); // Paper - per-world time
|
||||
long repetitions = timeline.value().getPeriodCount(clockManager);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline.repetitions", timeline.getRegisteredName(), repetitions), false);
|
||||
return wrapTime(repetitions);
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - per-world time
|
||||
private static int setTotalTicks(final CommandSourceStack source, final Holder<WorldClock> clock, final int totalTicks) {
|
||||
+ // Paper start
|
||||
+ // TODO - snapshot - 26.1
|
||||
+ for (net.minecraft.server.level.ServerLevel level : io.papermc.paper.configuration.GlobalConfiguration.get().commands.timeCommandAffectsAllWorlds ? source.getServer().getAllLevels() : java.util.List.of(source.getLevel())) {
|
||||
+ long currentTime = level.clockManager().getTotalTicks(clock);
|
||||
+ org.bukkit.event.world.TimeSkipEvent event = new org.bukkit.event.world.TimeSkipEvent(level.getWorld(), org.bukkit.event.world.TimeSkipEvent.SkipReason.COMMAND, totalTicks - currentTime);
|
||||
+ if (event.callEvent()) {
|
||||
+ level.clockManager().setTotalTicks(clock, currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- clockManager.setTotalTicks(clock, totalTicks);
|
||||
+ // clockManager.setTotalTicks(clock, totalTicks);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), totalTicks), true);
|
||||
return totalTicks;
|
||||
- source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), totalTicks), true);
|
||||
- return totalTicks;
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager();
|
||||
+ long currentTotalTicks = clockManager.getTotalTicks(clock);
|
||||
+ org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.createTimeSkipEvent(source, totalTicks - currentTotalTicks);
|
||||
+ final long newTotalTicks;
|
||||
+ if (event.callEvent()) {
|
||||
+ newTotalTicks = currentTotalTicks + event.getSkipAmount();
|
||||
+ clockManager.setTotalTicks(clock, newTotalTicks);
|
||||
+ } else {
|
||||
+ newTotalTicks = totalTicks; // just pass it through
|
||||
+ }
|
||||
+ source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), newTotalTicks), true);
|
||||
+ return wrapTime(newTotalTicks);
|
||||
}
|
||||
|
||||
private static int addTime(final CommandSourceStack source, final Holder<WorldClock> clock, final int time) {
|
||||
+ // Paper start
|
||||
+ // TODO - snapshot - 26.1
|
||||
+ for (net.minecraft.server.level.ServerLevel level : io.papermc.paper.configuration.GlobalConfiguration.get().commands.timeCommandAffectsAllWorlds ? source.getServer().getAllLevels() : java.util.List.of(source.getLevel())) {
|
||||
+ org.bukkit.event.world.TimeSkipEvent event = new org.bukkit.event.world.TimeSkipEvent(level.getWorld(), org.bukkit.event.world.TimeSkipEvent.SkipReason.COMMAND, time);;
|
||||
+ if (event.callEvent()) {
|
||||
+ level.clockManager().addTicks(clock, event.getSkipAmount());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- clockManager.addTicks(clock, time);
|
||||
+ // Paper - move up
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager();
|
||||
+ org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.createTimeSkipEvent(source, time);
|
||||
+ if (event.callEvent()) {
|
||||
+ clockManager.addTicks(clock, event.getSkipAmount());
|
||||
+ }
|
||||
long totalTicks = clockManager.getTotalTicks(clock);
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), totalTicks), true);
|
||||
return wrapTime(totalTicks);
|
||||
}
|
||||
|
||||
private static int setTimeToTimeMarker(final CommandSourceStack source, final Holder<WorldClock> clock, final ResourceKey<ClockTimeMarker> timeMarkerId) throws CommandSyntaxException {
|
||||
+ // Paper start
|
||||
+ // TODO - snapshot - 26.1
|
||||
+ boolean foundMarker = false;
|
||||
+ for (net.minecraft.server.level.ServerLevel level : io.papermc.paper.configuration.GlobalConfiguration.get().commands.timeCommandAffectsAllWorlds ? source.getServer().getAllLevels() : java.util.List.of(source.getLevel())) {
|
||||
+ java.util.OptionalLong targetTime = level.clockManager().getTotalTicksToTimeMarker(clock, timeMarkerId);
|
||||
+ if (targetTime.isEmpty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ foundMarker = true;
|
||||
+ long currentTime = level.clockManager().getTotalTicks(clock);
|
||||
+ long delta = targetTime.getAsLong() - currentTime;
|
||||
+ org.bukkit.event.world.TimeSkipEvent event = new org.bukkit.event.world.TimeSkipEvent(level.getWorld(), org.bukkit.event.world.TimeSkipEvent.SkipReason.COMMAND, delta);
|
||||
+ if (event.callEvent()) {
|
||||
+ level.clockManager().setTotalTicks(clock, currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- ServerClockManager clockManager = source.getServer().clockManager();
|
||||
- if (!clockManager.moveToTimeMarker(clock, timeMarkerId)) {
|
||||
+ if (!foundMarker) { // Paper
|
||||
+ // Paper start - per-world time
|
||||
+ ServerClockManager clockManager = source.getLevel().clockManager();
|
||||
+ java.util.OptionalLong targetTime = clockManager.getTotalTicksToTimeMarker(clock, timeMarkerId);
|
||||
+ if (targetTime.isEmpty()) {
|
||||
throw ERROR_NO_TIME_MARKER_FOUND.create(clock.getRegisteredName(), timeMarkerId);
|
||||
} else {
|
||||
+ final long currentTime = clockManager.getTotalTicks(clock);
|
||||
+ final org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.createTimeSkipEvent(source, targetTime.getAsLong() - currentTime);
|
||||
+ if (event.callEvent()) {
|
||||
+ clockManager.setTotalTicks(clock, currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
source.sendSuccess(
|
||||
() -> Component.translatable("commands.time.set.time_marker", clock.getRegisteredName(), timeMarkerId.identifier().toString()), true
|
||||
);
|
||||
@@ -197,13 +_,13 @@
|
||||
}
|
||||
|
||||
private static int setPaused(final CommandSourceStack source, final Holder<WorldClock> clock, final boolean paused) {
|
||||
- source.getServer().clockManager().setPaused(clock, paused);
|
||||
+ source.getLevel().clockManager().setPaused(clock, paused); // Paper - per-world time
|
||||
source.sendSuccess(() -> Component.translatable(paused ? "commands.time.pause" : "commands.time.resume", clock.getRegisteredName()), true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int setRate(final CommandSourceStack source, final Holder<WorldClock> clock, final float rate) {
|
||||
- source.getServer().clockManager().setRate(clock, rate);
|
||||
+ source.getLevel().clockManager().setRate(clock, rate); // Paper - per-world time
|
||||
source.sendSuccess(() -> Component.translatable("commands.time.rate", clock.getRegisteredName(), rate), true);
|
||||
return 1;
|
||||
}
|
||||
@@ -189,6 +189,15 @@
|
||||
this.ticketStorage.purgeStaleTickets(this.chunkMap);
|
||||
}
|
||||
|
||||
@@ -344,7 +_,7 @@
|
||||
if (!this.level.isDebug()) {
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("pollingChunks");
|
||||
- if (this.level.tickRateManager().runsNormally()) {
|
||||
+ if (this.level.tickRateManager().runsNormally() && this.level.paperConfig().unsupportedSettings.ticking.chunks) { // Paper - option to disable ticking
|
||||
profiler.push("tickingChunks");
|
||||
this.tickChunks(profiler, timeDiff);
|
||||
profiler.pop();
|
||||
@@ -376,12 +_,20 @@
|
||||
chunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
private final EntityTickList entityTickList = new EntityTickList();
|
||||
private final ServerWaypointManager waypointManager;
|
||||
private EnvironmentAttributeSystem environmentAttributes;
|
||||
@@ -221,24 +_,192 @@
|
||||
@@ -221,24 +_,199 @@
|
||||
private final boolean tickTime;
|
||||
private final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
+ private final WeatherData weatherData;
|
||||
+ public final net.minecraft.world.level.timers.TimerQueue<net.minecraft.server.MinecraftServer> scheduledEvents;
|
||||
+ public final WorldGenSettings worldGenSettings;
|
||||
+ private @Nullable ServerClockManager clockManager;
|
||||
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
||||
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
+
|
||||
@@ -184,6 +185,12 @@
|
||||
this.serverLevelData = levelData;
|
||||
ChunkGenerator generator = levelStem.generator();
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - per-world time
|
||||
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().time.affectsAllWorlds) {
|
||||
+ this.clockManager = savedDataStorage.computeIfAbsent(net.minecraft.world.clock.ServerClockManager.TYPE); // Paper - per-world time
|
||||
+ this.clockManager.init(server, this); // Paper - per-world time
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
+ if (loadedWorldData.pdc() != null) {
|
||||
+ this.getWorld().readBukkitValues(loadedWorldData.pdc().persistentData().toTagCompound());
|
||||
+ }
|
||||
@@ -262,30 +269,39 @@
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
@@ -322,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public ServerClockManager clockManager() {
|
||||
- return this.server.clockManager();
|
||||
+ return io.papermc.paper.configuration.GlobalConfiguration.get().time.affectsAllWorlds ? this.server.clockManager() : this.clockManager; // Paper - per-world time
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -354,11 +_,24 @@
|
||||
int percentage = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (this.sleepStatus.areEnoughSleeping(percentage) && this.sleepStatus.areEnoughDeepSleeping(percentage, this.players)) {
|
||||
Optional<Holder<WorldClock>> defaultClock = this.dimensionType().defaultClock();
|
||||
+ org.bukkit.event.world.TimeSkipEvent event = null; // Paper - time skip event
|
||||
+ org.bukkit.event.world.ClockTimeSkipEvent event = null; // Paper - per-world time
|
||||
if (this.getGameRules().get(GameRules.ADVANCE_TIME) && defaultClock.isPresent()) {
|
||||
- this.server.clockManager().moveToTimeMarker(defaultClock.get(), ClockTimeMarkers.WAKE_UP_FROM_SLEEP);
|
||||
+ // Paper start - time skip event
|
||||
+ long currentTime = this.server.clockManager().getTotalTicks(defaultClock.get());
|
||||
+ long delta = this.server.clockManager().getTotalTicksToTimeMarker(defaultClock.get(), ClockTimeMarkers.WAKE_UP_FROM_SLEEP).orElse(0L) - currentTime;
|
||||
+ // Paper start - per-world time
|
||||
+ long currentTime = this.clockManager().getTotalTicks(defaultClock.get());
|
||||
+ long delta = this.clockManager().getTotalTicksToTimeMarker(defaultClock.get(), ClockTimeMarkers.WAKE_UP_FROM_SLEEP).orElse(0L) - currentTime;
|
||||
+ event = new org.bukkit.event.world.TimeSkipEvent(
|
||||
+ this.getWorld(),
|
||||
+ org.bukkit.event.world.TimeSkipEvent.SkipReason.NIGHT_SKIP,
|
||||
+ org.bukkit.event.world.ClockTimeSkipEvent.SkipReason.NIGHT_SKIP,
|
||||
+ delta
|
||||
+ );
|
||||
+
|
||||
+ if (event.callEvent()) {
|
||||
+ this.server.clockManager().setTotalTicks(defaultClock.get(), currentTime + event.getSkipAmount()); // TODO - snapshot - per world time
|
||||
+ this.clockManager().setTotalTicks(defaultClock.get(), currentTime + event.getSkipAmount());
|
||||
+ }
|
||||
+ // Paper end - time skip event
|
||||
+ // Paper end - per-world time
|
||||
}
|
||||
|
||||
- this.wakeUpAllPlayers();
|
||||
+ if (event == null || !event.isCancelled()) this.wakeUpAllPlayers(); // Paper - time skip event - only wake up players if time skip event is not cancelled
|
||||
+ if (event == null || !event.isCancelled()) this.wakeUpAllPlayers(); // Paper - per-world time - only wake up players if time skip event is not cancelled
|
||||
if (this.getGameRules().get(GameRules.ADVANCE_WEATHER) && this.isRaining()) {
|
||||
this.resetWeatherCycle();
|
||||
}
|
||||
@@ -310,6 +326,19 @@
|
||||
if (isActive) {
|
||||
this.resetEmptyTime();
|
||||
}
|
||||
@@ -437,9 +_,12 @@
|
||||
}
|
||||
}
|
||||
);
|
||||
+ if (this.paperConfig().unsupportedSettings.ticking.blockEntities) { // Paper - option to disable ticking
|
||||
profiler.popPush("blockEntities");
|
||||
this.tickBlockEntities();
|
||||
profiler.pop();
|
||||
+ } // Paper - option to disable ticking
|
||||
+ this.spigotConfig.currentPrimedTnt = 0; // Spigot
|
||||
}
|
||||
|
||||
profiler.push("entityManagement");
|
||||
@@ -468,7 +_,7 @@
|
||||
long time = this.levelData.getGameTime() + 1L;
|
||||
this.serverLevelData.setGameTime(time);
|
||||
@@ -987,16 +1016,15 @@
|
||||
this.getServer().getDataStorage().set(MapItemSavedData.type(id), data);
|
||||
}
|
||||
|
||||
@@ -1492,7 +_,21 @@
|
||||
@@ -1492,7 +_,20 @@
|
||||
|
||||
@Override
|
||||
public void setRespawnData(final LevelData.RespawnData respawnData) {
|
||||
- this.getServer().setRespawnData(respawnData);
|
||||
+ // Paper start
|
||||
+ final LevelData.RespawnData previousRespawnData = this.serverLevelData.getRespawnData();
|
||||
+ this.serverLevelData.setSpawn(respawnData);
|
||||
+ if (!previousRespawnData.positionEquals(respawnData)) {
|
||||
+ if (!this.serverLevelData.getRespawnData().positionEquals(respawnData)) {
|
||||
+ org.bukkit.Location previousLocation = this.getWorld().getSpawnLocation();
|
||||
+ this.serverLevelData.setSpawn(respawnData);
|
||||
+ this.server.getPlayerList().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket(respawnData), this.dimension());
|
||||
+ this.server.updateEffectiveRespawnData();
|
||||
+ new org.bukkit.event.world.SpawnChangeEvent(this.getWorld(), previousLocation).callEvent();
|
||||
|
||||
+7
-11
@@ -9,13 +9,12 @@
|
||||
private final boolean transferred;
|
||||
private long keepAliveTime;
|
||||
private boolean keepAlivePending;
|
||||
@@ -46,6 +_,17 @@
|
||||
@@ -46,6 +_,16 @@
|
||||
private boolean closed = false;
|
||||
private int latency;
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
+ // CraftBukkit start
|
||||
+ public final org.bukkit.craftbukkit.CraftServer cserver;
|
||||
+ public boolean processedDisconnect;
|
||||
+ // CraftBukkit end
|
||||
+ public final java.util.Map<java.util.UUID, net.kyori.adventure.resource.ResourcePackCallback> packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
|
||||
+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
@@ -210,7 +209,7 @@
|
||||
|
||||
public void send(final Packet<?> packet, final @Nullable ChannelFutureListener listener) {
|
||||
+ // CraftBukkit start
|
||||
+ if (packet == null || this.processedDisconnect) { // Spigot
|
||||
+ if (packet == null) {
|
||||
+ return;
|
||||
+ } else if (packet instanceof net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket defaultSpawnPositionPacket && this instanceof ServerGamePacketListenerImpl serverGamePacketListener) {
|
||||
+ serverGamePacketListener.player.compassTarget = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(defaultSpawnPositionPacket.respawnData().pos(), serverGamePacketListener.getPlayer().level());
|
||||
@@ -219,7 +218,7 @@
|
||||
if (packet.isTerminal()) {
|
||||
this.close();
|
||||
}
|
||||
@@ -174,15 +_,111 @@
|
||||
@@ -174,15 +_,108 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,13 +236,13 @@
|
||||
|
||||
public void disconnect(final DisconnectionDetails details) {
|
||||
+ // CraftBukkit start - fire PlayerKickEvent
|
||||
+ if (this.processedDisconnect) {
|
||||
+ if (!this.connection.isConnected()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!this.cserver.isPrimaryThread()) {
|
||||
+ org.bukkit.craftbukkit.util.Waitable waitable = new org.bukkit.craftbukkit.util.Waitable() {
|
||||
+ @Override
|
||||
+ protected Object evaluate() {
|
||||
+ protected @Nullable Object evaluate() {
|
||||
+ ServerCommonPacketListenerImpl.this.disconnect(details);
|
||||
+ return null;
|
||||
+ }
|
||||
@@ -285,7 +284,7 @@
|
||||
+ }
|
||||
+
|
||||
+ reason = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.reason());
|
||||
+ leaveMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.leaveMessage());
|
||||
+ leaveMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.leaveMessage());
|
||||
+ serverGamePacketListener.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - Add API for quit reason
|
||||
+ // Log kick to console *after* event was processed.
|
||||
+ switch (cause) {
|
||||
@@ -303,14 +302,11 @@
|
||||
+ }
|
||||
+
|
||||
+ private void disconnect0(final DisconnectionDetails details) {
|
||||
+ // CraftBukkit end
|
||||
this.connection.send(new ClientboundDisconnectPacket(details.reason()), PacketSendListener.thenRun(() -> this.connection.disconnect(details)));
|
||||
+ this.onDisconnect(details); // CraftBukkit - fire quit instantly
|
||||
this.connection.setReadOnly();
|
||||
- this.server.executeBlocking(this.connection::handleDisconnection);
|
||||
- }
|
||||
+ // CraftBukkit - Don't wait
|
||||
+ this.server.scheduleOnMain(this.connection::handleDisconnection); // Paper
|
||||
+ this.connection.handleConnectionDisconnectOnNextTick = true; // Paper - Force kill connection ticking. Let this close the connection
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - add proper async disconnect
|
||||
|
||||
+14
-1
@@ -100,7 +100,7 @@
|
||||
public SocketAddress startMemoryChannel() {
|
||||
ChannelFuture newChannel;
|
||||
synchronized (this.channels) {
|
||||
@@ -151,6 +_,13 @@
|
||||
@@ -151,12 +_,26 @@
|
||||
|
||||
public void tick() {
|
||||
synchronized (this.connections) {
|
||||
@@ -114,6 +114,19 @@
|
||||
Iterator<Connection> iterator = this.connections.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Connection connection = iterator.next();
|
||||
if (!connection.isConnecting()) {
|
||||
if (connection.isConnected()) {
|
||||
+ // Paper start - Force kill connection ticking
|
||||
+ // also call this multiple times, doesnt matter
|
||||
+ // See MC-307764
|
||||
+ if (connection.handleConnectionDisconnectOnNextTick) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - Force kill connection ticking
|
||||
try {
|
||||
connection.tick();
|
||||
} catch (Exception var7) {
|
||||
@@ -170,6 +_,7 @@
|
||||
connection.setReadOnly();
|
||||
}
|
||||
|
||||
+12
-17
@@ -83,7 +83,7 @@
|
||||
|
||||
public ServerGamePacketListenerImpl(final MinecraftServer server, final Connection connection, final ServerPlayer player, final CommonListenerCookie cookie) {
|
||||
super(server, connection, cookie);
|
||||
@@ -284,11 +_,26 @@
|
||||
@@ -284,8 +_,22 @@
|
||||
player.connection = this;
|
||||
player.getTextFilter().join();
|
||||
this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile);
|
||||
@@ -108,10 +108,6 @@
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ if (this.isDisconnected()) return; // Paper
|
||||
if (this.ackBlockChangesUpTo > -1) {
|
||||
this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo));
|
||||
this.ackBlockChangesUpTo = -1;
|
||||
@@ -298,11 +_,13 @@
|
||||
this.keepConnectionAlive();
|
||||
this.chatSpamThrottler.tick();
|
||||
@@ -1356,17 +1352,9 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1453,24 +_,50 @@
|
||||
|
||||
@@ -1454,23 +_,42 @@
|
||||
@Override
|
||||
public void onDisconnect(final DisconnectionDetails details) {
|
||||
+ // CraftBukkit start - Rarely it would send a disconnect line twice
|
||||
+ if (this.processedDisconnect) {
|
||||
+ return;
|
||||
+ } else {
|
||||
+ this.processedDisconnect = true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
LOGGER.info("{} lost connection: {}", this.player.getPlainTextName(), details.reason().getString());
|
||||
- this.removePlayerFromWorld();
|
||||
+ // Paper start - Fix kick event leave message not being sent
|
||||
@@ -2510,7 +2498,7 @@
|
||||
if (this.player.isModelPartShown(PlayerModelPart.HAT) != wasHatShown) {
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT, this.player));
|
||||
}
|
||||
@@ -2082,7 +_,7 @@
|
||||
@@ -2082,21 +_,21 @@
|
||||
packet.difficulty().getDisplayName()
|
||||
);
|
||||
} else {
|
||||
@@ -2519,7 +2507,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2096,7 +_,7 @@
|
||||
@Override
|
||||
public void handleChangeGameMode(final ServerboundChangeGameModePacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
|
||||
- if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions())) {
|
||||
+ if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions()) && !this.player.getBukkitEntity().hasPermission("minecraft.command.gamemode")) { // Paper - add permission check
|
||||
LOGGER.warn(
|
||||
"Player {} tried to change game mode to {} without required permissions",
|
||||
this.player.getGameProfile().name(),
|
||||
packet.mode().getShortDisplayName().getString()
|
||||
);
|
||||
} else {
|
||||
@@ -2664,7 +2659,7 @@
|
||||
+ }
|
||||
+
|
||||
+ public final boolean isDisconnected() {
|
||||
+ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper - Fix duplication bugs
|
||||
+ return (!this.player.joining && !this.connection.isConnected());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
|
||||
+33
-25
@@ -13,11 +13,11 @@
|
||||
public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener {
|
||||
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("User Authenticator #%d").setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)).build()); // Paper - Cache authenticator threads
|
||||
+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("User Authenticator #", 0).uncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)).factory()); // Paper - Virtual authenticator threads
|
||||
private static final int MAX_TICKS_BEFORE_LOGIN = 600;
|
||||
private final byte[] challenge;
|
||||
private final MinecraftServer server;
|
||||
@@ -56,10 +_,15 @@
|
||||
@@ -56,10 +_,14 @@
|
||||
private final ServerActivityMonitor serverActivityMonitor;
|
||||
public volatile ServerLoginPacketListenerImpl.State state = ServerLoginPacketListenerImpl.State.HELLO;
|
||||
private int tick;
|
||||
@@ -31,11 +31,10 @@
|
||||
+ private int velocityLoginMessageId = -1; // Paper - Add Velocity IP Forwarding Support
|
||||
+ public java.util.@Nullable UUID requestedUuid; // Paper
|
||||
+ private final io.papermc.paper.connection.PaperPlayerLoginConnection paperLoginConnection; // Paper - Config API
|
||||
+ private volatile boolean disconnecting = false; // Paper - Fix disconnect still ticking login
|
||||
|
||||
public ServerLoginPacketListenerImpl(final MinecraftServer minecraftserver, final Connection connection, final boolean transferred) {
|
||||
this.server = minecraftserver;
|
||||
@@ -67,10 +_,20 @@
|
||||
@@ -67,10 +_,19 @@
|
||||
this.serverActivityMonitor = this.server.getServerActivityMonitor();
|
||||
this.challenge = Ints.toByteArray(RandomSource.create().nextInt());
|
||||
this.transferred = transferred;
|
||||
@@ -44,7 +43,6 @@
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ if (this.disconnecting) return; // Paper - Fix disconnect being called multiple times due to not awaiting for disconnect
|
||||
+ // Paper start - login cookie API
|
||||
+ // Don't block the connection
|
||||
+ if (this.paperLoginConnection.isAwaitingCookies()) {
|
||||
@@ -56,7 +54,7 @@
|
||||
if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) {
|
||||
this.verifyLoginAndFinishConnectionSetup(Objects.requireNonNull(this.authenticatedProfile));
|
||||
}
|
||||
@@ -80,11 +_,23 @@
|
||||
@@ -80,16 +_,39 @@
|
||||
this.finishLoginAndWaitForClient(this.authenticatedProfile);
|
||||
}
|
||||
|
||||
@@ -66,28 +64,37 @@
|
||||
+ public void tickTimeout() {
|
||||
+ // Paper end - login cookie API
|
||||
if (this.tick++ == 600) {
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.slow_login"));
|
||||
- this.disconnect(Component.translatable("multiplayer.disconnect.slow_login"));
|
||||
+ this.disconnectAsync(Component.translatable("multiplayer.disconnect.slow_login")); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ @Deprecated
|
||||
+ public void disconnect(String reason) {
|
||||
+ this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(reason))); // Paper - Fix hex colors not working in some kick messages
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
@Override
|
||||
public boolean isAcceptingMessages() {
|
||||
return this.connection.isConnected();
|
||||
@@ -95,6 +_,7 @@
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void disconnectAsync(Component reason) {
|
||||
+ try {
|
||||
+ LOGGER.info("Disconnecting {}: {}", this.getUserName(), reason.getString());
|
||||
+ this.connection.send(new ClientboundLoginDisconnectPacket(reason), PacketSendListener.thenRun(() -> this.connection.disconnect(reason)));
|
||||
+ this.connection.handleConnectionDisconnectOnNextTick = true;
|
||||
+ } catch (Exception var3) {
|
||||
+ LOGGER.error("Error whilst disconnecting player", (Throwable)var3);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
public void disconnect(final Component component) {
|
||||
try {
|
||||
LOGGER.info("Disconnecting {}: {}", this.getUserName(), component.getString());
|
||||
this.connection.send(new ClientboundLoginDisconnectPacket(component));
|
||||
this.connection.disconnect(component);
|
||||
+ this.disconnecting = true; // Paper - Fix disconnect still ticking login
|
||||
} catch (Exception var3) {
|
||||
LOGGER.error("Error whilst disconnecting player", (Throwable)var3);
|
||||
}
|
||||
@@ -117,7 +_,14 @@
|
||||
@Override
|
||||
public void handleHello(final ServerboundHelloPacket packet) {
|
||||
@@ -104,7 +111,7 @@
|
||||
this.requestedUsername = packet.name();
|
||||
GameProfile singleplayerProfile = this.server.getSingleplayerProfile();
|
||||
if (singleplayerProfile != null && this.requestedUsername.equalsIgnoreCase(singleplayerProfile.name())) {
|
||||
@@ -127,7 +_,32 @@
|
||||
@@ -127,7 +_,30 @@
|
||||
this.state = ServerLoginPacketListenerImpl.State.KEY;
|
||||
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge, true));
|
||||
} else {
|
||||
@@ -119,8 +126,7 @@
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Add Velocity IP Forwarding Support
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - Cache authenticator threads
|
||||
+ // Paper start - Virtual authenticator threads
|
||||
+ authenticatorPool.execute(() -> {
|
||||
+ try {
|
||||
+ GameProfile gameprofile = ServerLoginPacketListenerImpl.this.createOfflineProfile(ServerLoginPacketListenerImpl.this.requestedUsername); // Spigot
|
||||
@@ -133,20 +139,22 @@
|
||||
+ ServerLoginPacketListenerImpl.this.server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + ServerLoginPacketListenerImpl.this.requestedUsername, ex);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - Cache authenticator threads
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Virtual authenticator threads
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,7 +_,7 @@
|
||||
@@ -139,9 +_,9 @@
|
||||
|
||||
private void verifyLoginAndFinishConnectionSetup(final GameProfile profile) {
|
||||
PlayerList playerList = this.server.getPlayerList();
|
||||
- Component error = playerList.canPlayerLogin(this.connection.getRemoteAddress(), new NameAndId(profile));
|
||||
+ Component error = org.bukkit.craftbukkit.event.CraftEventFactory.handleLoginResult(playerList.canPlayerLogin(this.connection.getRemoteAddress(), new NameAndId(profile)), this.paperLoginConnection, this.connection, profile, this.server, true); // Paper
|
||||
if (error != null) {
|
||||
this.disconnect(error);
|
||||
- this.disconnect(error);
|
||||
+ this.disconnectAsync(error); // Paper
|
||||
} else {
|
||||
if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) {
|
||||
this.connection
|
||||
@@ -151,7 +_,7 @@
|
||||
);
|
||||
}
|
||||
@@ -169,7 +177,7 @@
|
||||
}
|
||||
|
||||
- Thread thread = new Thread("User Authenticator #" + UNIQUE_THREAD_ID.incrementAndGet()) {
|
||||
+ // Paper start - Cache authenticator threads
|
||||
+ // Paper start - Virtual authenticator threads
|
||||
+ authenticatorPool.execute(new Runnable() {
|
||||
{
|
||||
Objects.requireNonNull(ServerLoginPacketListenerImpl.this);
|
||||
@@ -222,7 +230,7 @@
|
||||
- thread.start();
|
||||
- }
|
||||
+ });
|
||||
+ // Paper end - Cache authenticator threads
|
||||
+ // Paper end - Virtual authenticator threads
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@
|
||||
+ );
|
||||
+ ev.callEvent();
|
||||
+ spawnPosition = io.papermc.paper.util.MCUtil.toVec3(ev.getSpawnLocation());
|
||||
+ this.spawnLevel = ((org.bukkit.craftbukkit.CraftWorld) ev.getSpawnLocation().getWorld()).getHandle();
|
||||
+ if (ev.getSpawnLocation().getWorld() != null) this.spawnLevel = ((org.bukkit.craftbukkit.CraftWorld) ev.getSpawnLocation().getWorld()).getHandle();
|
||||
+ this.spawnPosition = CompletableFuture.completedFuture(spawnPosition);
|
||||
+ this.spawnAngle = new Vec2(ev.getSpawnLocation().getYaw(), ev.getSpawnLocation().getPitch());
|
||||
+ }
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -296,64 +_,148 @@
|
||||
@@ -296,64 +_,147 @@
|
||||
}
|
||||
|
||||
protected void save(final ServerPlayer player) {
|
||||
@@ -310,7 +310,6 @@
|
||||
+ this.cserver.getPluginManager().callEvent(playerQuitEvent);
|
||||
+ player.getBukkitEntity().disconnect();
|
||||
+
|
||||
+ if (this.server.isSameThread()) player.doTick(); // SPIGOT-924 // Paper - Improved watchdog support; don't tick during emergency shutdowns
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start - Configurable player collision; Remove from collideRule team if needed
|
||||
@@ -741,9 +740,12 @@
|
||||
}
|
||||
|
||||
public UserWhiteList getWhiteList() {
|
||||
@@ -654,10 +_,18 @@
|
||||
@@ -652,12 +_,20 @@
|
||||
public void sendLevelInfo(final ServerPlayer player, final ServerLevel level) {
|
||||
WorldBorder worldBorder = level.getWorldBorder();
|
||||
player.connection.send(new ClientboundInitializeBorderPacket(worldBorder));
|
||||
player.connection.send(this.server.clockManager().createFullSyncPacket());
|
||||
- player.connection.send(this.server.clockManager().createFullSyncPacket());
|
||||
+ player.connection.send(level.clockManager().createFullSyncPacket(player)); // Paper - per-world time; per-player time
|
||||
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getRespawnData()));
|
||||
+ // Paper start - view distances
|
||||
+ player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level)));
|
||||
|
||||
+102
-22
@@ -1,5 +1,35 @@
|
||||
--- a/net/minecraft/world/clock/ServerClockManager.java
|
||||
+++ b/net/minecraft/world/clock/ServerClockManager.java
|
||||
@@ -30,6 +_,7 @@
|
||||
);
|
||||
private final PackedClockStates packedClockStates;
|
||||
private MinecraftServer server;
|
||||
+ private @org.jspecify.annotations.Nullable ServerLevel level; // Paper - per-world time
|
||||
private final Map<Holder<WorldClock>, ServerClockManager.ClockInstance> clocks = new HashMap<>();
|
||||
|
||||
private ServerClockManager(final PackedClockStates packedClockStates) {
|
||||
@@ -37,6 +_,12 @@
|
||||
}
|
||||
|
||||
public void init(final MinecraftServer server) {
|
||||
+ // Paper start - per-world time
|
||||
+ this.init(server, null);
|
||||
+ }
|
||||
+ public void init(final MinecraftServer server, @org.jspecify.annotations.Nullable final ServerLevel level) {
|
||||
+ this.level = level;
|
||||
+ // Paper end - per-world time
|
||||
this.server = server;
|
||||
server.registryAccess()
|
||||
.lookupOrThrow(Registries.WORLD_CLOCK)
|
||||
@@ -61,7 +_,7 @@
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
- boolean advanceTime = this.server.getGlobalGameRules().get(GameRules.ADVANCE_TIME);
|
||||
+ boolean advanceTime = this.advanceTime(); // Paper - per-world time
|
||||
if (advanceTime) {
|
||||
this.clocks.values().forEach(ServerClockManager.ClockInstance::tick);
|
||||
this.setDirty();
|
||||
@@ -97,7 +_,16 @@
|
||||
return set.booleanValue();
|
||||
}
|
||||
@@ -18,36 +48,86 @@
|
||||
this.modifyClock(clock, instance -> instance.totalTicks = Math.max(instance.totalTicks + ticks, 0L));
|
||||
}
|
||||
|
||||
@@ -113,7 +_,7 @@
|
||||
@@ -112,13 +_,18 @@
|
||||
private void modifyClock(final Holder<WorldClock> clock, final Consumer<? super ServerClockManager.ClockInstance> action) {
|
||||
ServerClockManager.ClockInstance instance = this.getInstance(clock);
|
||||
action.accept(instance);
|
||||
Map<Holder<WorldClock>, ClockNetworkState> updates = Map.of(clock, instance.packNetworkState(this.server));
|
||||
- Map<Holder<WorldClock>, ClockNetworkState> updates = Map.of(clock, instance.packNetworkState(this.server));
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates));
|
||||
+ this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates)); // TODO 26.1 per-player time
|
||||
+ // Paper start - per-world time
|
||||
+ this.broadcastUpdates(clock, instance);
|
||||
this.setDirty();
|
||||
|
||||
+ if (this.level != null) {
|
||||
+ this.level.environmentAttributes().invalidateTickCache();
|
||||
+ } else {
|
||||
for (ServerLevel level : this.server.getAllLevels()) {
|
||||
@@ -126,7 +_,23 @@
|
||||
return this.getInstance(definition).totalTicks;
|
||||
level.environmentAttributes().invalidateTickCache();
|
||||
}
|
||||
+ }
|
||||
+ // Paper end - per-world time
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,12 +_,48 @@
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ // TODO - snapshot: just make the inner class, fields and getter public
|
||||
+ public boolean isPaused(final Holder<WorldClock> definition) {
|
||||
+ return this.getInstance(definition).paused;
|
||||
+ }
|
||||
+
|
||||
+ public float partialTick(final Holder<WorldClock> definition) {
|
||||
+ return this.getInstance(definition).partialTick;
|
||||
+ }
|
||||
+
|
||||
+ public float rate(final Holder<WorldClock> definition) {
|
||||
+ return this.getInstance(definition).rate;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public ClientboundSetTimePacket createFullSyncPacket() {
|
||||
+ // TODO - snapshot: 26.1 per-player time
|
||||
return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.server)));
|
||||
- return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.server)));
|
||||
+ // Paper start - per-player time
|
||||
+ return this.createFullSyncPacket(null);
|
||||
+ }
|
||||
+
|
||||
+ public ClientboundSetTimePacket createFullSyncPacket(final net.minecraft.server.level.ServerPlayer player) {
|
||||
+ final Map<Holder<WorldClock>, ClockNetworkState> updates = new HashMap<>(this.clocks.size());
|
||||
+ this.clocks.forEach((clock, instance) -> updates.put(clock, this.packNetworkState(clock, instance, player)));
|
||||
+ return new ClientboundSetTimePacket(this.getGameTime(), updates);
|
||||
+ // Paper end - per-player time
|
||||
}
|
||||
|
||||
private long getGameTime() {
|
||||
- return this.server.overworld().getGameTime();
|
||||
- }
|
||||
+ return this.level != null ? this.level.getGameTime() : this.server.overworld().getGameTime(); // Paper - per-world time
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - per-world time; per-player time
|
||||
+ private void broadcastUpdates(final Holder<WorldClock> clock, final ServerClockManager.ClockInstance instance) {
|
||||
+ for (final net.minecraft.server.level.ServerPlayer player : this.level != null ? this.level.players() : this.server.getPlayerList().getPlayers()) {
|
||||
+ final var packet = new net.minecraft.network.protocol.game.ClientboundSetTimePacket(
|
||||
+ this.getGameTime(),
|
||||
+ java.util.Map.of(clock, this.packNetworkState(clock, instance, player))
|
||||
+ );
|
||||
+ player.connection.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private ClockNetworkState packNetworkState(
|
||||
+ final Holder<WorldClock> clock,
|
||||
+ final ServerClockManager.ClockInstance instance,
|
||||
+ final net.minecraft.server.level.ServerPlayer player
|
||||
+ ) {
|
||||
+ if (player != null && player.level().dimensionType().defaultClock().filter(clock::equals).isPresent()) {
|
||||
+ final boolean paused = !player.relativeTime || instance.paused || !this.advanceTime();
|
||||
+ return new ClockNetworkState(player.getPlayerTime(), instance.partialTick, paused ? 0.0F : instance.rate);
|
||||
+ }
|
||||
+ return instance.packNetworkState(this.advanceTime());
|
||||
+ }
|
||||
+
|
||||
+ private boolean advanceTime() {
|
||||
+ return this.level != null ? this.level.getGameRules().get(GameRules.ADVANCE_TIME) : this.server.getGlobalGameRules().get(GameRules.ADVANCE_TIME);
|
||||
+ }
|
||||
+ // Paper end - per-world time; per-player time
|
||||
|
||||
public boolean isAtTimeMarker(final Holder<WorldClock> clock, final ResourceKey<ClockTimeMarker> timeMarkerId) {
|
||||
ServerClockManager.ClockInstance clockInstance = this.getInstance(clock);
|
||||
@@ -171,8 +_,7 @@
|
||||
return new ClockState(this.totalTicks, this.partialTick, this.rate, this.paused);
|
||||
}
|
||||
|
||||
- public ClockNetworkState packNetworkState(final MinecraftServer server) {
|
||||
- boolean advanceTime = server.getGlobalGameRules().get(GameRules.ADVANCE_TIME);
|
||||
+ public ClockNetworkState packNetworkState(final boolean advanceTime) { // Paper - per-world time
|
||||
boolean paused = this.paused || !advanceTime;
|
||||
return new ClockNetworkState(this.totalTicks, this.partialTick, paused ? 0.0F : this.rate);
|
||||
}
|
||||
+18
-1
@@ -1,6 +1,14 @@
|
||||
--- a/net/minecraft/world/damagesource/CombatTracker.java
|
||||
+++ b/net/minecraft/world/damagesource/CombatTracker.java
|
||||
@@ -29,15 +_,24 @@
|
||||
@@ -22,22 +_,40 @@
|
||||
private static final Style INTENTIONAL_GAME_DESIGN_STYLE = Style.EMPTY
|
||||
.withClickEvent(new ClickEvent.OpenUrl(CommonLinks.INTENTIONAL_GAME_DESIGN_BUG))
|
||||
.withHoverEvent(new HoverEvent.ShowText(Component.literal("MCPE-28723")));
|
||||
- public final List<CombatEntry> entries = Lists.newArrayList();
|
||||
+ public final List<CombatEntry> entries = new net.minecraft.util.ArrayListDeque<>(); // Paper - Fix mem leak (MC-301114); Use ArrayListDeque
|
||||
public final LivingEntity mob;
|
||||
private int lastDamageTime;
|
||||
private int combatStartTime;
|
||||
private int combatEndTime;
|
||||
public boolean inCombat;
|
||||
public boolean takingDamage;
|
||||
@@ -22,6 +30,15 @@
|
||||
+ public void recordDamageAndCheckCombatState(final CombatEntry entry) {
|
||||
+ final DamageSource source = entry.source();
|
||||
+ // Paper end - Combat tracker API
|
||||
+ // Paper start - Fix mem leak (MC-301114)
|
||||
+ final io.papermc.paper.configuration.type.number.IntOr.Disabled maxTrackingCombatEntries;
|
||||
+ if (!this.entries.isEmpty() && (maxTrackingCombatEntries = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxTrackingCombatEntries).enabled()) {
|
||||
+ final int maxEntries = maxTrackingCombatEntries.intValue();
|
||||
+ while (this.entries.size() > maxEntries) {
|
||||
+ this.entries.removeFirst();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Fix mem leak (MC-301114)
|
||||
this.entries.add(entry);
|
||||
this.lastDamageTime = this.mob.tickCount;
|
||||
this.takingDamage = true;
|
||||
|
||||
@@ -1355,7 +1355,7 @@
|
||||
this.setTicksFrozen(0);
|
||||
}
|
||||
|
||||
@@ -2762,11 +_,43 @@
|
||||
@@ -2762,11 +_,42 @@
|
||||
|
||||
public void thunderHit(final ServerLevel level, final LightningBolt lightningBolt) {
|
||||
this.setRemainingFireTicks(this.remainingFireTicks + 1);
|
||||
@@ -1383,11 +1383,10 @@
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ final DamageSource damageSource = this.damageSources().lightningBolt().eventEntityDamager(lightningBolt);
|
||||
+ if (thisBukkitEntity instanceof org.bukkit.entity.Hanging) {
|
||||
+ org.bukkit.event.hanging.HangingBreakByEntityEvent hangingEvent = new org.bukkit.event.hanging.HangingBreakByEntityEvent((org.bukkit.entity.Hanging) thisBukkitEntity, stormBukkitEntity);
|
||||
+ pluginManager.callEvent(hangingEvent);
|
||||
+
|
||||
+ if (hangingEvent.isCancelled()) {
|
||||
+ org.bukkit.event.hanging.HangingBreakByEntityEvent hangingEvent = new org.bukkit.event.hanging.HangingBreakByEntityEvent((org.bukkit.entity.Hanging) thisBukkitEntity, stormBukkitEntity, new org.bukkit.craftbukkit.damage.CraftDamageSource(damageSource));
|
||||
+ if (!hangingEvent.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
@@ -1396,7 +1395,7 @@
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!this.hurtServer(level, this.damageSources().lightningBolt().eventEntityDamager(lightningBolt), 5.0F)) { // Paper - fix DamageSource API
|
||||
+ if (!this.hurtServer(level, damageSource, 5.0F)) { // Paper - fix DamageSource API
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(
|
||||
+ entity.getBukkitEntity(),
|
||||
+ !entity.isAlive() ? org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.HOLDER_GONE,
|
||||
+ !entity.isAlive() ? org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.LEASHED_GONE : org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.HOLDER_GONE,
|
||||
+ level.getGameRules().get(GameRules.ENTITY_DROPS) && !entity.pluginRemoved
|
||||
+ );
|
||||
+ event.callEvent();
|
||||
|
||||
@@ -1053,7 +1053,7 @@
|
||||
int absorbValue = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5;
|
||||
int absorb = 25 - absorbValue;
|
||||
float v = damage * absorb;
|
||||
@@ -1915,24 +_,194 @@
|
||||
@@ -1915,24 +_,181 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,19 +1147,6 @@
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (source.getEntity() instanceof net.minecraft.world.entity.player.Player) {
|
||||
+ // Paper start - PlayerAttackEntityCooldownResetEvent
|
||||
+ //((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetOnlyAttackStrengthTicker(); // Moved from Player in order to make the cooldown reset get called after the damage event is fired
|
||||
+ if (source.getEntity() instanceof ServerPlayer player) {
|
||||
+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackStrengthScale(0F)).callEvent()) {
|
||||
+ player.resetOnlyAttackStrengthTicker();
|
||||
+ }
|
||||
+ } else {
|
||||
+ ((net.minecraft.world.entity.player.Player)source.getEntity()).resetOnlyAttackStrengthTicker();
|
||||
+ }
|
||||
+ // Paper end - PlayerAttackEntityCooldownResetEvent
|
||||
+ }
|
||||
+
|
||||
+ // Resistance
|
||||
+ if (event.getDamage(DamageModifier.RESISTANCE) < 0) {
|
||||
+ float damageResisted = (float)-event.getDamage(DamageModifier.RESISTANCE);
|
||||
@@ -1405,6 +1392,18 @@
|
||||
|
||||
profiler.pop();
|
||||
if (this.isFallFlying()) {
|
||||
@@ -2865,6 +_,11 @@
|
||||
}
|
||||
|
||||
public void onAttack() {
|
||||
+ // Paper start
|
||||
+ onAttack(null);
|
||||
+ }
|
||||
+ public void onAttack(Entity entity) {
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void detectEquipmentUpdates() {
|
||||
@@ -2879,16 +_,39 @@
|
||||
|
||||
private @Nullable Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -213,13 +_,22 @@
|
||||
@@ -213,8 +_,16 @@
|
||||
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
if (heldItem.is(Items.BUCKET) && !this.isBaby()) {
|
||||
@@ -18,13 +18,6 @@
|
||||
player.setItemInHand(hand, bucketOrMilkBucket);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
+ boolean isFood = this.isFood(heldItem); // Paper - track before stack is possibly decreased to 0 (Fixes MC-244739)
|
||||
InteractionResult interactionResult = super.mobInteract(player, hand);
|
||||
- if (interactionResult.consumesAction() && this.isFood(heldItem)) {
|
||||
+ if (interactionResult.consumesAction() && isFood) { // Paper
|
||||
this.playEatingSound();
|
||||
}
|
||||
|
||||
@@ -328,8 +_,7 @@
|
||||
double deltaY = Mth.randomBetween(this.random, 0.3F, 0.7F);
|
||||
double deltaZ = Mth.randomBetween(this.random, -0.2F, 0.2F);
|
||||
|
||||
+14
-3
@@ -1,6 +1,15 @@
|
||||
--- a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java
|
||||
+++ b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java
|
||||
@@ -314,8 +_,12 @@
|
||||
@@ -300,7 +_,7 @@
|
||||
@Override
|
||||
protected void addPassenger(final Entity passenger) {
|
||||
if (!this.isVehicle()) {
|
||||
- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.HARNESS_GOGGLES_DOWN, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ this.playSound(SoundEvents.HARNESS_GOGGLES_DOWN, 1.0F, 1.0F); // Paper - don't play sound if silenced (Fixes MC-297169)
|
||||
}
|
||||
|
||||
super.addPassenger(passenger);
|
||||
@@ -314,16 +_,21 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,9 +24,11 @@
|
||||
if (!this.level().isClientSide()) {
|
||||
this.setServerStillTimeout(10);
|
||||
}
|
||||
@@ -324,6 +_,7 @@
|
||||
|
||||
if (!this.isVehicle()) {
|
||||
this.clearHome();
|
||||
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.HARNESS_GOGGLES_UP, this.getSoundSource(), 1.0F, 1.0F);
|
||||
- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.HARNESS_GOGGLES_UP, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ this.playSound(SoundEvents.HARNESS_GOGGLES_UP, 1.0F, 1.0F); // Paper - don't play sound if silenced (Fixes MC-297169)
|
||||
}
|
||||
+ return true; // Paper - cancellable passengers
|
||||
}
|
||||
|
||||
+4
-4
@@ -43,15 +43,15 @@
|
||||
} else {
|
||||
if (!this.isRemoved()) {
|
||||
+ // CraftBukkit start - fire break events
|
||||
+ Entity damager = (!source.isDirect() && source.getEntity() != null) ? source.getEntity() : source.getDirectEntity(); // Paper - fix DamageSource API
|
||||
+ org.bukkit.event.hanging.HangingBreakEvent event;
|
||||
+ Entity damager = source.getDirectEntity();
|
||||
+ final org.bukkit.event.hanging.HangingBreakEvent event;
|
||||
+ if (damager != null) {
|
||||
+ event = new org.bukkit.event.hanging.HangingBreakByEntityEvent((org.bukkit.entity.Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION) ? org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.EXPLOSION : org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.ENTITY);
|
||||
+ event = new org.bukkit.event.hanging.HangingBreakByEntityEvent((org.bukkit.entity.Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), new org.bukkit.craftbukkit.damage.CraftDamageSource(source), source.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION) ? org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.EXPLOSION : org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.ENTITY);
|
||||
+ } else {
|
||||
+ event = new org.bukkit.event.hanging.HangingBreakEvent((org.bukkit.entity.Hanging) this.getBukkitEntity(), source.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION) ? org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.EXPLOSION : org.bukkit.event.hanging.HangingBreakEvent.RemoveCause.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ this.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ event.callEvent();
|
||||
+
|
||||
+ if (this.isRemoved() || event.isCancelled()) {
|
||||
+ return true;
|
||||
|
||||
@@ -240,8 +240,9 @@
|
||||
float attackStrengthScale = this.getAttackStrengthScale(0.5F);
|
||||
float magicBoost = attackStrengthScale * (this.getEnchantedDamage(entity, baseDamage, damageSource) - baseDamage);
|
||||
baseDamage *= this.baseDamageScaleFactor();
|
||||
this.onAttack();
|
||||
- this.onAttack();
|
||||
- if (!this.deflectProjectile(entity)) {
|
||||
+ this.onAttack(entity); // Paper
|
||||
+ final float dmgFinal = magicBoost; // Paper - damage events
|
||||
+ if (!this.deflectProjectile(entity, () -> !org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(entity, dmgSourceFinal, dmgFinal, false))) {
|
||||
if (baseDamage > 0.0F || magicBoost > 0.0F) {
|
||||
@@ -480,15 +481,27 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1808,10 +_,31 @@
|
||||
|
||||
@Override
|
||||
public void onAttack() {
|
||||
- this.resetOnlyAttackStrengthTicker();
|
||||
+ // this.resetOnlyAttackStrengthTicker(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt
|
||||
super.onAttack();
|
||||
@@ -1807,10 +_,39 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void onAttack() {
|
||||
- this.resetOnlyAttackStrengthTicker();
|
||||
- super.onAttack();
|
||||
- }
|
||||
+ // Paper start
|
||||
+ public void onAttack(@Nullable Entity entity) {
|
||||
+ if (entity != null) {
|
||||
+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent((org.bukkit.entity.Player) this.getBukkitEntity(), entity.getBukkitEntity(), this.getAttackStrengthScale(0F)).callEvent()) {
|
||||
+ this.resetOnlyAttackStrengthTicker();
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.resetOnlyAttackStrengthTicker();
|
||||
+ }
|
||||
+ super.onAttack(entity);
|
||||
+ // Paper end
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - Force update attributes.
|
||||
+ @Override
|
||||
+ public void detectEquipmentUpdates() {
|
||||
@@ -509,10 +522,9 @@
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Force update attributes.
|
||||
+
|
||||
|
||||
public void resetOnlyAttackStrengthTicker() {
|
||||
this.attackStrengthTicker = 0;
|
||||
}
|
||||
@@ -1843,17 +_,32 @@
|
||||
return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING);
|
||||
}
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@
|
||||
+ this.splash(hitResult);
|
||||
+ }
|
||||
+
|
||||
+ public void splash(final HitResult hitResult) {
|
||||
+ public void splash(final @org.jspecify.annotations.Nullable HitResult hitResult) { // Paper
|
||||
+ // Paper end - More projectile API
|
||||
if (this.level() instanceof ServerLevel level) {
|
||||
ItemStack potionItemStack = this.getItem();
|
||||
@@ -37,7 +37,7 @@
|
||||
- private void onHitAsWater(final ServerLevel level) {
|
||||
+ private static final Predicate<LivingEntity> APPLY_WATER_GET_ENTITIES_PREDICATE = AbstractThrownPotion.WATER_SENSITIVE_OR_ON_FIRE.or(Axolotl.class::isInstance); // Paper - Fix potions splash events
|
||||
+
|
||||
+ private boolean onHitAsWater(final ServerLevel level, final HitResult hitResult) { // Paper - Fix potions splash events
|
||||
+ private boolean onHitAsWater(final ServerLevel level, final @org.jspecify.annotations.Nullable HitResult hitResult) { // Paper - Fix potions splash events
|
||||
AABB aabb = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
|
||||
|
||||
- for (LivingEntity entity : this.level().getEntitiesOfClass(LivingEntity.class, aabb, WATER_SENSITIVE_OR_ON_FIRE)) {
|
||||
@@ -88,7 +88,7 @@
|
||||
}
|
||||
|
||||
- protected abstract void onHitAsPotion(ServerLevel level, ItemStack potionItem, HitResult hitResult);
|
||||
+ protected abstract boolean onHitAsPotion(ServerLevel level, ItemStack potionItem, HitResult hitResult); // Paper - Fix potions splash events & More Projectile API
|
||||
+ protected abstract boolean onHitAsPotion(ServerLevel level, ItemStack potionItem, @org.jspecify.annotations.Nullable HitResult hitResult); // Paper - Fix potions splash events & More Projectile API
|
||||
|
||||
private void dowseFire(final BlockPos pos) {
|
||||
BlockState blockState = this.level().getBlockState(pos);
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
@Override
|
||||
- public void onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final HitResult hitResult) {
|
||||
+ public boolean onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final HitResult hitResult) { // Paper - More projectile API
|
||||
+ public boolean onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final @org.jspecify.annotations.Nullable HitResult hitResult) { // Paper - More projectile API
|
||||
AreaEffectCloud cloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
||||
if (this.getOwner() instanceof LivingEntity owner) {
|
||||
cloud.setOwner(owner);
|
||||
|
||||
+3
-2
@@ -5,11 +5,12 @@
|
||||
|
||||
@Override
|
||||
- public void onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final HitResult hitResult) {
|
||||
+ public boolean onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final HitResult hitResult) { // Paper - More projectile API
|
||||
+ public boolean onHitAsPotion(final ServerLevel level, final ItemStack potionItem, final @org.jspecify.annotations.Nullable HitResult hitResult) { // Paper - More projectile API
|
||||
PotionContents contents = potionItem.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
|
||||
float durationScale = potionItem.getOrDefault(DataComponents.POTION_DURATION_SCALE, 1.0F);
|
||||
Iterable<MobEffectInstance> mobEffects = contents.getAllEffects();
|
||||
AABB potionAabb = this.getBoundingBox().move(hitResult.getLocation().subtract(this.position()));
|
||||
- AABB potionAabb = this.getBoundingBox().move(hitResult.getLocation().subtract(this.position()));
|
||||
+ AABB potionAabb = hitResult == null ? this.getBoundingBox() : this.getBoundingBox().move(hitResult.getLocation().subtract(this.position())); // Paper - More projectile API
|
||||
AABB effectAabb = potionAabb.inflate(4.0, 2.0, 4.0);
|
||||
List<LivingEntity> entities = this.level().getEntitiesOfClass(LivingEntity.class, effectAabb);
|
||||
+ java.util.Map<org.bukkit.entity.LivingEntity, Double> affected = new java.util.HashMap<>(); // CraftBukkit
|
||||
|
||||
+8
-6
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java
|
||||
@@ -32,12 +_,20 @@
|
||||
@@ -32,12 +_,22 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -13,9 +13,11 @@
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.entity.Vehicle vehicle = (org.bukkit.entity.Vehicle) this.getBukkitEntity();
|
||||
+ org.bukkit.entity.Entity attacker = (source.getEntity() == null) ? null : source.getEntity().getBukkitEntity();
|
||||
+
|
||||
+ org.bukkit.event.vehicle.VehicleDamageEvent event = new org.bukkit.event.vehicle.VehicleDamageEvent(vehicle, attacker, damage);
|
||||
+ org.bukkit.craftbukkit.damage.CraftDamageSource damageSourceBukkit = new org.bukkit.craftbukkit.damage.CraftDamageSource(source);
|
||||
+ org.bukkit.entity.Entity attacker = net.minecraft.Optionull.map(
|
||||
+ source.eventEntityDamager() != null ? source.eventEntityDamager() : source.getDirectEntity(), Entity::getBukkitEntity
|
||||
+ );
|
||||
+ org.bukkit.event.vehicle.VehicleDamageEvent event = new org.bukkit.event.vehicle.VehicleDamageEvent(vehicle, damageSourceBukkit, attacker, damage);
|
||||
+ if (!event.callEvent()) return false;
|
||||
+ damage = (float) event.getDamage();
|
||||
+ // CraftBukkit end
|
||||
@@ -28,7 +30,7 @@
|
||||
if (creativePlayer) {
|
||||
- this.discard();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.vehicle.VehicleDestroyEvent destroyEvent = new org.bukkit.event.vehicle.VehicleDestroyEvent(vehicle, attacker);
|
||||
+ org.bukkit.event.vehicle.VehicleDestroyEvent destroyEvent = new org.bukkit.event.vehicle.VehicleDestroyEvent(vehicle, damageSourceBukkit, attacker);
|
||||
+ if (!destroyEvent.callEvent()) {
|
||||
+ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away
|
||||
+ return true;
|
||||
@@ -38,7 +40,7 @@
|
||||
}
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.vehicle.VehicleDestroyEvent destroyEvent = new org.bukkit.event.vehicle.VehicleDestroyEvent(vehicle, attacker);
|
||||
+ org.bukkit.event.vehicle.VehicleDestroyEvent destroyEvent = new org.bukkit.event.vehicle.VehicleDestroyEvent(vehicle, damageSourceBukkit, attacker);
|
||||
+ if (!destroyEvent.callEvent()) {
|
||||
+ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away
|
||||
+ return true;
|
||||
|
||||
+11
-2
@@ -84,14 +84,23 @@
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0));
|
||||
this.lastYd = 0.0;
|
||||
}
|
||||
@@ -704,12 +_,12 @@
|
||||
@@ -704,12 +_,20 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void remove(final Entity.RemovalReason reason) {
|
||||
+ public void remove(final Entity.RemovalReason reason, org.bukkit.event.entity.EntityRemoveEvent.@Nullable Cause eventCause) { // CraftBukkit - add Bukkit remove cause
|
||||
if (!this.level().isClientSide() && reason.shouldDestroy() && this.isLeashed()) {
|
||||
this.dropLeash();
|
||||
- this.dropLeash();
|
||||
+ // Paper start - Fire EntityUnleashEvent on boat destruction
|
||||
+ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(this.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.LEASHED_GONE, true);
|
||||
+ event.callEvent();
|
||||
+ if (event.isDropLeash()) {
|
||||
+ this.dropLeash();
|
||||
+ } else {
|
||||
+ this.removeLeash();
|
||||
+ }
|
||||
+ // Paper end - Fire EntityUnleashEvent on boat destruction
|
||||
}
|
||||
|
||||
- super.remove(reason);
|
||||
|
||||
+8
-1
@@ -201,7 +201,7 @@
|
||||
player.handleCreativeModeItemDrop(itemStack);
|
||||
}
|
||||
}
|
||||
@@ -595,8 +_,9 @@
|
||||
@@ -595,14 +_,15 @@
|
||||
if (player instanceof ServerPlayer) {
|
||||
ItemStack carried = this.getCarried();
|
||||
if (!carried.isEmpty()) {
|
||||
@@ -212,6 +212,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void dropOrPlaceInInventory(final Player player, final ItemStack carried) {
|
||||
- boolean playerRemovedNotChangingDimension = player.isRemoved() && player.getRemovalReason() != Entity.RemovalReason.CHANGED_DIMENSION;
|
||||
+ boolean playerRemovedNotChangingDimension = !player.isAlive() && player.getRemovalReason() != Entity.RemovalReason.CHANGED_DIMENSION; // Paper - Make sure player is dead (https://github.com/PaperMC/Paper/pull/13002)
|
||||
boolean serverPlayerHasDisconnected = player instanceof ServerPlayer serverPlayer && serverPlayer.hasDisconnected();
|
||||
if (playerRemovedNotChangingDimension || serverPlayerHasDisconnected) {
|
||||
player.drop(carried, false);
|
||||
@@ -642,6 +_,14 @@
|
||||
public abstract boolean stillValid(Player player);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand));
|
||||
+ if (event.callEvent() && delayed.attemptSpawn()) {
|
||||
+ player.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below
|
||||
+ if (player.dropAllLeashConnections(null)) {
|
||||
+ if (player.dropAllLeashConnections(player, hand)) { // Paper - PlayerUnleashEntityEvent
|
||||
+ level.playSound(null, player, SoundEvents.LEAD_BREAK, SoundSource.NEUTRAL, 1.0F, 1.0F);
|
||||
+ }
|
||||
+ if (event.shouldConsume() && !player.hasInfiniteMaterials()) {
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
protected Level(
|
||||
final WritableLevelData levelData,
|
||||
final ResourceKey<Level> dimension,
|
||||
@@ -141,7 +_,24 @@
|
||||
@@ -141,7 +_,25 @@
|
||||
final boolean isDebug,
|
||||
final long biomeZoomSeed,
|
||||
final int maxChainedNeighborUpdates
|
||||
@@ -87,10 +87,11 @@
|
||||
+ java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
|
||||
+ io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config
|
||||
) {
|
||||
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, CraftNamespacedKey.fromMinecraft(dimension.identifier())); // Spigot
|
||||
+ final org.bukkit.NamespacedKey worldKey = CraftNamespacedKey.fromMinecraft(dimension.identifier()); // Paper
|
||||
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, worldKey); // Spigot
|
||||
+ this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
|
||||
+ this.generator = generator;
|
||||
+ this.world = new CraftWorld((ServerLevel) this, generator, biomeProvider, environment);
|
||||
+ this.world = new CraftWorld((ServerLevel) this, worldKey, biomeProvider, environment);
|
||||
+
|
||||
+ for (SpawnCategory spawnCategory : SpawnCategory.values()) {
|
||||
+ if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {
|
||||
@@ -445,7 +446,15 @@
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
}
|
||||
@@ -533,31 +_,48 @@
|
||||
@@ -523,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void addBlockEntityTicker(final TickingBlockEntity ticker) {
|
||||
+ if (!this.paperConfig().unsupportedSettings.ticking.blockEntities) return; // Paper - option to disable ticking
|
||||
(this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(ticker);
|
||||
}
|
||||
|
||||
@@ -533,18 +_,23 @@
|
||||
this.pendingBlockEntityTickers.clear();
|
||||
}
|
||||
|
||||
@@ -471,10 +480,9 @@
|
||||
|
||||
+ this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 use removeAll
|
||||
this.tickingBlockEntities = false;
|
||||
+ this.spigotConfig.currentPrimedTnt = 0; // Spigot
|
||||
}
|
||||
|
||||
public <T extends Entity> void guardEntityTick(final Consumer<T> tick, final T entity) {
|
||||
@@ -552,12 +_,23 @@
|
||||
try {
|
||||
tick.accept(entity);
|
||||
} catch (Throwable var6) {
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/level/block/AbstractSkullBlock.java
|
||||
+++ b/net/minecraft/world/level/block/AbstractSkullBlock.java
|
||||
@@ -76,6 +_,11 @@
|
||||
if (!level.isClientSide()) {
|
||||
boolean signal = level.hasNeighborSignal(pos);
|
||||
if (signal != state.getValue(POWERED)) {
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, signal)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
level.setBlock(pos, state.setValue(POWERED, signal), Block.UPDATE_CLIENTS);
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -13,15 +13,15 @@
|
||||
boolean wasPressed = oldSignal > 0;
|
||||
boolean isPressed = signal > 0;
|
||||
+
|
||||
+ // CraftBukkit start - Interact Pressure Plate
|
||||
+ if (wasPressed != isPressed) {
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), oldSignal, signal);
|
||||
+ eventRedstone.callEvent();
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (oldSignal != signal) {
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldSignal, signal);
|
||||
+
|
||||
+ isPressed = eventRedstone.getNewCurrent() > 0;
|
||||
+ signal = eventRedstone.getNewCurrent();
|
||||
+ signal = event.getNewCurrent();
|
||||
+ isPressed = signal > 0;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
+
|
||||
if (oldSignal != signal) {
|
||||
BlockState newState = this.setSignalForState(state, signal);
|
||||
level.setBlock(pos, newState, Block.UPDATE_CLIENTS);
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
--- a/net/minecraft/world/level/block/BellBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BellBlock.java
|
||||
@@ -73,6 +_,11 @@
|
||||
) {
|
||||
boolean signal = level.hasNeighborSignal(pos);
|
||||
if (signal != state.getValue(POWERED)) {
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, signal)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
if (signal) {
|
||||
this.attemptToRing(level, pos, null);
|
||||
}
|
||||
@@ -143,6 +_,11 @@
|
||||
direction = level.getBlockState(pos).getValue(FACING);
|
||||
}
|
||||
|
||||
+19
-27
@@ -1,25 +1,27 @@
|
||||
--- a/net/minecraft/world/level/block/ButtonBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ButtonBlock.java
|
||||
@@ -92,6 +_,19 @@
|
||||
@@ -92,6 +_,11 @@
|
||||
if (state.getValue(POWERED)) {
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ boolean powered = state.getValue(ButtonBlock.POWERED);
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ int old = (powered) ? 15 : 0;
|
||||
+ int current = (!powered) ? 15 : 0;
|
||||
+
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(block, old, current);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
|
||||
+
|
||||
+ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) {
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, true)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
this.press(state, level, pos, player);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
@@ -102,7 +_,9 @@
|
||||
final BlockState state, final ServerLevel level, final BlockPos pos, final Explosion explosion, final BiConsumer<ItemStack, BlockPos> onHit
|
||||
) {
|
||||
if (explosion.canTriggerBlocks() && !state.getValue(POWERED)) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, true)) { // Paper - Call BlockRedstoneEvent
|
||||
this.press(state, level, pos, null);
|
||||
+ } // Paper - Call BlockRedstoneEvent
|
||||
}
|
||||
|
||||
super.onExplosionHit(state, level, pos, explosion, onHit);
|
||||
@@ -162,6 +_,7 @@
|
||||
final InsideBlockEffectApplier effectApplier,
|
||||
final boolean isPrecise
|
||||
@@ -28,7 +30,7 @@
|
||||
if (!level.isClientSide() && this.type.canButtonBeActivatedByArrows() && !state.getValue(POWERED)) {
|
||||
this.checkPressed(state, level, pos);
|
||||
}
|
||||
@@ -173,7 +_,31 @@
|
||||
@@ -173,7 +_,21 @@
|
||||
: null;
|
||||
boolean shouldBePressed = firstArrow != null;
|
||||
boolean wasPressed = state.getValue(POWERED);
|
||||
@@ -36,27 +38,17 @@
|
||||
+ if (wasPressed != shouldBePressed && shouldBePressed) {
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(firstArrow.getBukkitEntity(), block);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ if (!event.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (shouldBePressed != wasPressed) {
|
||||
+ // CraftBukkit start
|
||||
+ boolean powered = wasPressed;
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ int old = (powered) ? 15 : 0;
|
||||
+ int current = (!powered) ? 15 : 0;
|
||||
+
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(block, old, current);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
|
||||
+
|
||||
+ if ((shouldBePressed && eventRedstone.getNewCurrent() <= 0) || (!shouldBePressed && eventRedstone.getNewCurrent() > 0)) {
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, shouldBePressed)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
level.setBlock(pos, state.setValue(POWERED, shouldBePressed), Block.UPDATE_ALL);
|
||||
this.updateNeighbours(state, level, pos);
|
||||
this.playSound(null, level, pos, shouldBePressed);
|
||||
+7
-10
@@ -1,24 +1,21 @@
|
||||
--- a/net/minecraft/world/level/block/CommandBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CommandBlock.java
|
||||
@@ -69,8 +_,17 @@
|
||||
@@ -69,9 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private void setPoweredAndUpdate(final Level level, final BlockPos pos, final CommandBlockEntity commandBlock, final boolean isPowered) {
|
||||
+ private void setPoweredAndUpdate(final Level level, final BlockPos pos, final CommandBlockEntity commandBlock, boolean isPowered) { // Paper - remove final from isPowered
|
||||
boolean wasPowered = commandBlock.isPowered();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ int old = wasPowered ? 15 : 0;
|
||||
+ int current = isPowered ? 15 : 0;
|
||||
+
|
||||
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, old, current);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
|
||||
+ isPowered = eventRedstone.getNewCurrent() > 0;
|
||||
+ // CraftBukkit end
|
||||
if (isPowered != wasPowered) {
|
||||
+ // Paper start - Call BlockRedstoneEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, isPowered)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Call BlockRedstoneEvent
|
||||
commandBlock.setPowered(isPowered);
|
||||
if (isPowered) {
|
||||
if (commandBlock.isAutomatic() || commandBlock.getMode() == CommandBlockEntity.Mode.SEQUENCE) {
|
||||
@@ -129,7 +_,7 @@
|
||||
final BlockState state, final Level level, final BlockPos pos, final Player player, final BlockHitResult hitResult
|
||||
) {
|
||||
|
||||
Loaded 100 of 206 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user