more additions
This commit is contained in:
parent
a7303b7ed5
commit
76244747ed
@ -11,7 +11,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":patchbukkit"))
|
||||
compileOnly("io.papermc.paper:paper-api:26.2.build.112-stable")
|
||||
compileOnly("io.papermc.paper:paper-api:26.2.build.117-stable")
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@ -47,7 +47,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
paperweight.paperDevBundle("26.2.build.112-stable")
|
||||
paperweight.paperDevBundle("26.2.build.117-stable")
|
||||
implementation("net.sf.jopt-simple:jopt-simple:6.0-alpha-3")
|
||||
implementation("org.apache.maven:maven-resolver-provider:3.9.6")
|
||||
implementation("org.apache.maven.resolver:maven-resolver-impl:1.9.18")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,111 @@
|
||||
package org.patchbukkit.ban;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import org.bukkit.BanEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitBanEntry<T> implements BanEntry<T> {
|
||||
private final String target;
|
||||
private final T banTarget;
|
||||
private Date created;
|
||||
private String source;
|
||||
private Date expiration;
|
||||
private String reason;
|
||||
private final PatchBukkitBanList<T> list;
|
||||
|
||||
public PatchBukkitBanEntry(
|
||||
@NotNull String target,
|
||||
@Nullable T banTarget,
|
||||
@Nullable Date created,
|
||||
@Nullable String source,
|
||||
@Nullable Date expiration,
|
||||
@Nullable String reason,
|
||||
@Nullable PatchBukkitBanList<T> list
|
||||
) {
|
||||
this.target = target;
|
||||
this.banTarget = banTarget;
|
||||
this.created = created != null ? created : new Date();
|
||||
this.source = source != null ? source : "Server";
|
||||
this.expiration = expiration;
|
||||
this.reason = reason != null ? reason : "Banned by operator";
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable T getBanTarget() {
|
||||
return this.banTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Date getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreated(@NotNull Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSource(@NotNull String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Date getExpiration() {
|
||||
return this.expiration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpiration(@Nullable Date expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getReason() {
|
||||
return this.reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReason(@Nullable String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
if (this.list != null) {
|
||||
this.list.saveEntry(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (this.list != null) {
|
||||
this.list.pardon(this.target);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof BanEntry<?> that)) return false;
|
||||
return Objects.equals(this.target, that.getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.target);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,192 @@
|
||||
package org.patchbukkit.ban;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.bukkit.BanEntry;
|
||||
import org.bukkit.BanList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import patchbukkit.bridge.NativeBridgeFfi;
|
||||
import patchbukkit.server.BanEntryProto;
|
||||
import patchbukkit.server.GetBanListRequest;
|
||||
import patchbukkit.server.SetBanEntryRequest;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class PatchBukkitBanList<T> implements BanList<T> {
|
||||
private final String banType;
|
||||
private final Map<String, BanEntry<T>> entries = new ConcurrentHashMap<>();
|
||||
|
||||
public PatchBukkitBanList(@NotNull String banType) {
|
||||
this.banType = banType;
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
try {
|
||||
var res = NativeBridgeFfi.getBanList(GetBanListRequest.newBuilder().setBanType(banType).build());
|
||||
if (res != null) {
|
||||
entries.clear();
|
||||
for (BanEntryProto proto : res.getEntriesList()) {
|
||||
Date created = new Date(proto.getCreated() * 1000);
|
||||
Date expires = proto.getExpires() > 0 ? new Date(proto.getExpires() * 1000) : null;
|
||||
T targetObj = parseTarget(proto.getTarget());
|
||||
PatchBukkitBanEntry<T> entry = new PatchBukkitBanEntry<>(
|
||||
proto.getTarget(),
|
||||
targetObj,
|
||||
created,
|
||||
proto.getSource(),
|
||||
expires,
|
||||
proto.getReason(),
|
||||
this
|
||||
);
|
||||
entries.put(proto.getTarget().toLowerCase(), entry);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private T parseTarget(String target) {
|
||||
if ("IP".equalsIgnoreCase(banType)) {
|
||||
try {
|
||||
return (T) InetAddress.getByName(target);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
return (T) target;
|
||||
}
|
||||
|
||||
public void saveEntry(PatchBukkitBanEntry<T> entry) {
|
||||
entries.put(entry.getTarget().toLowerCase(), entry);
|
||||
try {
|
||||
var proto = BanEntryProto.newBuilder()
|
||||
.setTarget(entry.getTarget())
|
||||
.setSource(entry.getSource())
|
||||
.setCreated(entry.getCreated().getTime() / 1000)
|
||||
.setExpires(entry.getExpiration() != null ? entry.getExpiration().getTime() / 1000 : 0)
|
||||
.setReason(entry.getReason() != null ? entry.getReason() : "")
|
||||
.build();
|
||||
NativeBridgeFfi.setBanEntry(SetBanEntryRequest.newBuilder()
|
||||
.setBanType(banType)
|
||||
.setEntry(proto)
|
||||
.setRemove(false)
|
||||
.build());
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends BanEntry<? super T>> @Nullable E getBanEntry(@NotNull String target) {
|
||||
return (E) entries.get(target.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BanEntry<T> getBanEntry(@NotNull T target) {
|
||||
return entries.get(targetToString(target).toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends BanEntry<? super T>> @Nullable E addBan(
|
||||
@NotNull String target,
|
||||
@Nullable String reason,
|
||||
@Nullable Date expires,
|
||||
@Nullable String source
|
||||
) {
|
||||
PatchBukkitBanEntry<T> entry = new PatchBukkitBanEntry<>(
|
||||
target,
|
||||
parseTarget(target),
|
||||
new Date(),
|
||||
source,
|
||||
expires,
|
||||
reason,
|
||||
this
|
||||
);
|
||||
saveEntry(entry);
|
||||
return (E) entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BanEntry<T> addBan(
|
||||
@NotNull T target,
|
||||
@Nullable String reason,
|
||||
@Nullable Date expires,
|
||||
@Nullable String source
|
||||
) {
|
||||
return addBan(targetToString(target), reason, expires, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BanEntry<T> addBan(
|
||||
@NotNull T target,
|
||||
@Nullable String reason,
|
||||
@Nullable Instant expires,
|
||||
@Nullable String source
|
||||
) {
|
||||
return addBan(target, reason, expires != null ? Date.from(expires) : null, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BanEntry<T> addBan(
|
||||
@NotNull T target,
|
||||
@Nullable String reason,
|
||||
@Nullable Duration duration,
|
||||
@Nullable String source
|
||||
) {
|
||||
Date expires = duration != null ? Date.from(Instant.now().plus(duration)) : null;
|
||||
return addBan(target, reason, expires, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<BanEntry> getBanEntries() {
|
||||
return new HashSet<>(entries.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends BanEntry<? super T>> @NotNull Set<E> getEntries() {
|
||||
return (Set<E>) new HashSet<>(entries.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned(@NotNull T target) {
|
||||
return isBanned(targetToString(target));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned(@NotNull String target) {
|
||||
BanEntry<T> entry = entries.get(target.toLowerCase());
|
||||
if (entry == null) return false;
|
||||
if (entry.getExpiration() != null && entry.getExpiration().before(new Date())) {
|
||||
pardon(target);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pardon(@NotNull T target) {
|
||||
pardon(targetToString(target));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pardon(@NotNull String target) {
|
||||
entries.remove(target.toLowerCase());
|
||||
try {
|
||||
var proto = BanEntryProto.newBuilder().setTarget(target).build();
|
||||
NativeBridgeFfi.setBanEntry(SetBanEntryRequest.newBuilder()
|
||||
.setBanType(banType)
|
||||
.setEntry(proto)
|
||||
.setRemove(true)
|
||||
.build());
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private String targetToString(T target) {
|
||||
if (target instanceof InetAddress addr) {
|
||||
return addr.getHostAddress();
|
||||
}
|
||||
return String.valueOf(target);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package org.patchbukkit.boss;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitBossBar implements BossBar {
|
||||
private String title;
|
||||
private BarColor color;
|
||||
private BarStyle style;
|
||||
private final Set<BarFlag> flags = EnumSet.noneOf(BarFlag.class);
|
||||
private double progress = 1.0;
|
||||
private boolean visible = true;
|
||||
private final List<Player> players = new CopyOnWriteArrayList<>();
|
||||
|
||||
public PatchBukkitBossBar(
|
||||
@Nullable String title,
|
||||
@NotNull BarColor color,
|
||||
@NotNull BarStyle style,
|
||||
@NotNull BarFlag... flags
|
||||
) {
|
||||
this.title = title != null ? title : "";
|
||||
this.color = color;
|
||||
this.style = style;
|
||||
if (flags != null) {
|
||||
Collections.addAll(this.flags, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(@Nullable String title) {
|
||||
this.title = title != null ? title : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BarColor getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(@NotNull BarColor color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BarStyle getStyle() {
|
||||
return this.style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStyle(@NotNull BarStyle style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFlag(@NotNull BarFlag flag) {
|
||||
this.flags.remove(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFlag(@NotNull BarFlag flag) {
|
||||
this.flags.add(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFlag(@NotNull BarFlag flag) {
|
||||
return this.flags.contains(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
this.progress = Math.max(0.0, Math.min(1.0, progress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProgress() {
|
||||
return this.progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(@NotNull Player player) {
|
||||
if (!this.players.contains(player)) {
|
||||
this.players.add(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(@NotNull Player player) {
|
||||
this.players.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
this.players.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<Player> getPlayers() {
|
||||
return Collections.unmodifiableList(new ArrayList<>(this.players));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package org.patchbukkit.boss;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.KeyedBossBar;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitKeyedBossBar extends PatchBukkitBossBar implements KeyedBossBar {
|
||||
private final NamespacedKey key;
|
||||
|
||||
public PatchBukkitKeyedBossBar(
|
||||
@NotNull NamespacedKey key,
|
||||
@Nullable String title,
|
||||
@NotNull BarColor color,
|
||||
@NotNull BarStyle style,
|
||||
@NotNull BarFlag... flags
|
||||
) {
|
||||
super(title, color, style, flags);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NamespacedKey getKey() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package org.patchbukkit.datapack;
|
||||
|
||||
import io.papermc.paper.datapack.Datapack;
|
||||
import io.papermc.paper.datapack.DatapackManager;
|
||||
import io.papermc.paper.datapack.DatapackSource;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.FeatureFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitDatapackManager implements DatapackManager {
|
||||
private static final Datapack VANILLA = new Datapack() {
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return "vanilla";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component getTitle() {
|
||||
return Component.text("Vanilla");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component getDescription() {
|
||||
return Component.text("The default data pack");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {}
|
||||
|
||||
@Override
|
||||
public @NotNull Component computeDisplayName() {
|
||||
return Component.text("Vanilla");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Compatibility getCompatibility() {
|
||||
return Compatibility.COMPATIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<FeatureFlag> getRequiredFeatures() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DatapackSource getSource() {
|
||||
return DatapackSource.DEFAULT;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void refreshPacks() {}
|
||||
|
||||
@Override
|
||||
public @Nullable Datapack getPack(@NotNull String name) {
|
||||
if ("vanilla".equalsIgnoreCase(name)) return VANILLA;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Datapack> getPacks() {
|
||||
return Collections.singletonList(VANILLA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Datapack> getEnabledPacks() {
|
||||
return Collections.singletonList(VANILLA);
|
||||
}
|
||||
}
|
||||
@ -83,6 +83,16 @@ public class PatchBukkitEntity implements Entity {
|
||||
return this.perm;
|
||||
}
|
||||
|
||||
private Location cachedLocation;
|
||||
private EntityType entityType = EntityType.UNKNOWN;
|
||||
|
||||
public static Entity create(UUID uuid, EntityType type, Location loc) {
|
||||
PatchBukkitEntity entity = new PatchBukkitEntity(uuid, type != null ? type.name() : "entity");
|
||||
entity.entityType = type != null ? type : EntityType.UNKNOWN;
|
||||
entity.cachedLocation = loc != null ? loc.clone() : new Location(null, 0, 0, 0);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public PatchBukkitEntity(
|
||||
UUID uuid,
|
||||
String name
|
||||
@ -263,10 +273,15 @@ public class PatchBukkitEntity implements Entity {
|
||||
|
||||
@Override
|
||||
public @NotNull Location getLocation() {
|
||||
var location = NativeBridgeFfi.getLocation(BridgeUtils.convertUuid(this.uuid));
|
||||
var world = PatchBukkitWorld.getOrCreate(BridgeUtils.convertUuid(location.getWorld().getUuid()));
|
||||
var position = location.getPosition();
|
||||
return new Location(world, position.getX(), position.getY(), position.getZ(), location.getYaw(), location.getPitch());
|
||||
try {
|
||||
var location = NativeBridgeFfi.getLocation(BridgeUtils.convertUuid(this.uuid));
|
||||
if (location != null && location.hasWorld() && location.hasPosition()) {
|
||||
var world = PatchBukkitWorld.getOrCreate(BridgeUtils.convertUuid(location.getWorld().getUuid()));
|
||||
var position = location.getPosition();
|
||||
return new Location(world, position.getX(), position.getY(), position.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
return this.cachedLocation != null ? this.cachedLocation.clone() : new Location(null, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -646,8 +661,7 @@ public class PatchBukkitEntity implements Entity {
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getType() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getType'");
|
||||
return this.entityType != null ? this.entityType : EntityType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package org.patchbukkit.entity;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityFactory;
|
||||
import org.bukkit.entity.EntitySnapshot;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitEntityFactory implements EntityFactory {
|
||||
public static final PatchBukkitEntityFactory INSTANCE = new PatchBukkitEntityFactory();
|
||||
|
||||
@Override
|
||||
public @NotNull EntitySnapshot createEntitySnapshot(@NotNull String input) throws IllegalArgumentException {
|
||||
return new EntitySnapshot() {
|
||||
@Override
|
||||
public @NotNull Entity createEntity(@NotNull World world) {
|
||||
return world.spawnEntity(world.getSpawnLocation(), getEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Entity createEntity(@NotNull Location location) {
|
||||
return location.getWorld().spawnEntity(location, getEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getEntityType() {
|
||||
try {
|
||||
return EntityType.valueOf(input.toUpperCase());
|
||||
} catch (Throwable e) {
|
||||
return EntityType.PIG;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAsString() {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -474,387 +475,421 @@ public class PatchBukkitLivingEntity
|
||||
return hadEffects;
|
||||
}
|
||||
|
||||
private boolean removeWhenFarAway = false;
|
||||
private boolean canPickupItems = false;
|
||||
private boolean leashed = false;
|
||||
private Entity leashHolder = null;
|
||||
private boolean gliding = false;
|
||||
private boolean swimming = false;
|
||||
private boolean riptiding = false;
|
||||
private boolean sleeping = false;
|
||||
private boolean climbing = false;
|
||||
private boolean hasAI = true;
|
||||
private boolean collidable = true;
|
||||
private boolean jumping = false;
|
||||
private float hurtDirection = 0.0f;
|
||||
private float bodyYaw = 0.0f;
|
||||
private final Set<UUID> collidableExemptions = new HashSet<>();
|
||||
private final Map<MemoryKey<?>, Object> memories = new HashMap<>();
|
||||
private ItemStack activeItem = ItemStack.empty();
|
||||
private EquipmentSlot activeItemHand = EquipmentSlot.HAND;
|
||||
private int activeItemRemainingTime = 0;
|
||||
private int activeItemUsedTime = 0;
|
||||
private Key waypointStyle;
|
||||
private Color waypointColor;
|
||||
|
||||
@Override
|
||||
public boolean hasLineOfSight(@NotNull Entity other) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'hasLineOfSight'");
|
||||
if (other == null || other.getWorld() != getWorld()) return false;
|
||||
RayTraceResult result = getWorld().rayTraceBlocks(getEyeLocation(), other.getLocation().toVector().subtract(getEyeLocation().toVector()), getEyeLocation().distance(other.getLocation()), FluidCollisionMode.NEVER);
|
||||
return result == null || result.getHitBlock() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLineOfSight(@NotNull Location location) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'hasLineOfSight'");
|
||||
if (location == null || location.getWorld() != getWorld()) return false;
|
||||
RayTraceResult result = getWorld().rayTraceBlocks(getEyeLocation(), location.toVector().subtract(getEyeLocation().toVector()), getEyeLocation().distance(location), FluidCollisionMode.NEVER);
|
||||
return result == null || result.getHitBlock() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getRemoveWhenFarAway() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getRemoveWhenFarAway'");
|
||||
return this.removeWhenFarAway;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoveWhenFarAway(boolean remove) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setRemoveWhenFarAway'");
|
||||
this.removeWhenFarAway = remove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EntityEquipment getEquipment() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getEquipment'");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCanPickupItems(boolean pickup) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setCanPickupItems'");
|
||||
this.canPickupItems = pickup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCanPickupItems() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getCanPickupItems'");
|
||||
return this.canPickupItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeashed() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isLeashed'");
|
||||
return this.leashed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Entity getLeashHolder() throws IllegalStateException {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getLeashHolder'");
|
||||
if (!this.leashed || this.leashHolder == null) {
|
||||
throw new IllegalStateException("Entity is not leashed");
|
||||
}
|
||||
return this.leashHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLeashHolder(@Nullable Entity holder) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setLeashHolder'");
|
||||
this.leashHolder = holder;
|
||||
this.leashed = holder != null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGliding() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isGliding'");
|
||||
return this.gliding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGliding(boolean gliding) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setGliding'");
|
||||
this.gliding = gliding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSwimming() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isSwimming'");
|
||||
return this.swimming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSwimming(boolean swimming) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setSwimming'");
|
||||
this.swimming = swimming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRiptiding() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isRiptiding'");
|
||||
return this.riptiding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRiptiding(boolean riptiding) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setRiptiding'");
|
||||
this.riptiding = riptiding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSleeping() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isSleeping'");
|
||||
return this.sleeping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClimbing() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isClimbing'");
|
||||
return this.climbing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAI(boolean ai) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setAI'");
|
||||
this.hasAI = ai;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAI() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'hasAI'");
|
||||
return this.hasAI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attack(@NotNull Entity target) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'attack'");
|
||||
if (target instanceof LivingEntity living) {
|
||||
living.damage(1.0, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swingMainHand() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'swingMainHand'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swingOffHand() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'swingOffHand'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playHurtAnimation(float yaw) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'playHurtAnimation'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCollidable(boolean collidable) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setCollidable'");
|
||||
this.collidable = collidable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollidable() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isCollidable'");
|
||||
return this.collidable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<UUID> getCollidableExemptions() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getCollidableExemptions'");
|
||||
return this.collidableExemptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getMemory(@NotNull MemoryKey<T> memoryKey) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getMemory'");
|
||||
return (T) this.memories.get(memoryKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setMemory(@NotNull MemoryKey<T> memoryKey, @Nullable T memoryValue) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setMemory'");
|
||||
if (memoryValue == null) {
|
||||
this.memories.remove(memoryKey);
|
||||
} else {
|
||||
this.memories.put(memoryKey, memoryValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Sound getHurtSound() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getHurtSound'");
|
||||
return Sound.ENTITY_GENERIC_HURT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Sound getDeathSound() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getDeathSound'");
|
||||
return Sound.ENTITY_GENERIC_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sound getFallDamageSound(int fallHeight) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getFallDamageSound'");
|
||||
return fallHeight > 4 ? Sound.ENTITY_GENERIC_BIG_FALL : Sound.ENTITY_GENERIC_SMALL_FALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sound getFallDamageSoundSmall() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getFallDamageSoundSmall'");
|
||||
return Sound.ENTITY_GENERIC_SMALL_FALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sound getFallDamageSoundBig() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getFallDamageSoundBig'");
|
||||
return Sound.ENTITY_GENERIC_BIG_FALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sound getDrinkingSound(@NotNull ItemStack itemStack) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getDrinkingSound'");
|
||||
return Sound.ENTITY_GENERIC_DRINK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sound getEatingSound(@NotNull ItemStack itemStack) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getEatingSound'");
|
||||
return Sound.ENTITY_GENERIC_EAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBreatheUnderwater() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'canBreatheUnderwater'");
|
||||
return hasPotionEffect(PotionEffectType.WATER_BREATHING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityCategory getCategory() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getCategory'");
|
||||
return EntityCategory.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSidewaysMovement() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getSidewaysMovement'");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getUpwardsMovement() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getUpwardsMovement'");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getForwardsMovement() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getForwardsMovement'");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUsingItem(@NotNull EquipmentSlot hand) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'startUsingItem'");
|
||||
this.activeItemHand = hand;
|
||||
this.activeItemRemainingTime = 72000;
|
||||
this.activeItemUsedTime = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeUsingActiveItem() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'completeUsingActiveItem'");
|
||||
this.activeItemRemainingTime = 0;
|
||||
this.activeItem = ItemStack.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getActiveItem() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getActiveItem'");
|
||||
return this.activeItem != null ? this.activeItem : ItemStack.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearActiveItem() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'clearActiveItem'");
|
||||
this.activeItem = ItemStack.empty();
|
||||
this.activeItemRemainingTime = 0;
|
||||
this.activeItemUsedTime = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveItemRemainingTime() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getActiveItemRemainingTime'");
|
||||
return this.activeItemRemainingTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveItemRemainingTime(@Range(from = 0, to = 2147483647) int ticks) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setActiveItemRemainingTime'");
|
||||
this.activeItemRemainingTime = ticks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActiveItem() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'hasActiveItem'");
|
||||
return this.activeItemRemainingTime > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveItemUsedTime() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getActiveItemUsedTime'");
|
||||
return this.activeItemUsedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EquipmentSlot getActiveItemHand() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getActiveItemHand'");
|
||||
return this.activeItemHand != null ? this.activeItemHand : EquipmentSlot.HAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJumping() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'isJumping'");
|
||||
return this.jumping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJumping(boolean jumping) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setJumping'");
|
||||
this.jumping = jumping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playPickupItemAnimation(@NotNull Item item, int quantity) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'playPickupItemAnimation'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getHurtDirection() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getHurtDirection'");
|
||||
return this.hurtDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHurtDirection(float hurtDirection) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setHurtDirection'");
|
||||
this.hurtDirection = hurtDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void knockback(double strength, double directionX, double directionZ) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'knockback'");
|
||||
Vector vel = getVelocity();
|
||||
vel.setX(vel.getX() + directionX * strength);
|
||||
vel.setZ(vel.getZ() + directionZ * strength);
|
||||
setVelocity(vel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastSlotBreak(@NotNull EquipmentSlot slot) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'broadcastSlotBreak'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastSlotBreak(@NotNull EquipmentSlot slot, @NotNull Collection<Player> players) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'broadcastSlotBreak'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack damageItemStack(@NotNull ItemStack stack, int amount) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'damageItemStack'");
|
||||
if (stack == null || stack.isEmpty()) return ItemStack.empty();
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damageItemStack(@NotNull EquipmentSlot slot, int amount) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'damageItemStack'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBodyYaw() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getBodyYaw'");
|
||||
return this.bodyYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBodyYaw(float bodyYaw) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setBodyYaw'");
|
||||
this.bodyYaw = bodyYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUseEquipmentSlot(@NotNull EquipmentSlot slot) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'canUseEquipmentSlot'");
|
||||
return true;
|
||||
}
|
||||
|
||||
public @NotNull CombatTracker getCombatTracker() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getCombatTracker'");
|
||||
@Override
|
||||
public @NotNull io.papermc.paper.world.damagesource.CombatTracker getCombatTracker() {
|
||||
return new io.papermc.paper.world.damagesource.CombatTracker() {
|
||||
@Override
|
||||
public org.bukkit.entity.LivingEntity getEntity() {
|
||||
return PatchBukkitLivingEntity.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<io.papermc.paper.world.damagesource.CombatEntry> getCombatEntries() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCombatEntries(java.util.List<io.papermc.paper.world.damagesource.CombatEntry> entries) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.world.damagesource.CombatEntry computeMostSignificantFall() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInCombat() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTakingDamage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombatDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCombatEntry(io.papermc.paper.world.damagesource.CombatEntry entry) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.Component getDeathMessage() {
|
||||
return net.kyori.adventure.text.Component.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCombatState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.world.damagesource.FallLocationType calculateFallLocationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastDamageTime() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -867,41 +902,33 @@ public class PatchBukkitLivingEntity
|
||||
}
|
||||
|
||||
public void setWaypointStyle(@Nullable Key key) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setWaypointStyle'");
|
||||
this.waypointStyle = key;
|
||||
}
|
||||
|
||||
public void setWaypointColor(@Nullable Color color) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'setWaypointColor'");
|
||||
this.waypointColor = color;
|
||||
}
|
||||
|
||||
public @NotNull Key getWaypointStyle() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getWaypointStyle'");
|
||||
return this.waypointStyle != null ? this.waypointStyle : Key.key("minecraft", "default");
|
||||
}
|
||||
|
||||
public @Nullable Color getWaypointColor() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getWaypointColor'");
|
||||
return this.waypointColor;
|
||||
}
|
||||
|
||||
public void kill(DamageSource damageSource) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'kill'");
|
||||
setHealth(0.0);
|
||||
}
|
||||
|
||||
public float getSoundVolume() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getSoundVolume'");
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
public float getSoundPitch() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getSoundPitch'");
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
public @Nullable Sound getHurtSound(@NotNull DamageSource damageSource) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getHurtSound'");
|
||||
return Sound.ENTITY_GENERIC_HURT;
|
||||
}}
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
package org.patchbukkit.entity;
|
||||
|
||||
import com.destroystokyo.paper.entity.ai.Goal;
|
||||
import com.destroystokyo.paper.entity.ai.GoalKey;
|
||||
import com.destroystokyo.paper.entity.ai.GoalType;
|
||||
import com.destroystokyo.paper.entity.ai.MobGoals;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitMobGoals implements MobGoals {
|
||||
public static final PatchBukkitMobGoals INSTANCE = new PatchBukkitMobGoals();
|
||||
|
||||
@Override
|
||||
public <T extends Mob> void addGoal(@NotNull T mob, int priority, @NotNull Goal<T> goal) {}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> void removeGoal(@NotNull T mob, @NotNull Goal<T> goal) {}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> void removeAllGoals(@NotNull T mob) {}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> void removeAllGoals(@NotNull T mob, @NotNull GoalType type) {}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> void removeGoal(@NotNull T mob, @NotNull GoalKey<T> key) {}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> boolean hasGoal(@NotNull T mob, @NotNull GoalKey<T> key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @Nullable Goal<T> getGoal(@NotNull T mob, @NotNull GoalKey<T> key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getGoals(@NotNull T mob, @NotNull GoalKey<T> key) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getAllGoals(@NotNull T mob) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getAllGoals(@NotNull T mob, @NotNull GoalType type) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getRunningGoals(@NotNull T mob) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getRunningGoals(@NotNull T mob, @NotNull GoalType type) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Mob> @NotNull Collection<Goal<T>> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,14 @@ public class PatchBukkitOfflinePlayer implements OfflinePlayer {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public PatchBukkitOfflinePlayer(UUID uuid) {
|
||||
this(uuid, null);
|
||||
}
|
||||
|
||||
public PatchBukkitOfflinePlayer(String name) {
|
||||
this(null, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return getPlayer() != null;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,358 @@
|
||||
package org.patchbukkit.inventory;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PatchBukkitInventory implements Inventory {
|
||||
private final InventoryHolder holder;
|
||||
private final int size;
|
||||
private final String title;
|
||||
private final InventoryType type;
|
||||
private final ItemStack[] contents;
|
||||
private int maxStackSize = 64;
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, int size, @NotNull String title) {
|
||||
this(holder, size, title, InventoryType.CHEST);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, @NotNull InventoryType type) {
|
||||
this(holder, type.getDefaultSize(), type.getDefaultTitle(), type);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, @NotNull InventoryType type, @NotNull String title) {
|
||||
this(holder, type.getDefaultSize(), title, type);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title) {
|
||||
this(holder, type.getDefaultSize(), net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(title), type);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, int size, @NotNull net.kyori.adventure.text.Component title) {
|
||||
this(holder, size, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(title), InventoryType.CHEST);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, int size) {
|
||||
this(holder, size, "Inventory", InventoryType.CHEST);
|
||||
}
|
||||
|
||||
public PatchBukkitInventory(@Nullable InventoryHolder holder, int size, @NotNull String title, @NotNull InventoryType type) {
|
||||
this.holder = holder;
|
||||
this.size = size;
|
||||
this.title = title;
|
||||
this.type = type;
|
||||
this.contents = new ItemStack[size];
|
||||
Arrays.fill(this.contents, ItemStack.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
return this.maxStackSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxStackSize(int size) {
|
||||
this.maxStackSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ItemStack getItem(int index) {
|
||||
if (index < 0 || index >= this.size) return null;
|
||||
return this.contents[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int index, @Nullable ItemStack item) {
|
||||
if (index >= 0 && index < this.size) {
|
||||
this.contents[index] = (item != null) ? item.clone() : ItemStack.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> addItem(@NotNull ItemStack... items) throws IllegalArgumentException {
|
||||
HashMap<Integer, ItemStack> leftover = new HashMap<>();
|
||||
if (items == null) return leftover;
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
ItemStack item = items[i];
|
||||
if (item == null || item.isEmpty()) continue;
|
||||
ItemStack remaining = item.clone();
|
||||
|
||||
for (int slot = 0; slot < this.size; slot++) {
|
||||
ItemStack current = this.contents[slot];
|
||||
if (current != null && !current.isEmpty() && current.isSimilar(remaining)) {
|
||||
int canAdd = Math.min(remaining.getAmount(), current.getMaxStackSize() - current.getAmount());
|
||||
if (canAdd > 0) {
|
||||
current.setAmount(current.getAmount() + canAdd);
|
||||
remaining.setAmount(remaining.getAmount() - canAdd);
|
||||
if (remaining.getAmount() <= 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining.getAmount() > 0) {
|
||||
for (int slot = 0; slot < this.size; slot++) {
|
||||
ItemStack current = this.contents[slot];
|
||||
if (current == null || current.isEmpty()) {
|
||||
this.contents[slot] = remaining.clone();
|
||||
remaining.setAmount(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining.getAmount() > 0) {
|
||||
leftover.put(i, remaining);
|
||||
}
|
||||
}
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItem(@NotNull ItemStack... items) throws IllegalArgumentException {
|
||||
HashMap<Integer, ItemStack> leftover = new HashMap<>();
|
||||
if (items == null) return leftover;
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
ItemStack item = items[i];
|
||||
if (item == null || item.isEmpty()) continue;
|
||||
int toRemove = item.getAmount();
|
||||
|
||||
for (int slot = 0; slot < this.size; slot++) {
|
||||
ItemStack current = this.contents[slot];
|
||||
if (current != null && current.isSimilar(item)) {
|
||||
int remove = Math.min(toRemove, current.getAmount());
|
||||
current.setAmount(current.getAmount() - remove);
|
||||
toRemove -= remove;
|
||||
if (current.getAmount() <= 0) {
|
||||
this.contents[slot] = ItemStack.empty();
|
||||
}
|
||||
if (toRemove <= 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (toRemove > 0) {
|
||||
ItemStack rem = item.clone();
|
||||
rem.setAmount(toRemove);
|
||||
leftover.put(i, rem);
|
||||
}
|
||||
}
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItemAnySlot(@NotNull ItemStack... items) throws IllegalArgumentException {
|
||||
return removeItem(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack[] getContents() {
|
||||
return this.contents.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContents(@NotNull ItemStack[] items) throws IllegalArgumentException {
|
||||
if (items == null) return;
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (i < items.length && items[i] != null) {
|
||||
this.contents[i] = items[i].clone();
|
||||
} else {
|
||||
this.contents[i] = ItemStack.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack[] getStorageContents() {
|
||||
return getContents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageContents(@NotNull ItemStack[] items) throws IllegalArgumentException {
|
||||
setContents(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull Material material) throws IllegalArgumentException {
|
||||
return first(material) != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@Nullable ItemStack item) {
|
||||
return first(item) != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull Material material, int amount) throws IllegalArgumentException {
|
||||
int count = 0;
|
||||
for (ItemStack is : this.contents) {
|
||||
if (is != null && is.getType() == material) {
|
||||
count += is.getAmount();
|
||||
if (count >= amount) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@Nullable ItemStack item, int amount) {
|
||||
if (item == null) return false;
|
||||
int count = 0;
|
||||
for (ItemStack is : this.contents) {
|
||||
if (is != null && is.isSimilar(item)) {
|
||||
count += is.getAmount();
|
||||
if (count >= amount) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAtLeast(@Nullable ItemStack item, int amount) {
|
||||
return contains(item, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ? extends ItemStack> all(@NotNull Material material) throws IllegalArgumentException {
|
||||
HashMap<Integer, ItemStack> map = new HashMap<>();
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].getType() == material) {
|
||||
map.put(i, this.contents[i]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ? extends ItemStack> all(@Nullable ItemStack item) {
|
||||
HashMap<Integer, ItemStack> map = new HashMap<>();
|
||||
if (item == null) return map;
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].isSimilar(item)) {
|
||||
map.put(i, this.contents[i]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int first(@NotNull Material material) throws IllegalArgumentException {
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].getType() == material) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int first(@NotNull ItemStack item) {
|
||||
if (item == null) return -1;
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].isSimilar(item)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int firstEmpty() {
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] == null || this.contents[i].isEmpty()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (ItemStack is : this.contents) {
|
||||
if (is != null && !is.isEmpty()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(@NotNull Material material) throws IllegalArgumentException {
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].getType() == material) {
|
||||
this.contents[i] = ItemStack.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(@NotNull ItemStack item) {
|
||||
if (item == null) return;
|
||||
for (int i = 0; i < this.size; i++) {
|
||||
if (this.contents[i] != null && this.contents[i].isSimilar(item)) {
|
||||
this.contents[i] = ItemStack.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(int index) {
|
||||
setItem(index, ItemStack.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(this.contents, ItemStack.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int close() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<HumanEntity> getViewers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder() {
|
||||
return this.holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder(boolean useSnapshot) {
|
||||
return this.holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator() {
|
||||
return Arrays.asList(this.contents).listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator(int index) {
|
||||
return Arrays.asList(this.contents).listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
package org.patchbukkit.inventory;
|
||||
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.inventory.InventoryType.SlotType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.MenuType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitInventoryView implements InventoryView {
|
||||
private final HumanEntity player;
|
||||
private final Inventory topInventory;
|
||||
private String title;
|
||||
|
||||
public PatchBukkitInventoryView(@NotNull HumanEntity player, @NotNull Inventory topInventory) {
|
||||
this.player = player;
|
||||
this.topInventory = topInventory;
|
||||
this.title = topInventory.getType().getDefaultTitle();
|
||||
}
|
||||
|
||||
public PatchBukkitInventoryView(@NotNull HumanEntity player, @NotNull Inventory topInventory, @NotNull String title) {
|
||||
this.player = player;
|
||||
this.topInventory = topInventory;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getTopInventory() {
|
||||
return this.topInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBottomInventory() {
|
||||
return this.player.getInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HumanEntity getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType() {
|
||||
return this.topInventory.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int slot, @Nullable ItemStack item) {
|
||||
if (slot >= 0 && slot < getTopInventory().getSize()) {
|
||||
getTopInventory().setItem(slot, item);
|
||||
} else if (slot >= getTopInventory().getSize()) {
|
||||
getBottomInventory().setItem(slot - getTopInventory().getSize(), item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ItemStack getItem(int slot) {
|
||||
if (slot >= 0 && slot < getTopInventory().getSize()) {
|
||||
return getTopInventory().getItem(slot);
|
||||
} else if (slot >= getTopInventory().getSize()) {
|
||||
return getBottomInventory().getItem(slot - getTopInventory().getSize());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursor(@Nullable ItemStack item) {
|
||||
getPlayer().setItemOnCursor(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ItemStack getCursor() {
|
||||
return getPlayer().getItemOnCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Inventory getInventory(int rawSlot) {
|
||||
if (rawSlot >= 0 && rawSlot < getTopInventory().getSize()) {
|
||||
return getTopInventory();
|
||||
} else if (rawSlot >= getTopInventory().getSize()) {
|
||||
return getBottomInventory();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertSlot(int rawSlot) {
|
||||
if (rawSlot >= getTopInventory().getSize()) {
|
||||
return rawSlot - getTopInventory().getSize();
|
||||
}
|
||||
return rawSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SlotType getSlotType(int slot) {
|
||||
if (slot < getTopInventory().getSize()) {
|
||||
return SlotType.CONTAINER;
|
||||
}
|
||||
return SlotType.QUICKBAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
getPlayer().closeInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countSlots() {
|
||||
return getTopInventory().getSize() + getBottomInventory().getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperty(@NotNull Property prop, int value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTitle() {
|
||||
return this.title != null ? this.title : getType().getDefaultTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalTitle() {
|
||||
return getType().getDefaultTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(@NotNull String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull MenuType getMenuType() {
|
||||
return MenuType.GENERIC_9X3;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package org.patchbukkit.inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.MerchantRecipe;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitMerchant implements Merchant {
|
||||
private final Component title;
|
||||
private List<MerchantRecipe> recipes = new ArrayList<>();
|
||||
private HumanEntity trader;
|
||||
|
||||
public PatchBukkitMerchant(@Nullable Component title) {
|
||||
this.title = title != null ? title : Component.text("Merchant");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<MerchantRecipe> getRecipes() {
|
||||
return Collections.unmodifiableList(this.recipes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipes(@NotNull List<MerchantRecipe> recipes) {
|
||||
this.recipes = new ArrayList<>(recipes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull MerchantRecipe getRecipe(int i) throws IndexOutOfBoundsException {
|
||||
return this.recipes.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(int i, @NotNull MerchantRecipe recipe) throws IndexOutOfBoundsException {
|
||||
this.recipes.set(i, recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRecipeCount() {
|
||||
return this.recipes.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrading() {
|
||||
return this.trader != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable HumanEntity getTrader() {
|
||||
return this.trader;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package org.patchbukkit.map;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitMapView implements MapView {
|
||||
private final int id;
|
||||
private Scale scale = Scale.NORMAL;
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
private World world;
|
||||
private final List<MapRenderer> renderers = new ArrayList<>();
|
||||
private boolean trackingPosition = true;
|
||||
private boolean unlimitedTracking = false;
|
||||
private boolean locked = false;
|
||||
|
||||
public PatchBukkitMapView(int id, @Nullable World world) {
|
||||
this.id = id;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Scale getScale() {
|
||||
return this.scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(@NotNull Scale scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCenterX() {
|
||||
return this.centerX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCenterZ() {
|
||||
return this.centerZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCenterX(int x) {
|
||||
this.centerX = x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCenterZ(int z) {
|
||||
this.centerZ = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable World getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(@Nullable World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<MapRenderer> getRenderers() {
|
||||
return Collections.unmodifiableList(this.renderers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRenderer(@NotNull MapRenderer renderer) {
|
||||
this.renderers.add(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRenderer(@Nullable MapRenderer renderer) {
|
||||
return this.renderers.remove(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrackingPosition() {
|
||||
return this.trackingPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrackingPosition(boolean trackingPosition) {
|
||||
this.trackingPosition = trackingPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnlimitedTracking() {
|
||||
return this.unlimitedTracking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnlimitedTracking(boolean unlimitedTracking) {
|
||||
this.unlimitedTracking = unlimitedTracking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocked() {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocked(boolean locked) {
|
||||
this.locked = locked;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package org.patchbukkit.potion;
|
||||
|
||||
import io.papermc.paper.potion.PotionMix;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.potion.PotionBrewer;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitPotionBrewer implements PotionBrewer {
|
||||
public static final PatchBukkitPotionBrewer INSTANCE = new PatchBukkitPotionBrewer();
|
||||
|
||||
@Override
|
||||
public void addPotionMix(@NotNull PotionMix potionMix) {}
|
||||
|
||||
@Override
|
||||
public void removePotionMix(@NotNull NamespacedKey key) {}
|
||||
|
||||
@Override
|
||||
public void resetPotionMixes() {}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<PotionEffect> getEffects(@NotNull PotionType type, boolean upgraded, boolean extended) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,221 @@
|
||||
package org.patchbukkit.profile;
|
||||
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.bukkit.profile.PlayerTextures;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitPlayerProfile implements PlayerProfile {
|
||||
private UUID uuid;
|
||||
private String name;
|
||||
private final Set<ProfileProperty> properties = new HashSet<>();
|
||||
private PlayerTextures textures = new EmptyPlayerTextures();
|
||||
|
||||
public PatchBukkitPlayerProfile(@Nullable UUID uuid, @Nullable String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UUID getUniqueId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UUID getId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UUID setId(@Nullable UUID uuid) {
|
||||
UUID old = this.uuid;
|
||||
this.uuid = uuid;
|
||||
return old;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String setName(@Nullable String name) {
|
||||
String old = this.name;
|
||||
this.name = name;
|
||||
return old;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerTextures getTextures() {
|
||||
return this.textures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextures(@Nullable PlayerTextures textures) {
|
||||
this.textures = textures != null ? textures : new EmptyPlayerTextures();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<ProfileProperty> getProperties() {
|
||||
return new HashSet<>(this.properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(@NotNull String propertyName) {
|
||||
return this.properties.stream().anyMatch(p -> p.getName().equalsIgnoreCase(propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(@NotNull ProfileProperty property) {
|
||||
this.properties.removeIf(p -> p.getName().equalsIgnoreCase(property.getName()));
|
||||
this.properties.add(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(@NotNull Collection<ProfileProperty> properties) {
|
||||
for (ProfileProperty p : properties) {
|
||||
setProperty(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeProperty(@NotNull String propertyName) {
|
||||
return this.properties.removeIf(p -> p.getName().equalsIgnoreCase(propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearProperties() {
|
||||
this.properties.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return this.uuid != null && this.name != null && !this.name.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean completeFromCache() {
|
||||
return completeFromCache(false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean completeFromCache(boolean onlineMode) {
|
||||
return completeFromCache(onlineMode, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean completeFromCache(boolean onlineMode, boolean setRequestProperties) {
|
||||
return isComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean complete(boolean textures) {
|
||||
return complete(textures, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean complete(boolean textures, boolean onlineMode) {
|
||||
return isComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<PlayerProfile> update() {
|
||||
return CompletableFuture.completedFuture(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerProfile clone() {
|
||||
PatchBukkitPlayerProfile copy = new PatchBukkitPlayerProfile(this.uuid, this.name);
|
||||
copy.properties.addAll(this.properties);
|
||||
copy.textures = this.textures;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
if (this.uuid != null) map.put("uniqueId", this.uuid.toString());
|
||||
if (this.name != null) map.put("name", this.name);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PlayerProfile that)) return false;
|
||||
return Objects.equals(this.uuid, that.getId()) && Objects.equals(this.name, that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.uuid, this.name);
|
||||
}
|
||||
|
||||
private static class EmptyPlayerTextures implements PlayerTextures {
|
||||
private URL skin;
|
||||
private URL cape;
|
||||
private SkinModel skinModel = SkinModel.CLASSIC;
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return skin == null && cape == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
skin = null;
|
||||
cape = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URL getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkin(@Nullable URL skinUrl) {
|
||||
this.skin = skinUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkin(@Nullable URL skinUrl, @Nullable SkinModel skinModel) {
|
||||
this.skin = skinUrl;
|
||||
this.skinModel = skinModel != null ? skinModel : SkinModel.CLASSIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SkinModel getSkinModel() {
|
||||
return skinModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URL getCape() {
|
||||
return cape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCape(@Nullable URL capeUrl) {
|
||||
this.cape = capeUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSigned() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package org.patchbukkit.scheduler;
|
||||
|
||||
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitAsyncScheduler implements AsyncScheduler {
|
||||
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runNow(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var future = executor.submit(() -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
try {
|
||||
task.accept(scheduledTask);
|
||||
} finally {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
}
|
||||
});
|
||||
scheduledTask.setFuture(future);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runDelayed(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long delay,
|
||||
@NotNull TimeUnit unit
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var future = executor.schedule(() -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
try {
|
||||
task.accept(scheduledTask);
|
||||
} finally {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
}
|
||||
}, delay, unit);
|
||||
scheduledTask.setFuture(future);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runAtFixedRate(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long initialDelay,
|
||||
long period,
|
||||
@NotNull TimeUnit unit
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, true);
|
||||
var future = executor.scheduleAtFixedRate(() -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
try {
|
||||
task.accept(scheduledTask);
|
||||
} finally {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.IDLE);
|
||||
}
|
||||
}, initialDelay, period, unit);
|
||||
scheduledTask.setFuture(future);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTasks(@NotNull Plugin plugin) {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package org.patchbukkit.scheduler;
|
||||
|
||||
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
@Override
|
||||
public void execute(@NotNull Plugin plugin, @NotNull Runnable run) {
|
||||
Bukkit.getScheduler().runTask(plugin, run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask run(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var bukkitTask = Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
});
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runDelayed(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long delayTicks
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var bukkitTask = Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
}, Math.max(1L, delayTicks));
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runAtFixedRate(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long initialDelayTicks,
|
||||
long periodTicks
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, true);
|
||||
var bukkitTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.IDLE);
|
||||
}, Math.max(1L, initialDelayTicks), Math.max(1L, periodTicks));
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTasks(@NotNull Plugin plugin) {
|
||||
Bukkit.getScheduler().cancelTasks(plugin);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package org.patchbukkit.scheduler;
|
||||
|
||||
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitRegionScheduler implements RegionScheduler {
|
||||
@Override
|
||||
public void execute(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Runnable run) {
|
||||
Bukkit.getScheduler().runTask(plugin, run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask run(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull World world,
|
||||
int chunkX,
|
||||
int chunkZ,
|
||||
@NotNull Consumer<ScheduledTask> task
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var bukkitTask = Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
});
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runDelayed(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull World world,
|
||||
int chunkX,
|
||||
int chunkZ,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long delayTicks
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, false);
|
||||
var bukkitTask = Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.FINISHED);
|
||||
}, Math.max(1L, delayTicks));
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ScheduledTask runAtFixedRate(
|
||||
@NotNull Plugin plugin,
|
||||
@NotNull World world,
|
||||
int chunkX,
|
||||
int chunkZ,
|
||||
@NotNull Consumer<ScheduledTask> task,
|
||||
long initialDelayTicks,
|
||||
long periodTicks
|
||||
) {
|
||||
PatchBukkitScheduledTask scheduledTask = new PatchBukkitScheduledTask(plugin, true);
|
||||
var bukkitTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.RUNNING);
|
||||
task.accept(scheduledTask);
|
||||
scheduledTask.setState(ScheduledTask.ExecutionState.IDLE);
|
||||
}, Math.max(1L, initialDelayTicks), Math.max(1L, periodTicks));
|
||||
scheduledTask.setBukkitTask(bukkitTask);
|
||||
return scheduledTask;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package org.patchbukkit.scheduler;
|
||||
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitScheduledTask implements ScheduledTask {
|
||||
private final Plugin plugin;
|
||||
private final boolean repeating;
|
||||
private final AtomicReference<ExecutionState> state = new AtomicReference<>(ExecutionState.IDLE);
|
||||
private BukkitTask bukkitTask;
|
||||
private Future<?> future;
|
||||
|
||||
public PatchBukkitScheduledTask(@NotNull Plugin plugin, boolean repeating) {
|
||||
this.plugin = plugin;
|
||||
this.repeating = repeating;
|
||||
}
|
||||
|
||||
public void setBukkitTask(BukkitTask bukkitTask) {
|
||||
this.bukkitTask = bukkitTask;
|
||||
}
|
||||
|
||||
public void setFuture(Future<?> future) {
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public void setState(ExecutionState newState) {
|
||||
this.state.set(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Plugin getOwningPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatingTask() {
|
||||
return this.repeating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CancelledState cancel() {
|
||||
if (bukkitTask != null) {
|
||||
bukkitTask.cancel();
|
||||
}
|
||||
if (future != null) {
|
||||
future.cancel(false);
|
||||
}
|
||||
state.set(ExecutionState.CANCELLED);
|
||||
return CancelledState.CANCELLED_BY_CALLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ExecutionState getExecutionState() {
|
||||
return this.state.get();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
package org.patchbukkit.scoreboard;
|
||||
|
||||
import io.papermc.paper.scoreboard.numbers.NumberFormat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scoreboard.Criteria;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.RenderType;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitObjective implements Objective {
|
||||
private final PatchBukkitScoreboard scoreboard;
|
||||
private final String name;
|
||||
private final Criteria criteria;
|
||||
private Component displayName;
|
||||
private RenderType renderType;
|
||||
private DisplaySlot displaySlot;
|
||||
private boolean autoUpdateDisplay = true;
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
public PatchBukkitObjective(
|
||||
PatchBukkitScoreboard scoreboard,
|
||||
String name,
|
||||
Criteria criteria,
|
||||
Component displayName,
|
||||
RenderType renderType
|
||||
) {
|
||||
this.scoreboard = scoreboard;
|
||||
this.name = name;
|
||||
this.criteria = criteria;
|
||||
this.displayName = displayName != null ? displayName : Component.text(name);
|
||||
this.renderType = renderType != null ? renderType : RenderType.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component displayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName != null ? displayName : Component.text(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDisplayName() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(@NotNull String displayName) {
|
||||
this.displayName = LegacyComponentSerializer.legacySection().deserialize(displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getCriteria() {
|
||||
return this.criteria.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Criteria getTrackedCriteria() {
|
||||
return this.criteria;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModifiable() {
|
||||
return !this.criteria.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Scoreboard getScoreboard() {
|
||||
return this.scoreboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
this.scoreboard.unregisterObjective(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@Nullable DisplaySlot slot) {
|
||||
this.displaySlot = slot;
|
||||
if (slot != null) {
|
||||
this.scoreboard.setObjectiveSlot(slot, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DisplaySlot getDisplaySlot() {
|
||||
return this.displaySlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderType(@NotNull RenderType renderType) {
|
||||
this.renderType = renderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderType getRenderType() {
|
||||
return this.renderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Score getScore(@NotNull OfflinePlayer player) {
|
||||
return getScore(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Score getScore(@NotNull String entry) {
|
||||
return this.scoreboard.getScore(this, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Score getScoreFor(@NotNull Entity entity) {
|
||||
return getScore(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willAutoUpdateDisplay() {
|
||||
return this.autoUpdateDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoUpdateDisplay(boolean autoUpdateDisplay) {
|
||||
this.autoUpdateDisplay = autoUpdateDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable NumberFormat numberFormat() {
|
||||
return this.numberFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void numberFormat(@Nullable NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package org.patchbukkit.scoreboard;
|
||||
|
||||
import io.papermc.paper.scoreboard.numbers.NumberFormat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitScore implements Score {
|
||||
private final PatchBukkitScoreboard scoreboard;
|
||||
private final Objective objective;
|
||||
private final String entry;
|
||||
private int score = 0;
|
||||
private boolean scoreSet = false;
|
||||
private boolean triggerable = false;
|
||||
private Component customName;
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
public PatchBukkitScore(PatchBukkitScoreboard scoreboard, Objective objective, String entry) {
|
||||
this.scoreboard = scoreboard;
|
||||
this.objective = objective;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull OfflinePlayer getPlayer() {
|
||||
return Bukkit.getOfflinePlayer(this.entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getEntry() {
|
||||
return this.entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Objective getObjective() {
|
||||
return this.objective;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScore() {
|
||||
return this.score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
this.scoreSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScoreSet() {
|
||||
return this.scoreSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Scoreboard getScoreboard() {
|
||||
return this.scoreboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScore() {
|
||||
this.scoreSet = false;
|
||||
this.score = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggerable() {
|
||||
return this.triggerable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTriggerable(boolean triggerable) {
|
||||
this.triggerable = triggerable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Component customName() {
|
||||
return this.customName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customName(@Nullable Component customName) {
|
||||
this.customName = customName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable NumberFormat numberFormat() {
|
||||
return this.numberFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void numberFormat(@Nullable NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,203 @@
|
||||
package org.patchbukkit.scoreboard;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scoreboard.Criteria;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.RenderType;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitScoreboard implements Scoreboard {
|
||||
private final Map<String, Objective> objectives = new ConcurrentHashMap<>();
|
||||
private final Map<DisplaySlot, Objective> slots = new ConcurrentHashMap<>();
|
||||
private final Map<String, Team> teams = new ConcurrentHashMap<>();
|
||||
private final Map<String, Map<Objective, Score>> scores = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public @NotNull Objective registerNewObjective(
|
||||
@NotNull String name,
|
||||
@NotNull String criteria,
|
||||
@Nullable Component displayName,
|
||||
@NotNull RenderType renderType
|
||||
) throws IllegalArgumentException {
|
||||
return registerNewObjective(name, Criteria.create(criteria), displayName, renderType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Objective registerNewObjective(
|
||||
@NotNull String name,
|
||||
@NotNull Criteria criteria,
|
||||
@Nullable Component displayName,
|
||||
@NotNull RenderType renderType
|
||||
) throws IllegalArgumentException {
|
||||
Objective obj = new PatchBukkitObjective(this, name, criteria, displayName, renderType);
|
||||
this.objectives.put(name, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Objective registerNewObjective(
|
||||
@NotNull String name,
|
||||
@NotNull String criteria,
|
||||
@NotNull String displayName,
|
||||
@NotNull RenderType renderType
|
||||
) {
|
||||
return registerNewObjective(name, Criteria.create(criteria), LegacyComponentSerializer.legacySection().deserialize(displayName), renderType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Objective getObjective(@NotNull String name) {
|
||||
return this.objectives.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Objective> getObjectivesByCriteria(@NotNull String criteria) {
|
||||
Set<Objective> set = new HashSet<>();
|
||||
for (Objective obj : this.objectives.values()) {
|
||||
if (obj.getCriteria().equalsIgnoreCase(criteria)) {
|
||||
set.add(obj);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Objective> getObjectivesByCriteria(@NotNull Criteria criteria) {
|
||||
return getObjectivesByCriteria(criteria.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Objective> getObjectives() {
|
||||
return Collections.unmodifiableSet(new HashSet<>(this.objectives.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Objective getObjective(@NotNull DisplaySlot slot) {
|
||||
return this.slots.get(slot);
|
||||
}
|
||||
|
||||
void setObjectiveSlot(@NotNull DisplaySlot slot, @Nullable Objective obj) {
|
||||
if (obj == null) this.slots.remove(slot);
|
||||
else this.slots.put(slot, obj);
|
||||
}
|
||||
|
||||
void unregisterObjective(Objective obj) {
|
||||
this.objectives.remove(obj.getName());
|
||||
this.slots.values().remove(obj);
|
||||
for (Map<Objective, Score> map : scores.values()) {
|
||||
map.remove(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Score> getScores(@NotNull OfflinePlayer player) {
|
||||
return getScores(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Score> getScores(@NotNull String entry) {
|
||||
Map<Objective, Score> map = this.scores.get(entry);
|
||||
if (map == null) return Collections.emptySet();
|
||||
return Collections.unmodifiableSet(new HashSet<>(map.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScores(@NotNull OfflinePlayer player) {
|
||||
resetScores(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScores(@NotNull String entry) {
|
||||
this.scores.remove(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Team getPlayerTeam(@NotNull OfflinePlayer player) {
|
||||
return getEntryTeam(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Team getEntryTeam(@NotNull String entry) {
|
||||
for (Team team : this.teams.values()) {
|
||||
if (team.hasEntry(entry)) return team;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Team getTeam(@NotNull String teamName) {
|
||||
return this.teams.get(teamName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Team> getTeams() {
|
||||
return Collections.unmodifiableSet(new HashSet<>(this.teams.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Team registerNewTeam(@NotNull String name) throws IllegalArgumentException {
|
||||
if (this.teams.containsKey(name)) {
|
||||
throw new IllegalArgumentException("Team '" + name + "' already exists");
|
||||
}
|
||||
Team team = new PatchBukkitTeam(this, name);
|
||||
this.teams.put(name, team);
|
||||
return team;
|
||||
}
|
||||
|
||||
void unregisterTeam(Team team) {
|
||||
this.teams.remove(team.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<OfflinePlayer> getPlayers() {
|
||||
Set<OfflinePlayer> set = new HashSet<>();
|
||||
for (String entry : getEntries()) {
|
||||
set.add(org.bukkit.Bukkit.getOfflinePlayer(entry));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getEntries() {
|
||||
return Collections.unmodifiableSet(new HashSet<>(this.scores.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSlot(@NotNull DisplaySlot slot) {
|
||||
this.slots.remove(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Score> getScoresFor(@NotNull Entity entity) throws IllegalArgumentException {
|
||||
return getScores(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScoresFor(@NotNull Entity entity) throws IllegalArgumentException {
|
||||
resetScores(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Team getEntityTeam(@NotNull Entity entity) throws IllegalArgumentException {
|
||||
return getEntryTeam(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
Score getScore(Objective objective, String entry) {
|
||||
return scores.computeIfAbsent(entry, k -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(objective, k -> new PatchBukkitScore(this, objective, entry));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package org.patchbukkit.scoreboard;
|
||||
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.ScoreboardManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchBukkitScoreboardManager implements ScoreboardManager {
|
||||
private final Scoreboard mainScoreboard = new PatchBukkitScoreboard();
|
||||
|
||||
@Override
|
||||
public @NotNull Scoreboard getMainScoreboard() {
|
||||
return this.mainScoreboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Scoreboard getNewScoreboard() {
|
||||
return new PatchBukkitScoreboard();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,277 @@
|
||||
package org.patchbukkit.scoreboard;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scoreboard.NameTagVisibility;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitTeam implements Team {
|
||||
private final PatchBukkitScoreboard scoreboard;
|
||||
private final String name;
|
||||
private Component displayName;
|
||||
private Component prefix = Component.empty();
|
||||
private Component suffix = Component.empty();
|
||||
private TextColor color = NamedTextColor.WHITE;
|
||||
private boolean friendlyFire = true;
|
||||
private boolean seeFriendlyInvisibles = false;
|
||||
private NameTagVisibility nameTagVisibility = NameTagVisibility.ALWAYS;
|
||||
private final Set<String> entries = new HashSet<>();
|
||||
private final Map<Option, OptionStatus> options = new EnumMap<>(Option.class);
|
||||
|
||||
public PatchBukkitTeam(PatchBukkitScoreboard scoreboard, String name) {
|
||||
this.scoreboard = scoreboard;
|
||||
this.name = name;
|
||||
this.displayName = Component.text(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> audiences() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component displayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName != null ? displayName : Component.text(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component prefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prefix(@Nullable Component prefix) {
|
||||
this.prefix = prefix != null ? prefix : Component.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component suffix() {
|
||||
return this.suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suffix(@Nullable Component suffix) {
|
||||
this.suffix = suffix != null ? suffix : Component.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasColor() {
|
||||
return this.color != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextColor color() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void color(@Nullable NamedTextColor color) {
|
||||
this.color = color != null ? color : NamedTextColor.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDisplayName() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(@NotNull String displayName) {
|
||||
this.displayName = LegacyComponentSerializer.legacySection().deserialize(displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getPrefix() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrefix(@NotNull String prefix) {
|
||||
this.prefix = LegacyComponentSerializer.legacySection().deserialize(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getSuffix() {
|
||||
return LegacyComponentSerializer.legacySection().serialize(this.suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuffix(@NotNull String suffix) {
|
||||
this.suffix = LegacyComponentSerializer.legacySection().deserialize(suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ChatColor getColor() {
|
||||
return ChatColor.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(@NotNull ChatColor color) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowFriendlyFire() {
|
||||
return this.friendlyFire;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowFriendlyFire(boolean enabled) {
|
||||
this.friendlyFire = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSeeFriendlyInvisibles() {
|
||||
return this.seeFriendlyInvisibles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCanSeeFriendlyInvisibles(boolean enabled) {
|
||||
this.seeFriendlyInvisibles = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NameTagVisibility getNameTagVisibility() {
|
||||
return this.nameTagVisibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameTagVisibility(@NotNull NameTagVisibility visibility) {
|
||||
this.nameTagVisibility = visibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<OfflinePlayer> getPlayers() {
|
||||
Set<OfflinePlayer> players = new HashSet<>();
|
||||
for (String entry : this.entries) {
|
||||
players.add(Bukkit.getOfflinePlayer(entry));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getEntries() {
|
||||
return Collections.unmodifiableSet(new HashSet<>(this.entries));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return this.entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Scoreboard getScoreboard() {
|
||||
return this.scoreboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(@NotNull OfflinePlayer player) {
|
||||
addEntry(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry(@NotNull String entry) {
|
||||
this.entries.add(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntities(@NotNull Collection<Entity> entities) {
|
||||
for (Entity e : entities) {
|
||||
addEntity(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntries(@NotNull Collection<String> entries) {
|
||||
this.entries.addAll(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePlayer(@NotNull OfflinePlayer player) {
|
||||
return removeEntry(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntry(@NotNull String entry) {
|
||||
return this.entries.remove(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntities(@NotNull Collection<Entity> entities) {
|
||||
boolean changed = false;
|
||||
for (Entity e : entities) {
|
||||
if (removeEntity(e)) changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntries(@NotNull Collection<String> entries) {
|
||||
return this.entries.removeAll(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
this.scoreboard.unregisterTeam(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlayer(@NotNull OfflinePlayer player) {
|
||||
return hasEntry(player.getName() != null ? player.getName() : player.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEntry(@NotNull String entry) {
|
||||
return this.entries.contains(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull OptionStatus getOption(@NotNull Option option) {
|
||||
return this.options.getOrDefault(option, OptionStatus.ALWAYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption(@NotNull Option option, @NotNull OptionStatus status) {
|
||||
this.options.put(option, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntity(@NotNull Entity entity) {
|
||||
addEntry(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntity(@NotNull Entity entity) {
|
||||
return removeEntry(entity.getUniqueId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEntity(@NotNull Entity entity) {
|
||||
return hasEntry(entity.getUniqueId().toString());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package org.patchbukkit.structure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.structure.Structure;
|
||||
import org.bukkit.structure.StructureManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PatchBukkitStructureManager implements StructureManager {
|
||||
private final Map<NamespacedKey, Structure> structures = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public @NotNull Map<NamespacedKey, Structure> getStructures() {
|
||||
return Collections.unmodifiableMap(this.structures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Structure getStructure(@NotNull NamespacedKey structureKey) {
|
||||
return this.structures.get(structureKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Structure registerStructure(@NotNull NamespacedKey structureKey, @NotNull Structure structure) {
|
||||
this.structures.put(structureKey, structure);
|
||||
return structure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Structure unregisterStructure(@NotNull NamespacedKey structureKey) {
|
||||
return this.structures.remove(structureKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Structure loadStructure(@NotNull NamespacedKey structureKey, boolean updateFlags) {
|
||||
return this.structures.get(structureKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Structure loadStructure(@NotNull NamespacedKey structureKey) {
|
||||
return loadStructure(structureKey, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveStructure(@NotNull NamespacedKey structureKey) {}
|
||||
|
||||
@Override
|
||||
public void saveStructure(@NotNull NamespacedKey structureKey, @NotNull Structure structure) throws IOException {
|
||||
this.structures.put(structureKey, structure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStructure(@NotNull NamespacedKey structureKey) throws IOException {
|
||||
this.structures.remove(structureKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStructure(@NotNull NamespacedKey structureKey, boolean unregister) throws IOException {
|
||||
if (unregister) {
|
||||
this.structures.remove(structureKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull File getStructureFile(@NotNull NamespacedKey structureKey) {
|
||||
return new File(structureKey.getKey() + ".nbt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Structure loadStructure(@NotNull File file) throws IOException {
|
||||
return createStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Structure loadStructure(@NotNull InputStream inputStream) throws IOException {
|
||||
return createStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveStructure(@NotNull File file, @NotNull Structure structure) throws IOException {}
|
||||
|
||||
@Override
|
||||
public void saveStructure(@NotNull OutputStream outputStream, @NotNull Structure structure) throws IOException {}
|
||||
|
||||
@Override
|
||||
public @NotNull Structure createStructure() {
|
||||
return (Structure) java.lang.reflect.Proxy.newProxyInstance(
|
||||
Structure.class.getClassLoader(),
|
||||
new Class<?>[] { Structure.class },
|
||||
(proxy, method, args) -> null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Structure copy(@NotNull Structure structure) {
|
||||
return createStructure();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
package org.patchbukkit.tick;
|
||||
|
||||
import org.bukkit.ServerTickManager;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import patchbukkit.bridge.NativeBridgeFfi;
|
||||
import patchbukkit.common.EmptyRequest;
|
||||
import patchbukkit.server.ServerTickInfoResponse;
|
||||
import patchbukkit.server.SetServerTickRateRequest;
|
||||
|
||||
public class PatchBukkitServerTickManager implements ServerTickManager {
|
||||
private float tickRate = 20.0f;
|
||||
private boolean frozen = false;
|
||||
|
||||
@Override
|
||||
public boolean isRunningNormally() {
|
||||
return !isFrozen() && !isSprinting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStepping() {
|
||||
try {
|
||||
ServerTickInfoResponse info = NativeBridgeFfi.getServerTickInfo(EmptyRequest.getDefaultInstance());
|
||||
if (info != null) return info.getIsStepping();
|
||||
} catch (Throwable ignored) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
try {
|
||||
ServerTickInfoResponse info = NativeBridgeFfi.getServerTickInfo(EmptyRequest.getDefaultInstance());
|
||||
if (info != null) return info.getIsSprinting();
|
||||
} catch (Throwable ignored) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen() {
|
||||
try {
|
||||
ServerTickInfoResponse info = NativeBridgeFfi.getServerTickInfo(EmptyRequest.getDefaultInstance());
|
||||
if (info != null) return info.getIsFrozen();
|
||||
} catch (Throwable ignored) {}
|
||||
return this.frozen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTickRate() {
|
||||
try {
|
||||
ServerTickInfoResponse info = NativeBridgeFfi.getServerTickInfo(EmptyRequest.getDefaultInstance());
|
||||
if (info != null) return info.getTickRate();
|
||||
} catch (Throwable ignored) {}
|
||||
return this.tickRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickRate(float tickRate) {
|
||||
this.tickRate = tickRate;
|
||||
try {
|
||||
NativeBridgeFfi.setServerTickRate(SetServerTickRateRequest.newBuilder()
|
||||
.setTickRate(tickRate)
|
||||
.setFrozen(this.frozen)
|
||||
.build());
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrozen(boolean frozen) {
|
||||
this.frozen = frozen;
|
||||
try {
|
||||
NativeBridgeFfi.setServerTickRate(SetServerTickRateRequest.newBuilder()
|
||||
.setTickRate(this.tickRate)
|
||||
.setFrozen(frozen)
|
||||
.build());
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stepGameIfFrozen(int ticks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopStepping() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestGameToSprint(int ticks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopSprinting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen(@NotNull Entity entity) {
|
||||
return isFrozen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrozenTicksToRun() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
package org.patchbukkit.world;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -7,17 +10,16 @@ import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitBlockState implements BlockState {
|
||||
private final Block block;
|
||||
private BlockData data;
|
||||
@ -168,13 +170,11 @@ public class PatchBukkitBlockState implements BlockState {
|
||||
|
||||
@Override
|
||||
public byte getLightLevel() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getLightLevel'");
|
||||
return this.block.getLightLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull @Unmodifiable Collection<ItemStack> getDrops(@Nullable ItemStack tool, @Nullable Entity entity) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getDrops'");
|
||||
return this.block.getDrops(tool, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,36 @@
|
||||
package org.patchbukkit.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.patchbukkit.persistence.PatchBukkitPersistentDataContainer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PatchBukkitChunk implements Chunk {
|
||||
private final World world;
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final Set<Plugin> tickets = ConcurrentHashMap.newKeySet();
|
||||
private long inhabitedTime = 0;
|
||||
private final org.bukkit.persistence.PersistentDataContainer pdc = new PatchBukkitPersistentDataContainer();
|
||||
|
||||
public PatchBukkitChunk(World world, int x, int z) {
|
||||
this.world = world;
|
||||
@ -41,7 +55,7 @@ public class PatchBukkitChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public @NotNull Block getBlock(int x, int y, int z) {
|
||||
return this.world.getBlockAt((this.x << 4) + x, y, (this.z << 4) + z);
|
||||
return this.world.getBlockAt((this.x << 4) + (x & 0xF), y, (this.z << 4) + (z & 0xF));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -56,7 +70,103 @@ public class PatchBukkitChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public @NotNull ChunkSnapshot getChunkSnapshot(boolean includeMaxBlocky, boolean includeBiome, boolean includeBiomeTempRain, boolean includeBiome3D) {
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getChunkSnapshot'");
|
||||
final String worldName = this.world.getName();
|
||||
final Key worldKey = this.world.getKey();
|
||||
final int chunkX = this.x;
|
||||
final int chunkZ = this.z;
|
||||
final long captureFullTime = this.world.getFullTime();
|
||||
|
||||
return new ChunkSnapshot() {
|
||||
@Override
|
||||
public int getX() {
|
||||
return chunkX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Key getWorldKey() {
|
||||
return worldKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Material getBlockType(int x, int y, int z) {
|
||||
return getBlockData(x, y, z).getMaterial();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockData getBlockData(int x, int y, int z) {
|
||||
return PatchBukkitChunk.this.getBlock(x, y, z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getData(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockSkyLight(int x, int y, int z) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockEmittedLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestBlockYAt(int x, int z) {
|
||||
return PatchBukkitChunk.this.world.getHighestBlockYAt((chunkX << 4) + x, (chunkZ << 4) + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getBiome(int x, int z) {
|
||||
return PatchBukkitChunk.this.world.getBiome((chunkX << 4) + x, 64, (chunkZ << 4) + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getBiome(int x, int y, int z) {
|
||||
return PatchBukkitChunk.this.world.getBiome((chunkX << 4) + x, y, (chunkZ << 4) + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRawBiomeTemperature(int x, int z) {
|
||||
return 0.8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRawBiomeTemperature(int x, int y, int z) {
|
||||
return 0.8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCaptureFullTime() {
|
||||
return captureFullTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSectionEmpty(int sy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull BlockData block) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull Biome biome) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,12 +176,26 @@ public class PatchBukkitChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public @NotNull Entity[] getEntities() {
|
||||
return new Entity[0];
|
||||
List<Entity> list = new ArrayList<>();
|
||||
int minX = this.x << 4;
|
||||
int maxX = minX + 15;
|
||||
int minZ = this.z << 4;
|
||||
int maxZ = minZ + 15;
|
||||
|
||||
for (Entity e : this.world.getEntities()) {
|
||||
Location loc = e.getLocation();
|
||||
int ex = loc.getBlockX();
|
||||
int ez = loc.getBlockZ();
|
||||
if (ex >= minX && ex <= maxX && ez >= minZ && ez <= maxZ) {
|
||||
list.add(e);
|
||||
}
|
||||
}
|
||||
return list.toArray(new Entity[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState[] getTileEntities() {
|
||||
return new BlockState[0];
|
||||
return getTileEntities(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -111,40 +235,50 @@ public class PatchBukkitChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public boolean isSlimeChunk() {
|
||||
return false;
|
||||
long seed = this.world.getSeed();
|
||||
java.util.Random rnd = new java.util.Random(
|
||||
seed +
|
||||
(long) (this.x * this.x * 4987142) +
|
||||
(long) (this.x * 5947611) +
|
||||
(long) (this.z * this.z) * 4392871L +
|
||||
(long) (this.z * 389711) ^ 987234911L
|
||||
);
|
||||
return rnd.nextInt(10) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceLoaded() {
|
||||
return false;
|
||||
return this.world.isChunkForceLoaded(this.x, this.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceLoaded(boolean progress) {
|
||||
this.world.setChunkForceLoaded(this.x, this.z, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPluginChunkTicket(@NotNull Plugin plugin) {
|
||||
return true;
|
||||
return this.world.addPluginChunkTicket(this.x, this.z, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePluginChunkTicket(@NotNull Plugin plugin) {
|
||||
return true;
|
||||
return this.world.removePluginChunkTicket(this.x, this.z, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Plugin> getPluginChunkTickets() {
|
||||
return Collections.emptyList();
|
||||
return this.world.getPluginChunkTickets(this.x, this.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInhabitedTime() {
|
||||
return 0;
|
||||
return this.inhabitedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInhabitedTime(long ticks) {
|
||||
this.inhabitedTime = ticks;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -153,8 +287,22 @@ public class PatchBukkitChunk implements Chunk {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<org.bukkit.entity.Player> getPlayersSeeingChunk() {
|
||||
return Collections.emptyList();
|
||||
public @NotNull Collection<Player> getPlayersSeeingChunk() {
|
||||
List<Player> seeing = new ArrayList<>();
|
||||
int minX = (this.x - 10) << 4;
|
||||
int maxX = (this.x + 11) << 4;
|
||||
int minZ = (this.z - 10) << 4;
|
||||
int maxZ = (this.z + 11) << 4;
|
||||
|
||||
for (Player p : this.world.getPlayers()) {
|
||||
Location loc = p.getLocation();
|
||||
int px = loc.getBlockX();
|
||||
int pz = loc.getBlockZ();
|
||||
if (px >= minX && px <= maxX && pz >= minZ && pz <= maxZ) {
|
||||
seeing.add(p);
|
||||
}
|
||||
}
|
||||
return seeing;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -173,12 +321,10 @@ public class PatchBukkitChunk implements Chunk {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull org.bukkit.block.Biome biome) {
|
||||
public boolean contains(@NotNull Biome biome) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private final org.bukkit.persistence.PersistentDataContainer pdc = new org.patchbukkit.persistence.PatchBukkitPersistentDataContainer();
|
||||
|
||||
@Override
|
||||
public @NotNull org.bukkit.persistence.PersistentDataContainer getPersistentDataContainer() {
|
||||
return this.pdc;
|
||||
|
||||
@ -2,10 +2,13 @@ package org.patchbukkit.world;
|
||||
|
||||
import io.papermc.paper.block.fluid.FluidData;
|
||||
import io.papermc.paper.world.MoonPhase;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import org.bukkit.*;
|
||||
@ -22,54 +25,51 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.patchbukkit.bridge.BridgeUtils;
|
||||
import org.patchbukkit.entity.PatchBukkitEntity;
|
||||
import patchbukkit.bridge.NativeBridgeFfi;
|
||||
import patchbukkit.world.GetBlockDataRequest;
|
||||
import patchbukkit.world.SetBlockDataRequest;
|
||||
import patchbukkit.world.SpawnWorldEntityRequest;
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getBiome(int x, int y, int z) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getBiome'"
|
||||
);
|
||||
return Biome.PLAINS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getComputedBiome(int x, int y, int z) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getComputedBiome'"
|
||||
);
|
||||
return getBiome(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, @NotNull Biome biome) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'setBiome'"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlockState(int x, int y, int z) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getBlockState'"
|
||||
);
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
return new PatchBukkitBlockState(world.getBlockAt(x, y, z));
|
||||
}
|
||||
return new PatchBukkitBlockState(new PatchBukkitBlock(null, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FluidData getFluidData(int x, int y, int z) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getFluidData'"
|
||||
);
|
||||
return new FluidData() {
|
||||
@Override public @NotNull org.bukkit.Fluid getFluidType() { return org.bukkit.Fluid.EMPTY; }
|
||||
@Override public @NotNull FluidData clone() { return this; }
|
||||
@Override public @NotNull org.bukkit.util.Vector computeFlowDirection(@NotNull Location location) { return new org.bukkit.util.Vector(0, 0, 0); }
|
||||
@Override public int getLevel() { return 0; }
|
||||
@Override public float computeHeight(@NotNull Location location) { return 0.0f; }
|
||||
@Override public boolean isSource() { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @org.jetbrains.annotations.NotNull BlockData getBlockData(int x, int y, int z) {
|
||||
public @NotNull BlockData getBlockData(int x, int y, int z) {
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
var request = GetBlockDataRequest.newBuilder()
|
||||
.setWorldUuid(BridgeUtils.convertUuid(world.getUID()))
|
||||
@ -80,9 +80,6 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
try {
|
||||
var response = NativeBridgeFfi.getBlockData(request);
|
||||
if (response != null && !response.getBlockState().isEmpty()) {
|
||||
// The bridge returns the actual block state string (e.g.
|
||||
// "minecraft:oak_stairs[facing=north]"). Previously the response was
|
||||
// discarded and every non-air block reported as STONE.
|
||||
return Bukkit.createBlockData(response.getBlockState());
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
@ -91,12 +88,12 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @org.jetbrains.annotations.NotNull Material getType(int x, int y, int z) {
|
||||
public @NotNull Material getType(int x, int y, int z) {
|
||||
return getBlockData(x, y, z).getMaterial();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockData(int x, int y, int z, @org.jetbrains.annotations.NotNull BlockData blockData) {
|
||||
public void setBlockData(int x, int y, int z, @NotNull BlockData blockData) {
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
var request = SetBlockDataRequest.newBuilder()
|
||||
.setWorldUuid(BridgeUtils.convertUuid(world.getUID()))
|
||||
@ -106,7 +103,9 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
.setBlockState(blockData.getAsString())
|
||||
.setApplyPhysics(true)
|
||||
.build();
|
||||
NativeBridgeFfi.setBlockData(request);
|
||||
try {
|
||||
NativeBridgeFfi.setBlockData(request);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,10 +115,7 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull Random random,
|
||||
@NotNull TreeType type
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'generateTree'"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,10 +125,7 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull TreeType type,
|
||||
@Nullable Consumer<? super BlockState> stateConsumer
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'generateTree'"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,10 +135,7 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull TreeType type,
|
||||
@Nullable Predicate<? super BlockState> statePredicate
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'generateTree'"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -154,46 +144,70 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull EntityType type,
|
||||
boolean randomizeData
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'spawnEntity'"
|
||||
);
|
||||
UUID worldUuid = (this instanceof PatchBukkitWorld w) ? w.getUID() : UUID.randomUUID();
|
||||
UUID entityUuid = UUID.randomUUID();
|
||||
try {
|
||||
var res = NativeBridgeFfi.spawnWorldEntity(SpawnWorldEntityRequest.newBuilder()
|
||||
.setWorldUuid(BridgeUtils.convertUuid(worldUuid))
|
||||
.setEntityType(type.name())
|
||||
.setX(loc.getX())
|
||||
.setY(loc.getY())
|
||||
.setZ(loc.getZ())
|
||||
.setYaw(loc.getYaw())
|
||||
.setPitch(loc.getPitch())
|
||||
.build());
|
||||
if (res != null && res.hasEntityUuid()) {
|
||||
entityUuid = UUID.fromString(res.getEntityUuid().getValue());
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
Entity entity = PatchBukkitEntity.create(entityUuid, type, loc);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<Entity> getEntities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getEntities'"
|
||||
);
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
return world.getEntities();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<LivingEntity> getLivingEntities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getLivingEntities'"
|
||||
);
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
return world.getLivingEntities();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <T extends Entity> Collection<T> getEntitiesByClass(
|
||||
@NotNull Class<T> cls
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getEntitiesByClass'"
|
||||
);
|
||||
List<T> list = new ArrayList<>();
|
||||
for (Entity e : getEntities()) {
|
||||
if (cls.isInstance(e)) {
|
||||
list.add((T) e);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Entity> getEntitiesByClasses(
|
||||
@NonNull @NotNull Class<?>... classes
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getEntitiesByClasses'"
|
||||
);
|
||||
List<Entity> list = new ArrayList<>();
|
||||
for (Entity e : getEntities()) {
|
||||
for (Class<?> c : classes) {
|
||||
if (c.isInstance(e)) {
|
||||
list.add(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -201,10 +215,14 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull Location location,
|
||||
@NotNull Class<T> clazz
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'createEntity'"
|
||||
);
|
||||
EntityType type = EntityType.PIG;
|
||||
for (EntityType et : EntityType.values()) {
|
||||
if (et.getEntityClass() != null && clazz.isAssignableFrom(et.getEntityClass())) {
|
||||
type = et;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (T) PatchBukkitEntity.create(UUID.randomUUID(), type, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -214,8 +232,11 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@Nullable Consumer<? super T> function,
|
||||
CreatureSpawnEvent.@NotNull SpawnReason reason
|
||||
) throws IllegalArgumentException {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'spawn'");
|
||||
T entity = createEntity(location, clazz);
|
||||
if (function != null) {
|
||||
function.accept(entity);
|
||||
}
|
||||
return addEntity(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,32 +246,30 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
boolean randomizeData,
|
||||
@Nullable Consumer<? super T> function
|
||||
) throws IllegalArgumentException {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'spawn'");
|
||||
return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestBlockYAt(int x, int z) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getHighestBlockYAt'"
|
||||
);
|
||||
return getHighestBlockYAt(x, z, HeightMap.WORLD_SURFACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestBlockYAt(@NotNull Location location) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getHighestBlockYAt'"
|
||||
);
|
||||
return getHighestBlockYAt(location.getBlockX(), location.getBlockZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestBlockYAt(int x, int z, @NotNull HeightMap heightMap) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getHighestBlockYAt'"
|
||||
);
|
||||
int maxY = (this instanceof PatchBukkitWorld w) ? w.getMaxHeight() - 1 : 255;
|
||||
int minY = (this instanceof PatchBukkitWorld w) ? w.getMinHeight() : -64;
|
||||
for (int y = maxY; y >= minY; y--) {
|
||||
Material type = getType(x, y, z);
|
||||
if (type != Material.AIR && type != Material.VOID_AIR && type != Material.CAVE_AIR) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return minY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -258,34 +277,33 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull Location location,
|
||||
@NotNull HeightMap heightMap
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getHighestBlockYAt'"
|
||||
);
|
||||
return getHighestBlockYAt(location.getBlockX(), location.getBlockZ(), heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull <T extends Entity> T addEntity(@NonNull T entity) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'addEntity'"
|
||||
);
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
world.registerEntity(entity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull MoonPhase getMoonPhase() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getMoonPhase'"
|
||||
);
|
||||
long day = 0;
|
||||
if (this instanceof PatchBukkitWorld w) {
|
||||
day = w.getFullTime() / 24000L;
|
||||
}
|
||||
int phaseIndex = (int) (day % 8);
|
||||
return MoonPhase.values()[Math.abs(phaseIndex)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NamespacedKey getKey() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getKey'"
|
||||
);
|
||||
if (this instanceof PatchBukkitWorld world) {
|
||||
return world.getKey();
|
||||
}
|
||||
return NamespacedKey.minecraft("overworld");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -293,25 +311,16 @@ public class PatchBukkitRegionAccessor implements RegionAccessor {
|
||||
@NotNull Location from,
|
||||
@NotNull Location to
|
||||
) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'lineOfSightExists'"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCollisionsIn(@NotNull BoundingBox boundingBox) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'hasCollisionsIn'"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable Set<FeatureFlag> getFeatureFlags() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException(
|
||||
"Unimplemented method 'getFeatureFlags'"
|
||||
);
|
||||
return Collections.singleton(FeatureFlag.VANILLA);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,7 @@ import "patchbukkit/itemstack.proto";
|
||||
import "patchbukkit/log.proto";
|
||||
import "patchbukkit/message.proto";
|
||||
import "patchbukkit/registry.proto";
|
||||
import "patchbukkit/server.proto";
|
||||
import "patchbukkit/sound.proto";
|
||||
import "patchbukkit/world.proto";
|
||||
|
||||
@ -32,6 +33,50 @@ service NativeBridge {
|
||||
rpc IsOnGround(patchbukkit.common.UUID) returns (patchbukkit.entity.IsOnGroundResponse);
|
||||
rpc GetPlayerLocale(patchbukkit.common.UUID) returns (patchbukkit.entity.GetPlayerLocaleResponse);
|
||||
rpc IsOp(patchbukkit.common.UUID) returns (patchbukkit.entity.IsOpResponse);
|
||||
rpc SetOp(patchbukkit.entity.SetOpRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetFoodLevel(patchbukkit.common.UUID) returns (patchbukkit.entity.GetFoodLevelResponse);
|
||||
rpc SetFoodLevel(patchbukkit.entity.SetFoodLevelRequest) returns (google.protobuf.Empty);
|
||||
rpc SetSaturation(patchbukkit.entity.SetSaturationRequest) returns (google.protobuf.Empty);
|
||||
rpc SetExhaustion(patchbukkit.entity.SetExhaustionRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetExperience(patchbukkit.common.UUID) returns (patchbukkit.entity.GetExperienceResponse);
|
||||
rpc SetExperience(patchbukkit.entity.SetExperienceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc KickPlayer(patchbukkit.entity.KickPlayerRequest) returns (google.protobuf.Empty);
|
||||
rpc SendTitle(patchbukkit.entity.SendTitleRequest) returns (google.protobuf.Empty);
|
||||
rpc SendActionBar(patchbukkit.entity.SendActionBarRequest) returns (google.protobuf.Empty);
|
||||
rpc ResetTitle(patchbukkit.common.UUID) returns (google.protobuf.Empty);
|
||||
|
||||
rpc SetDisplayName(patchbukkit.entity.SetDisplayNameRequest) returns (google.protobuf.Empty);
|
||||
rpc SetPlayerListName(patchbukkit.entity.SetPlayerListNameRequest) returns (google.protobuf.Empty);
|
||||
rpc SetPlayerListHeaderFooter(patchbukkit.entity.SetPlayerListHeaderFooterRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetPlayerPoseState(patchbukkit.common.UUID) returns (patchbukkit.entity.GetPlayerPoseStateResponse);
|
||||
rpc SetSneaking(patchbukkit.entity.SetSneakingRequest) returns (google.protobuf.Empty);
|
||||
rpc SetSprinting(patchbukkit.entity.SetSprintingRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc SetPlayerTime(patchbukkit.entity.SetPlayerTimeRequest) returns (google.protobuf.Empty);
|
||||
rpc ResetPlayerTime(patchbukkit.common.UUID) returns (google.protobuf.Empty);
|
||||
rpc SetPlayerWeather(patchbukkit.entity.SetPlayerWeatherRequest) returns (google.protobuf.Empty);
|
||||
rpc ResetPlayerWeather(patchbukkit.common.UUID) returns (google.protobuf.Empty);
|
||||
|
||||
rpc SetCompassTarget(patchbukkit.entity.SetCompassTargetRequest) returns (google.protobuf.Empty);
|
||||
rpc GetCompassTarget(patchbukkit.common.UUID) returns (patchbukkit.common.Vec3);
|
||||
rpc SetRespawnPoint(patchbukkit.entity.SetRespawnPointRequest) returns (google.protobuf.Empty);
|
||||
rpc GetRespawnPoint(patchbukkit.common.UUID) returns (patchbukkit.common.Location);
|
||||
|
||||
rpc StopSound(patchbukkit.entity.StopSoundRequest) returns (google.protobuf.Empty);
|
||||
rpc SendBlockChange(patchbukkit.entity.SendBlockChangeRequest) returns (google.protobuf.Empty);
|
||||
rpc SendResourcePack(patchbukkit.entity.SendResourcePackRequest) returns (google.protobuf.Empty);
|
||||
rpc GetPlayerConnectionInfo(patchbukkit.common.UUID) returns (patchbukkit.entity.PlayerConnectionInfoResponse);
|
||||
rpc SendGameEvent(patchbukkit.entity.SendGameEventRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc SetCooldown(patchbukkit.entity.SetCooldownRequest) returns (google.protobuf.Empty);
|
||||
rpc GetCooldown(patchbukkit.entity.GetCooldownRequest) returns (patchbukkit.entity.GetCooldownResponse);
|
||||
|
||||
rpc OpenEnderChest(patchbukkit.common.UUID) returns (google.protobuf.Empty);
|
||||
rpc UpdateInventory(patchbukkit.common.UUID) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetPlayerInventory(patchbukkit.common.UUID) returns (patchbukkit.itemstack.GetPlayerInventoryResponse);
|
||||
rpc SetPlayerInventorySlot(patchbukkit.itemstack.SetPlayerInventorySlotRequest) returns (google.protobuf.Empty);
|
||||
@ -65,5 +110,46 @@ service NativeBridge {
|
||||
rpc RegisterCommand(patchbukkit.command.RegisterCommandRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetWorldInfo(patchbukkit.world.GetWorldInfoRequest) returns (patchbukkit.world.GetWorldInfoResponse);
|
||||
rpc SetWorldTime(patchbukkit.world.SetWorldTimeRequest) returns (google.protobuf.Empty);
|
||||
rpc SetWorldWeather(patchbukkit.world.SetWorldWeatherRequest) returns (google.protobuf.Empty);
|
||||
rpc SetWorldSpawn(patchbukkit.world.SetWorldSpawnRequest) returns (google.protobuf.Empty);
|
||||
rpc SetWorldDifficulty(patchbukkit.world.SetWorldDifficultyRequest) returns (google.protobuf.Empty);
|
||||
rpc SetWorldPvp(patchbukkit.world.SetWorldPvpRequest) returns (google.protobuf.Empty);
|
||||
rpc SetWorldGamerule(patchbukkit.world.SetWorldGameruleRequest) returns (google.protobuf.Empty);
|
||||
rpc GetWorldGamerules(patchbukkit.world.GetWorldGamerulesRequest) returns (patchbukkit.world.GetWorldGamerulesResponse);
|
||||
rpc GetWorldEntities(patchbukkit.world.GetWorldEntitiesRequest) returns (patchbukkit.world.GetWorldEntitiesResponse);
|
||||
rpc SpawnWorldEntity(patchbukkit.world.SpawnWorldEntityRequest) returns (patchbukkit.world.SpawnWorldEntityResponse);
|
||||
rpc CreateWorldExplosion(patchbukkit.world.CreateWorldExplosionRequest) returns (google.protobuf.Empty);
|
||||
rpc PlayWorldSound(patchbukkit.world.PlayWorldSoundRequest) returns (google.protobuf.Empty);
|
||||
rpc SetChunkForceLoaded(patchbukkit.world.SetChunkForceLoadedRequest) returns (google.protobuf.Empty);
|
||||
rpc GetForceLoadedChunks(patchbukkit.world.GetForceLoadedChunksRequest) returns (patchbukkit.world.GetForceLoadedChunksResponse);
|
||||
rpc SaveWorld(patchbukkit.world.SaveWorldRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetServerInfo(patchbukkit.common.EmptyRequest) returns (patchbukkit.server.ServerInfoResponse);
|
||||
rpc SetServerMotd(patchbukkit.server.SetServerMotdRequest) returns (google.protobuf.Empty);
|
||||
rpc SetServerMaxPlayers(patchbukkit.server.SetServerMaxPlayersRequest) returns (google.protobuf.Empty);
|
||||
rpc SetServerWhitelist(patchbukkit.server.SetServerWhitelistRequest) returns (google.protobuf.Empty);
|
||||
rpc SetServerWhitelistEnforced(patchbukkit.server.SetServerWhitelistEnforcedRequest) returns (google.protobuf.Empty);
|
||||
rpc SetServerIdleTimeout(patchbukkit.server.SetServerIdleTimeoutRequest) returns (google.protobuf.Empty);
|
||||
rpc SetServerDefaultGamemode(patchbukkit.server.SetServerDefaultGamemodeRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetServerTickInfo(patchbukkit.common.EmptyRequest) returns (patchbukkit.server.ServerTickInfoResponse);
|
||||
rpc SetServerTickRate(patchbukkit.server.SetServerTickRateRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc ShutdownServer(patchbukkit.server.ShutdownServerRequest) returns (google.protobuf.Empty);
|
||||
rpc BroadcastMessage(patchbukkit.server.BroadcastMessageRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetWhitelist(patchbukkit.common.EmptyRequest) returns (patchbukkit.server.GetWhitelistResponse);
|
||||
rpc SetWhitelistPlayer(patchbukkit.server.SetWhitelistPlayerRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetOperators(patchbukkit.common.EmptyRequest) returns (patchbukkit.server.GetOperatorsResponse);
|
||||
rpc SetOperator(patchbukkit.server.SetOperatorRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetBanList(patchbukkit.server.GetBanListRequest) returns (patchbukkit.server.GetBanListResponse);
|
||||
rpc SetBanEntry(patchbukkit.server.SetBanEntryRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc CreateWorld(patchbukkit.server.CreateWorldRequest) returns (patchbukkit.server.CreateWorldResponse);
|
||||
rpc UnloadWorld(patchbukkit.server.UnloadWorldRequest) returns (patchbukkit.server.UnloadWorldResponse);
|
||||
rpc SaveAllWorlds(patchbukkit.common.EmptyRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +66,171 @@ message IsOpResponse {
|
||||
bool is_op = 1;
|
||||
}
|
||||
|
||||
message SetOpRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
bool is_op = 2;
|
||||
}
|
||||
|
||||
message GetFoodLevelResponse {
|
||||
int32 food_level = 1;
|
||||
float saturation = 2;
|
||||
float exhaustion = 3;
|
||||
}
|
||||
|
||||
message SetFoodLevelRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int32 food_level = 2;
|
||||
}
|
||||
|
||||
message SetSaturationRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
float saturation = 2;
|
||||
}
|
||||
|
||||
message SetExhaustionRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
float exhaustion = 2;
|
||||
}
|
||||
|
||||
message GetExperienceResponse {
|
||||
int32 level = 1;
|
||||
float progress = 2;
|
||||
int32 total_experience = 3;
|
||||
}
|
||||
|
||||
message SetExperienceRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int32 level = 2;
|
||||
float progress = 3;
|
||||
int32 total_experience = 4;
|
||||
}
|
||||
|
||||
message KickPlayerRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message SendTitleRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string title = 2;
|
||||
string subtitle = 3;
|
||||
int32 fade_in = 4;
|
||||
int32 stay = 5;
|
||||
int32 fade_out = 6;
|
||||
}
|
||||
|
||||
message SendActionBarRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message SetDisplayNameRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string display_name = 2;
|
||||
}
|
||||
|
||||
message SetPlayerListNameRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string list_name = 2;
|
||||
}
|
||||
|
||||
message SetPlayerListHeaderFooterRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string header = 2;
|
||||
string footer = 3;
|
||||
}
|
||||
|
||||
message GetPlayerPoseStateResponse {
|
||||
bool is_sneaking = 1;
|
||||
bool is_sprinting = 2;
|
||||
bool is_gliding = 3;
|
||||
bool is_swimming = 4;
|
||||
bool is_sleeping = 5;
|
||||
}
|
||||
|
||||
message SetSneakingRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
bool sneaking = 2;
|
||||
}
|
||||
|
||||
message SetSprintingRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
bool sprinting = 2;
|
||||
}
|
||||
|
||||
message SetPlayerTimeRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int64 time = 2;
|
||||
bool relative = 3;
|
||||
}
|
||||
|
||||
message SetPlayerWeatherRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int32 weather = 2;
|
||||
}
|
||||
|
||||
message SetCompassTargetRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
patchbukkit.common.Vec3 position = 2;
|
||||
}
|
||||
|
||||
message SetRespawnPointRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
patchbukkit.common.Vec3 position = 2;
|
||||
float yaw = 3;
|
||||
bool force = 4;
|
||||
}
|
||||
|
||||
message StopSoundRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string sound = 2;
|
||||
string category = 3;
|
||||
}
|
||||
|
||||
message SendBlockChangeRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int32 x = 2;
|
||||
int32 y = 3;
|
||||
int32 z = 4;
|
||||
string block_state = 5;
|
||||
}
|
||||
|
||||
message SendResourcePackRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string url = 2;
|
||||
string prompt = 3;
|
||||
bool required = 4;
|
||||
}
|
||||
|
||||
message PlayerConnectionInfoResponse {
|
||||
int32 ping = 1;
|
||||
string address = 2;
|
||||
int32 port = 3;
|
||||
string client_brand = 4;
|
||||
}
|
||||
|
||||
message SendGameEventRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
int32 event_type = 2;
|
||||
float value = 3;
|
||||
}
|
||||
|
||||
message SetCooldownRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string item_group = 2;
|
||||
int32 duration_ticks = 3;
|
||||
}
|
||||
|
||||
message GetCooldownRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string item_group = 2;
|
||||
}
|
||||
|
||||
message GetCooldownResponse {
|
||||
float cooldown = 1;
|
||||
bool is_on_cooldown = 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
162
proto/patchbukkit/server.proto
Normal file
162
proto/patchbukkit/server.proto
Normal file
@ -0,0 +1,162 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package patchbukkit.server;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "patchbukkit/common/types.proto";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "patchbukkit.server";
|
||||
|
||||
message ServerInfoResponse {
|
||||
string server_name = 1;
|
||||
string version = 2;
|
||||
string bukkit_version = 3;
|
||||
string minecraft_version = 4;
|
||||
string motd = 5;
|
||||
string ip = 6;
|
||||
int32 port = 7;
|
||||
int32 max_players = 8;
|
||||
int32 view_distance = 9;
|
||||
int32 simulation_distance = 10;
|
||||
bool allow_flight = 11;
|
||||
bool allow_nether = 12;
|
||||
bool allow_end = 13;
|
||||
bool online_mode = 14;
|
||||
bool hardcore = 15;
|
||||
bool pvp = 16;
|
||||
bool has_whitelist = 17;
|
||||
bool is_whitelist_enforced = 18;
|
||||
int32 spawn_protection = 19;
|
||||
string default_gamemode = 20;
|
||||
int32 idle_timeout = 21;
|
||||
bool generate_structures = 22;
|
||||
int32 max_world_size = 23;
|
||||
}
|
||||
|
||||
message SetServerMotdRequest {
|
||||
string motd = 1;
|
||||
}
|
||||
|
||||
message SetServerMaxPlayersRequest {
|
||||
int32 max_players = 1;
|
||||
}
|
||||
|
||||
message SetServerWhitelistRequest {
|
||||
bool enabled = 1;
|
||||
}
|
||||
|
||||
message SetServerWhitelistEnforcedRequest {
|
||||
bool enforced = 1;
|
||||
}
|
||||
|
||||
message SetServerIdleTimeoutRequest {
|
||||
int32 timeout_minutes = 1;
|
||||
}
|
||||
|
||||
message SetServerDefaultGamemodeRequest {
|
||||
string gamemode = 1;
|
||||
}
|
||||
|
||||
message ServerTickInfoResponse {
|
||||
repeated double tps = 1;
|
||||
float tick_rate = 2;
|
||||
bool is_frozen = 3;
|
||||
bool is_sprinting = 4;
|
||||
bool is_stepping = 5;
|
||||
double average_tick_time = 6;
|
||||
int64 tick_count = 7;
|
||||
repeated int64 tick_times_nanos = 8;
|
||||
}
|
||||
|
||||
message SetServerTickRateRequest {
|
||||
float tick_rate = 1;
|
||||
bool frozen = 2;
|
||||
}
|
||||
|
||||
message ShutdownServerRequest {
|
||||
bool save = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message BroadcastMessageRequest {
|
||||
string message = 1;
|
||||
string permission = 2;
|
||||
}
|
||||
|
||||
message WhitelistEntryProto {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message GetWhitelistResponse {
|
||||
repeated WhitelistEntryProto players = 1;
|
||||
}
|
||||
|
||||
message SetWhitelistPlayerRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string name = 2;
|
||||
bool whitelisted = 3;
|
||||
}
|
||||
|
||||
message OperatorEntryProto {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string name = 2;
|
||||
int32 level = 3;
|
||||
bool bypasses_player_limit = 4;
|
||||
}
|
||||
|
||||
message GetOperatorsResponse {
|
||||
repeated OperatorEntryProto operators = 1;
|
||||
}
|
||||
|
||||
message SetOperatorRequest {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string name = 2;
|
||||
int32 level = 3;
|
||||
bool is_op = 4;
|
||||
}
|
||||
|
||||
message BanEntryProto {
|
||||
string target = 1;
|
||||
string source = 2;
|
||||
int64 created = 3;
|
||||
int64 expires = 4;
|
||||
string reason = 5;
|
||||
}
|
||||
|
||||
message GetBanListRequest {
|
||||
string ban_type = 1; // "NAME" or "IP" or "PROFILE"
|
||||
}
|
||||
|
||||
message GetBanListResponse {
|
||||
repeated BanEntryProto entries = 1;
|
||||
}
|
||||
|
||||
message SetBanEntryRequest {
|
||||
string ban_type = 1; // "NAME" or "IP" or "PROFILE"
|
||||
BanEntryProto entry = 2;
|
||||
bool remove = 3;
|
||||
}
|
||||
|
||||
message CreateWorldRequest {
|
||||
string name = 1;
|
||||
string dimension = 2; // "minecraft:overworld", "minecraft:the_nether", "minecraft:the_end"
|
||||
int64 seed = 3;
|
||||
}
|
||||
|
||||
message CreateWorldResponse {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string name = 2;
|
||||
bool success = 3;
|
||||
}
|
||||
|
||||
message UnloadWorldRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string world_name = 2;
|
||||
bool save = 3;
|
||||
}
|
||||
|
||||
message UnloadWorldResponse {
|
||||
bool success = 1;
|
||||
}
|
||||
@ -2,6 +2,7 @@ syntax = "proto3";
|
||||
|
||||
package patchbukkit.world;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "patchbukkit/common/types.proto";
|
||||
|
||||
option java_multiple_files = true;
|
||||
@ -38,6 +39,7 @@ message SpawnParticleRequest {
|
||||
double offset_y = 8;
|
||||
double offset_z = 9;
|
||||
double extra = 10;
|
||||
bool force = 11;
|
||||
}
|
||||
|
||||
message GetWorldsResponse {
|
||||
@ -75,6 +77,150 @@ message GetWorldInfoResponse {
|
||||
int32 max_height = 2;
|
||||
int32 height = 3;
|
||||
int64 seed = 4;
|
||||
string name = 5;
|
||||
string dimension = 6;
|
||||
int32 sea_level = 7;
|
||||
int32 logical_height = 8;
|
||||
string difficulty = 9;
|
||||
bool hardcore = 10;
|
||||
bool pvp = 11;
|
||||
int32 spawn_x = 12;
|
||||
int32 spawn_y = 13;
|
||||
int32 spawn_z = 14;
|
||||
float spawn_angle = 15;
|
||||
int64 time = 16;
|
||||
int64 full_time = 17;
|
||||
bool is_storm = 18;
|
||||
bool is_thundering = 19;
|
||||
int32 weather_duration = 20;
|
||||
int32 thunder_duration = 21;
|
||||
int32 clear_weather_duration = 22;
|
||||
}
|
||||
|
||||
message SetWorldTimeRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
int64 time = 2;
|
||||
int64 full_time = 3;
|
||||
}
|
||||
|
||||
message SetWorldWeatherRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
bool storm = 2;
|
||||
bool thundering = 3;
|
||||
int32 weather_duration = 4;
|
||||
int32 thunder_duration = 5;
|
||||
int32 clear_weather_duration = 6;
|
||||
}
|
||||
|
||||
message SetWorldSpawnRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
int32 x = 2;
|
||||
int32 y = 3;
|
||||
int32 z = 4;
|
||||
float angle = 5;
|
||||
}
|
||||
|
||||
message SetWorldDifficultyRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string difficulty = 2;
|
||||
}
|
||||
|
||||
message SetWorldPvpRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
bool pvp = 2;
|
||||
}
|
||||
|
||||
message SetWorldGameruleRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string rule = 2;
|
||||
string value = 3;
|
||||
}
|
||||
|
||||
message GetWorldGamerulesRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
}
|
||||
|
||||
message GetWorldGamerulesResponse {
|
||||
map<string, string> gamerules = 1;
|
||||
}
|
||||
|
||||
message EntitySummaryProto {
|
||||
patchbukkit.common.UUID uuid = 1;
|
||||
string entity_type = 2;
|
||||
double x = 3;
|
||||
double y = 4;
|
||||
double z = 5;
|
||||
float yaw = 6;
|
||||
float pitch = 7;
|
||||
bool is_player = 8;
|
||||
string custom_name = 9;
|
||||
}
|
||||
|
||||
message GetWorldEntitiesRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
}
|
||||
|
||||
message GetWorldEntitiesResponse {
|
||||
repeated EntitySummaryProto entities = 1;
|
||||
}
|
||||
|
||||
message SpawnWorldEntityRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string entity_type = 2;
|
||||
double x = 3;
|
||||
double y = 4;
|
||||
double z = 5;
|
||||
float yaw = 6;
|
||||
float pitch = 7;
|
||||
}
|
||||
|
||||
message SpawnWorldEntityResponse {
|
||||
patchbukkit.common.UUID entity_uuid = 1;
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
message CreateWorldExplosionRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
double x = 2;
|
||||
double y = 3;
|
||||
double z = 4;
|
||||
float power = 5;
|
||||
bool set_fire = 6;
|
||||
bool break_blocks = 7;
|
||||
}
|
||||
|
||||
message PlayWorldSoundRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
string sound = 2;
|
||||
string category = 3;
|
||||
double x = 4;
|
||||
double y = 5;
|
||||
double z = 6;
|
||||
float volume = 7;
|
||||
float pitch = 8;
|
||||
int64 seed = 9;
|
||||
}
|
||||
|
||||
message ChunkCoordProto {
|
||||
int32 x = 1;
|
||||
int32 z = 2;
|
||||
}
|
||||
|
||||
message SetChunkForceLoadedRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
int32 x = 2;
|
||||
int32 z = 3;
|
||||
bool forced = 4;
|
||||
}
|
||||
|
||||
message GetForceLoadedChunksRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
}
|
||||
|
||||
message GetForceLoadedChunksResponse {
|
||||
repeated ChunkCoordProto chunks = 1;
|
||||
}
|
||||
|
||||
message SaveWorldRequest {
|
||||
patchbukkit.common.UUID world_uuid = 1;
|
||||
}
|
||||
|
||||
229
rust/Cargo.lock
generated
229
rust/Cargo.lock
generated
@ -283,7 +283,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -461,7 +461,7 @@ checksum = "46d07918caa9eeaaf06b7873925c53a61daac173539b4f7715090745e44e4e69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -499,9 +499,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cap-fs-ext"
|
||||
version = "4.0.2"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78e5a3368ae89b7cb68186411452b4b9fac8b41be9c19bf3f47c2d2c8e36e6b"
|
||||
checksum = "56ff379b70af8e08307a8f65e7040c7301cb4a572538ade16b4984f0da77847f"
|
||||
dependencies = [
|
||||
"cap-primitives",
|
||||
"cap-std",
|
||||
@ -511,9 +511,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cap-primitives"
|
||||
version = "4.0.2"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdadbd7c002d3a484b35243669abdae85a0ebaded5a61117169dc3400f9a7ff0"
|
||||
checksum = "8b5f74729fd2f44701d1a8eb47e906cdb3ccd9ec0f02baad85a744b791940b18"
|
||||
dependencies = [
|
||||
"ambient-authority",
|
||||
"fs-set-times",
|
||||
@ -529,9 +529,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cap-std"
|
||||
version = "4.0.2"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7281235d6e96d3544ca18bba9049be92f4190f8d923e3caef1b5f66cfa752608"
|
||||
checksum = "c1ec78e242cfa2cfe276807ac2ecc00315a6c97786977414bcd1c3963b6c91b8"
|
||||
dependencies = [
|
||||
"cap-primitives",
|
||||
"io-extras",
|
||||
@ -550,9 +550,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.3"
|
||||
version = "1.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d"
|
||||
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@ -811,27 +811,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d552bd33b7a56dc70aeb1e1c960e51a218fa0db50f23873b500a310379450b2d"
|
||||
checksum = "16c273ba1bfc3a1cb27cb4f83df27134f3cb638a61f5ed79ab22cf86eb13da0d"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64-meta"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078e80e4c222279e3330f6aa1a256ca77ddf156d4453166a9f09defedc4594dd"
|
||||
checksum = "cbf8909326a466739e83ffe11e74c0c8c6b4bfa911b612aece915daa746cff58"
|
||||
dependencies = [
|
||||
"cranelift-srcgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "820ce15d4ad3562d613c31a67b6d0434d403e7091a68d1349903842f7d31737e"
|
||||
checksum = "3cb26b06b54d8b2f8cdf4d440a32fc3b3b91c71c162333a69a70a66fa265fc45"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
"wasmtime-internal-core",
|
||||
@ -839,9 +839,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bitset"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61bca563d4b86d285928d9e27f97f27039bb33a0fc524fa130d7d0c106bf8ab3"
|
||||
checksum = "7ce4e57dbb7f73d08011808a19787c3a03c3e7854b2a479ed0b788915fb671be"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -850,9 +850,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "709f4b7c0fb57d952658d5b5c07fbdc4149acd7b7f0de9678ae754b9c981949a"
|
||||
checksum = "74b0a8968f33d0bc13bc86fe70dd3947e93acc9f358ed9848e9988448972a9be"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-assembler-x64",
|
||||
@ -881,9 +881,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903dc8915af62aad1d9d0f39a5968d33fa80b9aa899ed6f56e47f40ca4512e1e"
|
||||
checksum = "f69e8e2fe9deb48ef7b8d0c61612f8c1e2277d0421c201e30a4c844a4ebac698"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
"cranelift-codegen-shared",
|
||||
@ -894,24 +894,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0522d74c227e49f3fd49ab055311486ae4f09083262b66705bed676952491469"
|
||||
checksum = "ad4db1e87a65e9c5a832e3ede160830d4e34df938ac38b5604819f8825687e73"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66560ea1c5cef72e170b18e46d263dba2d3169c9d39e8cafdab2173c6362cc1a"
|
||||
checksum = "9248cd37bb6ec460981f57ead368e32b1eca7a207ad50e3e9c7adc3b161f20e9"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ef5b17cc814d27e96b66a5b46da0e4ce2b8ac55a6d478048bb99d04b05526"
|
||||
checksum = "26b8bc91c0a3530d132acbf118965dabe9a084029eb0fa74b64760360dec3316"
|
||||
dependencies = [
|
||||
"cranelift-bitset",
|
||||
"serde",
|
||||
@ -921,9 +921,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a87e0aaa39dbf70693b348a221e45904111704ee8f9fef140498471005f9842d"
|
||||
checksum = "5086f2ebc084a98b387e522680f62ef65a512444d8382151e03088716d3a1714"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"hashbrown 0.17.1",
|
||||
@ -934,15 +934,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf79003ebfa1eed5e87f3b84446ad5236f540268289960e14f387dc9b28e40b7"
|
||||
checksum = "b6a658670f779afc2df083be201ebe54805f69b7b9ffa8dab04142b72ed751c9"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05bf4f235743c81e67ee4db617c5a4a0b65d58d3f0cfc575ee0f1a4e0cd58273"
|
||||
checksum = "16a41083b1fd953debd6f32d21fcda765b258f323ce907fdd6b4715f2769c478"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@ -951,9 +951,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-srcgen"
|
||||
version = "0.134.3"
|
||||
version = "0.134.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6977c2a71ab1e0d1e62f966b411a498aa04c4dce47d93d52f8a360a06058922"
|
||||
checksum = "244d9cd0759b0a3ccdd587cafb13434f9ea43b5c9d07701d277daf5cd0f7b7c1"
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
@ -991,9 +991,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -1382,7 +1382,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1446,9 +1446,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.17.0"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
|
||||
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
@ -1759,7 +1759,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1889,9 +1889,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.17"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f877e75f39e9827ec50a572dd592684ac28c029578726c85f1b2aa6ab807449"
|
||||
checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@ -2163,9 +2163,9 @@ checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92a7ed671a6aad807a8651a2e1782a6598fda9ce5185dd8158549e95a91c6428"
|
||||
checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_locale_core",
|
||||
@ -2550,9 +2550,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.33"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||
|
||||
[[package]]
|
||||
name = "lz4-java-wrc"
|
||||
@ -2834,7 +2834,7 @@ checksum = "e4e98dc3b890f6c23a0f9d3d491a2823d0dea0fa656302a13dd225fa924112a8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3024,9 +3024,11 @@ dependencies = [
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-types",
|
||||
"protoc-bin-vendored",
|
||||
"pumpkin",
|
||||
"pumpkin-api-macros",
|
||||
"pumpkin-config",
|
||||
"pumpkin-data",
|
||||
"pumpkin-protocol",
|
||||
"pumpkin-util",
|
||||
@ -3035,6 +3037,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde-saphyr",
|
||||
"serde_json",
|
||||
"time",
|
||||
"tokio",
|
||||
"toml 1.1.4+spec-1.1.0",
|
||||
"tracing",
|
||||
@ -3481,14 +3484,14 @@ checksum = "1c8d9ca532f185d5d4db7a7c9d51420b452168ea1c2b913953281bd6fe1fcbd0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulley-interpreter"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5c8c21ea032e4efbdf2d067dc45171779dbe0c8ecf20ef4a57efa7474f2b0a"
|
||||
checksum = "ed2bd641cb6a3ec5bffe60405568933163e0ea619da0943e9d2a417ceaa7fe82"
|
||||
dependencies = [
|
||||
"cranelift-bitset",
|
||||
"log",
|
||||
@ -3498,9 +3501,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pulley-macros"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f10925455d5dde962e3604eade797ba5488644c8ee14a44191e2f2b58980574"
|
||||
checksum = "d3fd4024d1e559eaf5579bc8ad84a2b5915f34b47acc13a06ffba7dac401b166"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3510,7 +3513,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"aes 0.9.2",
|
||||
"arc-swap",
|
||||
@ -3576,18 +3579,18 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-api-macros"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-codecs"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"tracing",
|
||||
@ -3596,7 +3599,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-config"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"pumpkin-util",
|
||||
"serde",
|
||||
@ -3608,7 +3611,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-data"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"crc-fast",
|
||||
"phf",
|
||||
@ -3621,7 +3624,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-inventory"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"pumpkin-data",
|
||||
"pumpkin-protocol",
|
||||
@ -3636,20 +3639,20 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-macros"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"pumpkin-data",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-nbt"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cesu8",
|
||||
@ -3663,7 +3666,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-protocol"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"aes 0.9.2",
|
||||
"async-compression",
|
||||
@ -3688,7 +3691,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-util"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"base64 0.23.1",
|
||||
"bytes",
|
||||
@ -3714,7 +3717,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-world"
|
||||
version = "0.1.0-dev+26.2-26.40"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#0d55aa54118956e459702394f2cf4609ab71db75"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"bitflags 2.13.1",
|
||||
@ -4004,7 +4007,7 @@ checksum = "1c25ef604ac7dd839d44d64648952ea23c97866f124ff671b0ed2cf3ad9bb06e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4426,9 +4429,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.14"
|
||||
version = "0.103.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a"
|
||||
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@ -4569,7 +4572,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4593,7 +4596,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4850,9 +4853,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4954,7 +4957,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5048,7 +5051,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5501,9 +5504,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c80ca6098e0d4d06886d91d7f2cc3cb6623eb583c4c0ab3c89cbfb6098c8586c"
|
||||
checksum = "4cdaf5b8af5713146e3a62d940c71e3eb2ad1ebacfa6b55f0c8509a5b4b87718"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"async-trait",
|
||||
@ -5545,9 +5548,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-environ"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134f9d136d29c76f6c1b4c9b468e97a2efc38c7d49fd188e39b64870b2fea701"
|
||||
checksum = "58793271eab7ec26bab99ca497131f8b37702e7dc39e2f2d18293e3e915b4964"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cpp_demangle",
|
||||
@ -5576,9 +5579,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-cache"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65db2eb1bfc5371a3b4107dbf539d0b93d05016fc29625b1648146b47db02071"
|
||||
checksum = "ede02ba77442cab88a2ddd5d16373e8bc450b55e05de8be039b024987a53d5a7"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"directories-next",
|
||||
@ -5596,9 +5599,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-component-macro"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bf7b91fed3fc34781d57f9c6654ea2513bf0a99f7b0b0523c00de1e6efebe1c"
|
||||
checksum = "c5bba4eff4804620bae04d7793308d97a0c5a8a97ea19e635452518f84560f84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"proc-macro2",
|
||||
@ -5611,15 +5614,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-component-util"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc8a678149885cae00289f806fbe74c7863084cf74cace0b8dc73602279400e1"
|
||||
checksum = "3d7032ff6b4d7a45e05be1cb32ec1756df5f2669f08296dbe2c61c3789dead2c"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-core"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0092c4b9d070ac5e278b6d0db10f5e71214190f0347ca57502b4692f796321"
|
||||
checksum = "f41d3b2cb9c3de7b696690af070d408b5e357011832f8b8bb7fbb315dbb620ed"
|
||||
dependencies = [
|
||||
"hashbrown 0.17.1",
|
||||
"libm",
|
||||
@ -5628,9 +5631,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-cranelift"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6851ebc9e03cab23d9821d2b2505d380bdfe38f35ccec945247b05274d85c98b"
|
||||
checksum = "1d5cda5b90247978dd2ba6ca4e309508da19e9244445671d2d0e6a34e5c3b847"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cranelift-codegen",
|
||||
@ -5655,9 +5658,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-fiber"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b26da6d5f60d4c438da70bba3553fe810a840533a64156be287dca2081c6991"
|
||||
checksum = "4d126366176553e8f304e8ac2078a4cc37134fe8f19d4d4695a09c5a2f577f10"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
@ -5670,9 +5673,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-jit-debug"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed621ba25d7bf78b7edd7b4749abbb27c2e5cdba836c9504a424ee74b6c23149"
|
||||
checksum = "c1d28ff131bc40e11d84bc3a9fa0d264506439ffbbc89f3562fbb529d1caa617"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"wasmtime-internal-versioned-export-macros",
|
||||
@ -5680,9 +5683,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-jit-icache-coherence"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5684ba160951baad06a725696f3c590e2fb0e8067c2aebee27bf7f9259058e85"
|
||||
checksum = "4a52de8b6afbfcd618073f592c1450cb661574e7061f3f4a44f1f7ec0c7f7909"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@ -5692,9 +5695,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-unwinder"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112eead527bffa8ff0646a11fb4339a9d52ddd1da2b9a6fce4aff84c815dd94f"
|
||||
checksum = "5524fbaaf3d2134dd6229164d7fc81e443cce06d1e0576524d5f4e86e747cb13"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cranelift-codegen",
|
||||
@ -5705,9 +5708,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-versioned-export-macros"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "153592e0bed824fc13c6696203fa1bd7bd20eb355316475e39a55f081ef80eca"
|
||||
checksum = "e93bb9ae112a80618510f938275a5d88637b656e7d0a021fc906f52206c708ad"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5716,9 +5719,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-wit-bindgen"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c456ad6e81e0f46abfeca43687d18ea15e289c395b262ea6e0023e2682e088be"
|
||||
checksum = "bfdbdd9d6fab1ecb67a7dc189e32c9e341444945fb709437bf8aab25d9a88459"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.13.1",
|
||||
@ -5729,9 +5732,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-wasi"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c1cf60cd6a565213af7074b4aad7bb5e110e3c6c6aae54425aa0500a0e15e86"
|
||||
checksum = "b373095a6dc8382da56882ad16d7ea16771dd6927dd480b1ce3fe7c4b816d2cf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bitflags 2.13.1",
|
||||
@ -5754,9 +5757,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-wasi-http"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a499879061ee9f724342d5f5009754b723ae53c7932161ee063a9fe19395e915"
|
||||
checksum = "372fc7845f26cd8f69bcbf6e4234fcc032f718480c7722fa20a28eb74d58998e"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
@ -5778,9 +5781,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-wasi-io"
|
||||
version = "47.0.3"
|
||||
version = "47.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb08e1d7755aaa467ce14080b7b01e33c914a920f6000696f1e42e40ea6387e"
|
||||
checksum = "51b3c9b39b1a1b3029f80e614623e182f165133dfaca8610f156450343f080a4"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
@ -6320,9 +6323,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.7"
|
||||
version = "0.11.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94b5c6b5976d66c1d703c4fd17d3f5e43c8cedaacf604961b171adc7130896d8"
|
||||
checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
@ -6331,13 +6334,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec-derive"
|
||||
version = "0.11.5"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f212a141d820099d57ffafb9569be9617a6f27d3dc881fbee8fb56642f917a9"
|
||||
checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
"syn 3.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@ -15,7 +15,9 @@ pumpkin = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master"
|
||||
pumpkin-data = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-data" }
|
||||
pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-protocol" }
|
||||
pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-util" }
|
||||
pumpkin-config = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-config" }
|
||||
pumpkin-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-api-macros" }
|
||||
prost-types = "0.14"
|
||||
|
||||
|
||||
tokio = "1"
|
||||
@ -27,7 +29,7 @@ walkdir = "2"
|
||||
zip = "8.6"
|
||||
|
||||
anyhow = "1.0"
|
||||
uuid = "1.24.1"
|
||||
uuid = "1.25.0"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
@ -35,6 +37,7 @@ serde-saphyr = "1.1.0"
|
||||
|
||||
rand = { git = "https://github.com/rust-random/rand"}
|
||||
prost = "0.14"
|
||||
time = "0.3"
|
||||
|
||||
toml = "1.1"
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use pumpkin::entity::EntityBase;
|
||||
|
||||
use crate::{
|
||||
@ -5,8 +7,16 @@ use crate::{
|
||||
proto::patchbukkit::{
|
||||
common::Uuid,
|
||||
entity::{
|
||||
DamageEntityRequest, EntityHealthResponse, SetEntityHealthRequest,
|
||||
SetEntityVelocityRequest, TeleportEntityRequest,
|
||||
DamageEntityRequest, EntityHealthResponse, GetCooldownRequest, GetCooldownResponse,
|
||||
GetExperienceResponse, GetFoodLevelResponse, GetPlayerPoseStateResponse,
|
||||
KickPlayerRequest, PlayerConnectionInfoResponse, SendActionBarRequest,
|
||||
SendBlockChangeRequest, SendGameEventRequest, SendResourcePackRequest,
|
||||
SendTitleRequest, SetCompassTargetRequest, SetCooldownRequest, SetDisplayNameRequest,
|
||||
SetEntityHealthRequest, SetEntityVelocityRequest, SetExhaustionRequest,
|
||||
SetExperienceRequest, SetFoodLevelRequest, SetOpRequest,
|
||||
SetPlayerListHeaderFooterRequest, SetPlayerListNameRequest, SetPlayerTimeRequest,
|
||||
SetPlayerWeatherRequest, SetRespawnPointRequest, SetSaturationRequest,
|
||||
SetSneakingRequest, SetSprintingRequest, StopSoundRequest, TeleportEntityRequest,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -171,3 +181,600 @@ pub fn ffi_native_bridge_is_op_impl(
|
||||
|
||||
Some(crate::proto::patchbukkit::entity::IsOpResponse { is_op })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_op_impl(request: SetOpRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let is_op = request.is_op;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let op_lvl = ctx.plugin_context.server.basic_config.op_permission_level;
|
||||
let lvl = if is_op {
|
||||
op_lvl
|
||||
} else {
|
||||
pumpkin_util::PermissionLvl::Zero
|
||||
};
|
||||
player.permission_lvl.store(lvl);
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_food_level_impl(request: Uuid) -> Option<GetFoodLevelResponse> {
|
||||
with_player(Some(&request), |player| {
|
||||
let food_level = i32::from(player.hunger_manager.level.load());
|
||||
let saturation = player.hunger_manager.saturation.load();
|
||||
let exhaustion = player.hunger_manager.get_exhaustion();
|
||||
GetFoodLevelResponse {
|
||||
food_level,
|
||||
saturation,
|
||||
exhaustion,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_food_level_impl(request: SetFoodLevelRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let food_level = request.food_level as u8;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
player.hunger_manager.set_level(food_level);
|
||||
player.send_health().await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_saturation_impl(request: SetSaturationRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let saturation = request.saturation;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
player.hunger_manager.set_saturation(saturation);
|
||||
player.send_health().await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_exhaustion_impl(request: SetExhaustionRequest) -> Option<()> {
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
player.hunger_manager.set_exhaustion(request.exhaustion);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_experience_impl(request: Uuid) -> Option<GetExperienceResponse> {
|
||||
with_player(Some(&request), |player| {
|
||||
let level = player.get_experience_level();
|
||||
let progress = player.get_experience_progress();
|
||||
let total_experience = player.get_total_experience();
|
||||
GetExperienceResponse {
|
||||
level,
|
||||
progress,
|
||||
total_experience,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_experience_impl(request: SetExperienceRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let level = request.level;
|
||||
let progress = request.progress;
|
||||
let total_experience = request.total_experience;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
player
|
||||
.set_experience(level, progress, total_experience)
|
||||
.await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_kick_player_impl(request: KickPlayerRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let msg = request.message;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
|
||||
player
|
||||
.kick(pumpkin::net::DisconnectReason::Kicked, text)
|
||||
.await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_send_title_impl(request: SendTitleRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let title = request.title;
|
||||
let subtitle = request.subtitle;
|
||||
let fade_in = request.fade_in;
|
||||
let stay = request.stay;
|
||||
let fade_out = request.fade_out;
|
||||
ctx.runtime.spawn(async move {
|
||||
if fade_in >= 0 && stay >= 0 && fade_out >= 0 {
|
||||
player.send_title_animation(fade_in, stay, fade_out).await;
|
||||
}
|
||||
if !title.is_empty() {
|
||||
let text = pumpkin_util::text::TextComponent::from_legacy_string(&title);
|
||||
player
|
||||
.show_title(&text, &pumpkin::entity::player::TitleMode::Title)
|
||||
.await;
|
||||
}
|
||||
if !subtitle.is_empty() {
|
||||
let text = pumpkin_util::text::TextComponent::from_legacy_string(&subtitle);
|
||||
player
|
||||
.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle)
|
||||
.await;
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_send_action_bar_impl(request: SendActionBarRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let msg = request.message;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
|
||||
player.send_system_message_raw(&text, true).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_reset_title_impl(request: Uuid) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(Some(&request), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let text = pumpkin_util::text::TextComponent::text("");
|
||||
player
|
||||
.show_title(&text, &pumpkin::entity::player::TitleMode::Title)
|
||||
.await;
|
||||
player
|
||||
.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle)
|
||||
.await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_display_name_impl(request: SetDisplayNameRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let name = request.display_name;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let comp = if name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
|
||||
};
|
||||
player.set_display_name(comp).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_player_list_name_impl(
|
||||
request: SetPlayerListNameRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let name = request.list_name;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let comp = if name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
|
||||
};
|
||||
player.set_tab_list_name(comp).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_player_list_header_footer_impl(
|
||||
request: SetPlayerListHeaderFooterRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let header = request.header;
|
||||
let footer = request.footer;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let h = pumpkin_util::text::TextComponent::from_legacy_string(&header);
|
||||
let f = pumpkin_util::text::TextComponent::from_legacy_string(&footer);
|
||||
player.set_tab_list_header_footer(h, f).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_player_pose_state_impl(
|
||||
request: Uuid,
|
||||
) -> Option<GetPlayerPoseStateResponse> {
|
||||
with_player(Some(&request), |player| {
|
||||
let is_sneaking = player
|
||||
.living_entity
|
||||
.entity
|
||||
.sneaking
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let is_sprinting = player
|
||||
.living_entity
|
||||
.entity
|
||||
.sprinting
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let is_gliding = player
|
||||
.living_entity
|
||||
.entity
|
||||
.fall_flying
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let is_swimming = player
|
||||
.living_entity
|
||||
.entity
|
||||
.swimming
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let is_sleeping = player.sleeping_since.load().is_some();
|
||||
GetPlayerPoseStateResponse {
|
||||
is_sneaking,
|
||||
is_sprinting,
|
||||
is_gliding,
|
||||
is_swimming,
|
||||
is_sleeping,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_sneaking_impl(request: SetSneakingRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let sneaking = request.sneaking;
|
||||
ctx.runtime.spawn(async move {
|
||||
player.living_entity.entity.set_sneaking(sneaking).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_sprinting_impl(request: SetSprintingRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let sprinting = request.sprinting;
|
||||
ctx.runtime.spawn(async move {
|
||||
player.living_entity.entity.set_sprinting(sprinting).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_player_time_impl(request: SetPlayerTimeRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let time = request.time;
|
||||
let relative = request.relative;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let packet = pumpkin_protocol::java::client::play::CUpdateTime::new(0, time, relative);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_reset_player_time_impl(request: Uuid) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(Some(&request), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let world_time = player.world().level_time.lock().await.time_of_day;
|
||||
let packet = pumpkin_protocol::java::client::play::CUpdateTime::new(
|
||||
world_time, world_time, true,
|
||||
);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_player_weather_impl(request: SetPlayerWeatherRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let weather = request.weather;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let event = if weather == 1 {
|
||||
pumpkin_protocol::java::client::play::GameEvent::BeginRaining
|
||||
} else {
|
||||
pumpkin_protocol::java::client::play::GameEvent::EndRaining
|
||||
};
|
||||
let packet = pumpkin_protocol::java::client::play::CGameEvent::new(event, 0.0);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_reset_player_weather_impl(request: Uuid) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(Some(&request), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let is_raining = player.world().is_raining().await;
|
||||
let event = if is_raining {
|
||||
pumpkin_protocol::java::client::play::GameEvent::BeginRaining
|
||||
} else {
|
||||
pumpkin_protocol::java::client::play::GameEvent::EndRaining
|
||||
};
|
||||
let packet = pumpkin_protocol::java::client::play::CGameEvent::new(event, 0.0);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_compass_target_impl(request: SetCompassTargetRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let pos = request.position?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let block_pos = pumpkin_util::math::position::BlockPos::new(
|
||||
pos.x as i32,
|
||||
pos.y as i32,
|
||||
pos.z as i32,
|
||||
);
|
||||
let dimension_name = player.world().dimension.minecraft_name.to_string();
|
||||
let packet = pumpkin_protocol::java::client::play::CPlayerSpawnPosition::new(
|
||||
block_pos,
|
||||
0.0,
|
||||
0.0,
|
||||
dimension_name,
|
||||
);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_compass_target_impl(
|
||||
request: Uuid,
|
||||
) -> Option<crate::proto::patchbukkit::common::Vec3> {
|
||||
with_player(Some(&request), |player| {
|
||||
let info = player.world().level_info.load();
|
||||
crate::proto::patchbukkit::common::Vec3 {
|
||||
x: info.spawn_x as f64,
|
||||
y: info.spawn_y as f64,
|
||||
z: info.spawn_z as f64,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_respawn_point_impl(request: SetRespawnPointRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let pos = request.position?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let block_pos =
|
||||
pumpkin_util::math::position::BlockPos::new(pos.x as i32, pos.y as i32, pos.z as i32);
|
||||
let yaw = request.yaw;
|
||||
let force = request.force;
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let dim = player.world().dimension.clone();
|
||||
player
|
||||
.set_respawn_point(dim, block_pos, yaw, 0.0, force)
|
||||
.await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_respawn_point_impl(
|
||||
request: Uuid,
|
||||
) -> Option<crate::proto::patchbukkit::common::Location> {
|
||||
with_player(Some(&request), |player| {
|
||||
let (pos, yaw, world_uuid) = if let Ok(guard) = player.respawn_point.try_lock() {
|
||||
match *guard {
|
||||
Some(ref pt) => (
|
||||
crate::proto::patchbukkit::common::Vec3 {
|
||||
x: pt.position.0.x as f64,
|
||||
y: pt.position.0.y as f64,
|
||||
z: pt.position.0.z as f64,
|
||||
},
|
||||
pt.yaw,
|
||||
player.world().uuid.to_string(),
|
||||
),
|
||||
None => {
|
||||
let info = player.world().level_info.load();
|
||||
(
|
||||
crate::proto::patchbukkit::common::Vec3 {
|
||||
x: info.spawn_x as f64,
|
||||
y: info.spawn_y as f64,
|
||||
z: info.spawn_z as f64,
|
||||
},
|
||||
info.spawn_yaw,
|
||||
player.world().uuid.to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let info = player.world().level_info.load();
|
||||
(
|
||||
crate::proto::patchbukkit::common::Vec3 {
|
||||
x: info.spawn_x as f64,
|
||||
y: info.spawn_y as f64,
|
||||
z: info.spawn_z as f64,
|
||||
},
|
||||
info.spawn_yaw,
|
||||
player.world().uuid.to_string(),
|
||||
)
|
||||
};
|
||||
crate::proto::patchbukkit::common::Location {
|
||||
position: Some(pos),
|
||||
yaw,
|
||||
pitch: 0.0,
|
||||
world: Some(crate::proto::patchbukkit::common::World {
|
||||
uuid: Some(crate::proto::patchbukkit::common::Uuid { value: world_uuid }),
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_stop_sound_impl(request: StopSoundRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let sound = if request.sound.is_empty() {
|
||||
None
|
||||
} else {
|
||||
pumpkin_util::resource_location::ResourceLocation::from_str(&request.sound).ok()
|
||||
};
|
||||
let category = if request.category.is_empty() {
|
||||
None
|
||||
} else {
|
||||
pumpkin_data::sound::SoundCategory::from_name(&request.category.to_lowercase())
|
||||
};
|
||||
ctx.runtime.spawn(async move {
|
||||
player.stop_sound(sound, category).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_send_block_change_impl(request: SendBlockChangeRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let pos = pumpkin_util::math::position::BlockPos::new(request.x, request.y, request.z);
|
||||
let state_str = request.block_state;
|
||||
let clean_key = state_str
|
||||
.split('[')
|
||||
.next()
|
||||
.unwrap_or(&state_str)
|
||||
.trim_start_matches("minecraft:");
|
||||
let state_id = if let Some(b) = pumpkin_data::Block::from_registry_key(clean_key) {
|
||||
b.default_state.id
|
||||
} else {
|
||||
pumpkin_data::BlockStateId::new_or_air(0)
|
||||
};
|
||||
ctx.runtime.spawn(async move {
|
||||
let packet = pumpkin_protocol::java::client::play::CBlockUpdate::new(
|
||||
pos,
|
||||
pumpkin_protocol::codec::var_int::VarInt(state_id.as_u16() as i32),
|
||||
);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_send_resource_pack_impl(request: SendResourcePackRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let url = request.url;
|
||||
let prompt = request.prompt;
|
||||
let required = request.required;
|
||||
ctx.runtime.spawn(async move {
|
||||
let prompt_comp = if prompt.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(pumpkin_util::text::TextComponent::from_legacy_string(
|
||||
&prompt,
|
||||
))
|
||||
};
|
||||
let id = uuid::Uuid::new_v4();
|
||||
let packet = pumpkin_protocol::java::client::play::CAddResourcePack::new(
|
||||
&id,
|
||||
&url,
|
||||
"",
|
||||
required,
|
||||
prompt_comp,
|
||||
);
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_player_connection_info_impl(
|
||||
request: Uuid,
|
||||
) -> Option<PlayerConnectionInfoResponse> {
|
||||
with_player(Some(&request), |player| {
|
||||
let ping = player.ping.load(std::sync::atomic::Ordering::Relaxed) as i32;
|
||||
let addr = player.client.address();
|
||||
PlayerConnectionInfoResponse {
|
||||
ping,
|
||||
address: addr.ip().to_string(),
|
||||
port: addr.port() as i32,
|
||||
client_brand: "vanilla".to_string(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_send_game_event_impl(request: SendGameEventRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let event_type = request.event_type as u8;
|
||||
let value = request.value;
|
||||
ctx.runtime.spawn(async move {
|
||||
let packet = pumpkin_protocol::java::client::play::CGameEvent {
|
||||
event: event_type,
|
||||
value,
|
||||
};
|
||||
player.send_client_packet(&packet).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_cooldown_impl(request: SetCooldownRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let player = player.clone();
|
||||
let group = request.item_group;
|
||||
let duration = request.duration_ticks;
|
||||
ctx.runtime.spawn(async move {
|
||||
player.start_cooldown(group, duration).await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_cooldown_impl(
|
||||
request: GetCooldownRequest,
|
||||
) -> Option<GetCooldownResponse> {
|
||||
with_player(request.uuid.as_ref(), |player| {
|
||||
let (cooldown, is_on_cooldown) = if let Ok(guard) = player.item_cooldowns.try_lock() {
|
||||
if let Some(cooldown) = guard.get(&request.item_group) {
|
||||
let current_tick = player
|
||||
.tick_counter
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let elapsed = current_tick - cooldown.start_tick;
|
||||
if elapsed < cooldown.duration {
|
||||
(1.0 - (elapsed as f32 / cooldown.duration as f32), true)
|
||||
} else {
|
||||
(0.0, false)
|
||||
}
|
||||
} else {
|
||||
(0.0, false)
|
||||
}
|
||||
} else {
|
||||
(0.0, false)
|
||||
};
|
||||
GetCooldownResponse {
|
||||
cooldown,
|
||||
is_on_cooldown,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_open_ender_chest_impl(request: Uuid) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(Some(&request), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
player.open_ender_chest().await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_update_inventory_impl(request: Uuid) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
with_player(Some(&request), |player| {
|
||||
let player = player.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
player
|
||||
.on_screen_handler_opened(player.player_screen_handler.clone())
|
||||
.await;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@ -47,6 +47,9 @@ pub use itemstack::*;
|
||||
pub mod command;
|
||||
pub use command::*;
|
||||
|
||||
pub mod server;
|
||||
pub use server::*;
|
||||
|
||||
static CALLBACK_CONTEXT: OnceLock<CallbackContext> = OnceLock::new();
|
||||
|
||||
struct CallbackContext {
|
||||
|
||||
452
rust/src/java/native_callbacks/server.rs
Normal file
452
rust/src/java/native_callbacks/server.rs
Normal file
@ -0,0 +1,452 @@
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::{
|
||||
java::native_callbacks::CALLBACK_CONTEXT,
|
||||
proto::patchbukkit::{
|
||||
common::{EmptyRequest, Uuid as ProtoUuid},
|
||||
server::{
|
||||
BanEntryProto, BroadcastMessageRequest, CreateWorldRequest, CreateWorldResponse,
|
||||
GetBanListRequest, GetBanListResponse, GetOperatorsResponse, GetWhitelistResponse,
|
||||
OperatorEntryProto, ServerInfoResponse, ServerTickInfoResponse, SetBanEntryRequest,
|
||||
SetOperatorRequest, SetServerDefaultGamemodeRequest, SetServerIdleTimeoutRequest,
|
||||
SetServerMaxPlayersRequest, SetServerMotdRequest, SetServerTickRateRequest,
|
||||
SetServerWhitelistEnforcedRequest, SetServerWhitelistRequest,
|
||||
SetWhitelistPlayerRequest, ShutdownServerRequest, UnloadWorldRequest,
|
||||
UnloadWorldResponse, WhitelistEntryProto,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pub fn ffi_native_bridge_get_server_info_impl(
|
||||
_request: EmptyRequest,
|
||||
) -> Option<ServerInfoResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = &ctx.plugin_context.server;
|
||||
let java_config = &server.advanced_config.networking.java;
|
||||
|
||||
let motd = java_config.motd.clone();
|
||||
let ip = java_config.address.ip().to_string();
|
||||
let port = java_config.address.port() as i32;
|
||||
let max_players = java_config.max_players as i32;
|
||||
let view_distance = java_config.view_distance.get() as i32;
|
||||
let simulation_distance = java_config.simulation_distance.get() as i32;
|
||||
let allow_flight = true;
|
||||
let allow_nether = server.basic_config.allow_nether;
|
||||
let allow_end = server.basic_config.allow_end;
|
||||
let online_mode = java_config.online_mode;
|
||||
let hardcore = server.basic_config.hardcore;
|
||||
let pvp = server.advanced_config.pvp.enabled;
|
||||
let has_whitelist = server.white_list.load(Ordering::Relaxed);
|
||||
let is_whitelist_enforced = server.basic_config.enforce_whitelist;
|
||||
let spawn_protection = 16;
|
||||
let idle_timeout = server.player_idle_timeout.load(Ordering::Relaxed);
|
||||
|
||||
let default_gamemode = if let Ok(gm) = server.defaultgamemode.try_lock() {
|
||||
format!("{:?}", gm.gamemode)
|
||||
} else {
|
||||
"SURVIVAL".to_string()
|
||||
};
|
||||
|
||||
Some(ServerInfoResponse {
|
||||
server_name: "Pumpkin".to_string(),
|
||||
version: "0.1.0".to_string(),
|
||||
bukkit_version: "1.21.4-R0.1-SNAPSHOT".to_string(),
|
||||
minecraft_version: "1.21.4".to_string(),
|
||||
motd,
|
||||
ip,
|
||||
port,
|
||||
max_players,
|
||||
view_distance,
|
||||
simulation_distance,
|
||||
allow_flight,
|
||||
allow_nether,
|
||||
allow_end,
|
||||
online_mode,
|
||||
hardcore,
|
||||
pvp,
|
||||
has_whitelist,
|
||||
is_whitelist_enforced,
|
||||
spawn_protection,
|
||||
default_gamemode,
|
||||
idle_timeout,
|
||||
generate_structures: true,
|
||||
max_world_size: 29999984,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_motd_impl(_request: SetServerMotdRequest) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_max_players_impl(
|
||||
_request: SetServerMaxPlayersRequest,
|
||||
) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_whitelist_impl(
|
||||
request: SetServerWhitelistRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
ctx.plugin_context
|
||||
.server
|
||||
.white_list
|
||||
.store(request.enabled, Ordering::Relaxed);
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_whitelist_enforced_impl(
|
||||
_request: SetServerWhitelistEnforcedRequest,
|
||||
) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_idle_timeout_impl(
|
||||
request: SetServerIdleTimeoutRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
ctx.plugin_context
|
||||
.server
|
||||
.player_idle_timeout
|
||||
.store(request.timeout_minutes, Ordering::Relaxed);
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_default_gamemode_impl(
|
||||
request: SetServerDefaultGamemodeRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
if let Ok(mut gm) = ctx.plugin_context.server.defaultgamemode.try_lock() {
|
||||
let mode = match request.gamemode.to_uppercase().as_str() {
|
||||
"CREATIVE" => pumpkin_util::GameMode::Creative,
|
||||
"ADVENTURE" => pumpkin_util::GameMode::Adventure,
|
||||
"SPECTATOR" => pumpkin_util::GameMode::Spectator,
|
||||
_ => pumpkin_util::GameMode::Survival,
|
||||
};
|
||||
gm.gamemode = mode;
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_server_tick_info_impl(
|
||||
_request: EmptyRequest,
|
||||
) -> Option<ServerTickInfoResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = &ctx.plugin_context.server;
|
||||
|
||||
let tick_rate = server.tick_rate_manager.tickrate();
|
||||
let is_frozen = server.tick_rate_manager.is_frozen();
|
||||
let is_sprinting = server.tick_rate_manager.is_sprinting();
|
||||
let is_stepping = server.tick_rate_manager.is_stepping_forward();
|
||||
let tick_count = server.tick_count.load(Ordering::Relaxed) as i64;
|
||||
let avg_nanos = server.aggregated_tick_times_nanos.load(Ordering::Relaxed);
|
||||
let average_tick_time = (avg_nanos as f64) / 1_000_000.0 / 100.0;
|
||||
|
||||
let mut tick_times_nanos = Vec::new();
|
||||
if let Ok(times) = server.tick_times_nanos.try_lock() {
|
||||
tick_times_nanos.extend_from_slice(&*times);
|
||||
} else {
|
||||
tick_times_nanos.resize(100, 50_000_000);
|
||||
}
|
||||
|
||||
let tps_val = (1_000.0 / (average_tick_time.max(50.0))).min(tick_rate as f64);
|
||||
let tps = vec![tps_val, tps_val, tps_val];
|
||||
|
||||
Some(ServerTickInfoResponse {
|
||||
tps,
|
||||
tick_rate,
|
||||
is_frozen,
|
||||
is_sprinting,
|
||||
is_stepping,
|
||||
average_tick_time,
|
||||
tick_count,
|
||||
tick_times_nanos,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_server_tick_rate_impl(
|
||||
request: SetServerTickRateRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = &ctx.plugin_context.server;
|
||||
if request.tick_rate > 0.0 {
|
||||
server
|
||||
.tick_rate_manager
|
||||
.set_tick_rate(server, request.tick_rate);
|
||||
}
|
||||
server.tick_rate_manager.set_frozen(server, request.frozen);
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_shutdown_server_impl(request: ShutdownServerRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
if request.save {
|
||||
let _ = server.save_all().await;
|
||||
}
|
||||
server.shutdown().await;
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_broadcast_message_impl(request: BroadcastMessageRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
let text = TextComponent::text(request.message);
|
||||
let sender = TextComponent::text("Server");
|
||||
ctx.runtime.spawn(async move {
|
||||
server.broadcast_message(&text, &sender, 0, None).await;
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_whitelist_impl(
|
||||
_request: EmptyRequest,
|
||||
) -> Option<GetWhitelistResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let mut players = Vec::new();
|
||||
if let Ok(config) = ctx.plugin_context.server.data.whitelist_config.try_read() {
|
||||
for entry in &config.whitelist {
|
||||
players.push(WhitelistEntryProto {
|
||||
uuid: Some(ProtoUuid {
|
||||
value: entry.uuid.to_string(),
|
||||
}),
|
||||
name: entry.name.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Some(GetWhitelistResponse { players })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_whitelist_player_impl(
|
||||
request: SetWhitelistPlayerRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.uuid.as_ref()?.value;
|
||||
let target_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
let target_name = request.name;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
|
||||
ctx.runtime.spawn(async move {
|
||||
let mut config = server.data.whitelist_config.write().await;
|
||||
if request.whitelisted {
|
||||
if !config.whitelist.iter().any(|e| e.uuid == target_uuid) {
|
||||
config
|
||||
.whitelist
|
||||
.push(pumpkin_config::whitelist::WhitelistEntry {
|
||||
uuid: target_uuid,
|
||||
name: target_name,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
config.whitelist.retain(|e| e.uuid != target_uuid);
|
||||
}
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_operators_impl(
|
||||
_request: EmptyRequest,
|
||||
) -> Option<GetOperatorsResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let mut operators = Vec::new();
|
||||
if let Ok(config) = ctx.plugin_context.server.data.operator_config.try_read() {
|
||||
for op in &config.ops {
|
||||
operators.push(OperatorEntryProto {
|
||||
uuid: Some(ProtoUuid {
|
||||
value: op.uuid.to_string(),
|
||||
}),
|
||||
name: op.name.clone(),
|
||||
level: op.level as i32,
|
||||
bypasses_player_limit: op.bypasses_player_limit,
|
||||
});
|
||||
}
|
||||
}
|
||||
Some(GetOperatorsResponse { operators })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_operator_impl(request: SetOperatorRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.uuid.as_ref()?.value;
|
||||
let target_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
let target_name = request.name;
|
||||
let level = match request.level {
|
||||
1 => pumpkin_util::permission::PermissionLvl::One,
|
||||
2 => pumpkin_util::permission::PermissionLvl::Two,
|
||||
3 => pumpkin_util::permission::PermissionLvl::Three,
|
||||
_ => pumpkin_util::permission::PermissionLvl::Four,
|
||||
};
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
|
||||
ctx.runtime.spawn(async move {
|
||||
let mut config = server.data.operator_config.write().await;
|
||||
if request.is_op {
|
||||
if let Some(op) = config.ops.iter_mut().find(|e| e.uuid == target_uuid) {
|
||||
op.level = level;
|
||||
} else {
|
||||
config.ops.push(pumpkin_config::op::Op {
|
||||
uuid: target_uuid,
|
||||
name: target_name,
|
||||
level,
|
||||
bypasses_player_limit: false,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
config.ops.retain(|e| e.uuid != target_uuid);
|
||||
}
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_ban_list_impl(
|
||||
request: GetBanListRequest,
|
||||
) -> Option<GetBanListResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let mut entries = Vec::new();
|
||||
|
||||
if request.ban_type == "IP" {
|
||||
if let Ok(list) = ctx.plugin_context.server.data.banned_ip_list.try_read() {
|
||||
for entry in &list.banned_ips {
|
||||
let created = entry.created.unix_timestamp();
|
||||
let expires = entry.expires.map(|e| e.unix_timestamp()).unwrap_or(0);
|
||||
entries.push(BanEntryProto {
|
||||
target: entry.ip.to_string(),
|
||||
source: entry.source.clone(),
|
||||
created,
|
||||
expires,
|
||||
reason: entry.reason.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Ok(list) = ctx.plugin_context.server.data.banned_player_list.try_read() {
|
||||
for entry in &list.banned_players {
|
||||
let created = entry.created.unix_timestamp();
|
||||
let expires = entry.expires.map(|e| e.unix_timestamp()).unwrap_or(0);
|
||||
entries.push(BanEntryProto {
|
||||
target: entry.name.clone(),
|
||||
source: entry.source.clone(),
|
||||
created,
|
||||
expires,
|
||||
reason: entry.reason.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(GetBanListResponse { entries })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_ban_entry_impl(request: SetBanEntryRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
|
||||
ctx.runtime.spawn(async move {
|
||||
if let Some(entry) = request.entry {
|
||||
if request.ban_type == "IP" {
|
||||
if let Ok(ip) = entry.target.parse::<std::net::IpAddr>() {
|
||||
let mut list = server.data.banned_ip_list.write().await;
|
||||
if request.remove {
|
||||
list.banned_ips.retain(|e| e.ip != ip);
|
||||
} else {
|
||||
list.banned_ips.retain(|e| e.ip != ip);
|
||||
let expires = if entry.expires > 0 {
|
||||
time::OffsetDateTime::from_unix_timestamp(entry.expires).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
list.banned_ips
|
||||
.push(pumpkin::data::banlist_serializer::BannedIpEntry {
|
||||
ip,
|
||||
created: time::OffsetDateTime::now_utc(),
|
||||
source: entry.source,
|
||||
expires,
|
||||
reason: entry.reason,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut list = server.data.banned_player_list.write().await;
|
||||
let target_name = entry.target.clone();
|
||||
if request.remove {
|
||||
list.banned_players
|
||||
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
|
||||
} else {
|
||||
list.banned_players
|
||||
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
|
||||
let expires = if entry.expires > 0 {
|
||||
time::OffsetDateTime::from_unix_timestamp(entry.expires).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
list.banned_players.push(
|
||||
pumpkin::data::banlist_serializer::BannedPlayerEntry {
|
||||
uuid: uuid::Uuid::nil(),
|
||||
name: target_name,
|
||||
created: time::OffsetDateTime::now_utc(),
|
||||
source: entry.source,
|
||||
expires,
|
||||
reason: entry.reason,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_create_world_impl(
|
||||
request: CreateWorldRequest,
|
||||
) -> Option<CreateWorldResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
let name = request.name;
|
||||
let dim = match request.dimension.as_str() {
|
||||
"minecraft:the_nether" => pumpkin_data::dimension::Dimension::THE_NETHER,
|
||||
"minecraft:the_end" => pumpkin_data::dimension::Dimension::THE_END,
|
||||
_ => pumpkin_data::dimension::Dimension::OVERWORLD,
|
||||
};
|
||||
|
||||
let world_name = name.clone();
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
ctx.runtime.spawn(async move {
|
||||
let world = server.create_world(world_name, dim).await;
|
||||
let _ = tx.send(world.uuid);
|
||||
});
|
||||
|
||||
let world_uuid = rx.blocking_recv().ok()?;
|
||||
Some(CreateWorldResponse {
|
||||
world_uuid: Some(ProtoUuid {
|
||||
value: world_uuid.to_string(),
|
||||
}),
|
||||
name,
|
||||
success: true,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_unload_world_impl(
|
||||
request: UnloadWorldRequest,
|
||||
) -> Option<UnloadWorldResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
let name = request.world_name;
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
ctx.runtime.spawn(async move {
|
||||
let res = server.unload_world(&name).await;
|
||||
let _ = tx.send(res.is_ok());
|
||||
});
|
||||
let success = rx.blocking_recv().unwrap_or(false);
|
||||
Some(UnloadWorldResponse { success })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_save_all_worlds_impl(_request: EmptyRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let server = ctx.plugin_context.server.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let _ = server.save_all().await;
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
@ -1,7 +1,22 @@
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
java::native_callbacks::CALLBACK_CONTEXT,
|
||||
proto::patchbukkit::world::{
|
||||
GetBlockDataRequest, GetBlockDataResponse, SetBlockDataRequest, SpawnParticleRequest,
|
||||
proto::patchbukkit::{
|
||||
common::{EmptyRequest, Uuid as ProtoUuid},
|
||||
world::{
|
||||
ChunkCoordProto, CreateWorldExplosionRequest, EntitySummaryProto, GetBlockDataRequest,
|
||||
GetBlockDataResponse, GetForceLoadedChunksRequest, GetForceLoadedChunksResponse,
|
||||
GetWorldBorderRequest, GetWorldEntitiesRequest, GetWorldEntitiesResponse,
|
||||
GetWorldGamerulesRequest, GetWorldGamerulesResponse, GetWorldInfoRequest,
|
||||
GetWorldInfoResponse, GetWorldsResponse, PlayWorldSoundRequest, SaveWorldRequest,
|
||||
SetBlockDataRequest, SetChunkForceLoadedRequest, SetWorldBorderRequest,
|
||||
SetWorldDifficultyRequest, SetWorldGameruleRequest, SetWorldPvpRequest,
|
||||
SetWorldSpawnRequest, SetWorldTimeRequest, SetWorldWeatherRequest,
|
||||
SpawnParticleRequest, SpawnWorldEntityRequest, SpawnWorldEntityResponse,
|
||||
WorldBorderData,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -29,8 +44,6 @@ pub fn ffi_native_bridge_get_block_data_impl(
|
||||
format!("minecraft:{key}")
|
||||
};
|
||||
|
||||
// Include block-state properties (facing, half, waterlogged, ...) so the Java side can
|
||||
// hand plugins a faithful BlockData string instead of the bare block name.
|
||||
if let Some(props) = block.properties(state_id) {
|
||||
let props = props.to_props();
|
||||
if !props.is_empty() {
|
||||
@ -71,8 +84,6 @@ pub fn ffi_native_bridge_set_block_data_impl(request: SetBlockDataRequest) -> Op
|
||||
.trim_start_matches("minecraft:");
|
||||
|
||||
let state_id = if let Some(b) = pumpkin_data::Block::from_registry_key(clean_key) {
|
||||
// Apply the block-state properties from the "[k=v,...]" suffix instead of silently
|
||||
// placing the default state (stairs used to lose their facing, doors their half, ...).
|
||||
match block_state_str.split_once('[') {
|
||||
Some((_, props_str)) => {
|
||||
let props: Vec<(&str, &str)> = props_str
|
||||
@ -93,15 +104,6 @@ pub fn ffi_native_bridge_set_block_data_impl(request: SetBlockDataRequest) -> Op
|
||||
pumpkin_data::BlockStateId::new_or_air(0)
|
||||
};
|
||||
|
||||
// Bukkit's contract is synchronous, ordered world mutation: Block#setType must be
|
||||
// observable by a read on the next line, and two writes to the same position must land
|
||||
// in call order. The previous fire-and-forget `runtime.spawn` guaranteed neither. This
|
||||
// mirrors the blocking pattern the read callbacks in this module already use.
|
||||
//
|
||||
// Re-entrancy note: none of the events set_block_state can fire (BlockPhysicsEvent via
|
||||
// NOTIFY_NEIGHBORS) are bridged to the JVM today. If one ever is, its blocking handler
|
||||
// would post to the JvmWorker thread that is currently blocked inside this call — keep
|
||||
// that in mind before wiring block-physics events.
|
||||
let flags = if request.apply_physics {
|
||||
pumpkin::world::BlockFlags::NOTIFY_ALL
|
||||
} else {
|
||||
@ -120,24 +122,22 @@ pub fn ffi_native_bridge_spawn_particle_impl(_request: SpawnParticleRequest) ->
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_worlds_impl(
|
||||
_request: crate::proto::patchbukkit::common::EmptyRequest,
|
||||
) -> Option<crate::proto::patchbukkit::world::GetWorldsResponse> {
|
||||
pub fn ffi_native_bridge_get_worlds_impl(_request: EmptyRequest) -> Option<GetWorldsResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world_uuids = worlds
|
||||
.iter()
|
||||
.map(|w| crate::proto::patchbukkit::common::Uuid {
|
||||
.map(|w| ProtoUuid {
|
||||
value: w.uuid.to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(crate::proto::patchbukkit::world::GetWorldsResponse { world_uuids })
|
||||
Some(GetWorldsResponse { world_uuids })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_world_border_impl(
|
||||
request: crate::proto::patchbukkit::world::GetWorldBorderRequest,
|
||||
) -> Option<crate::proto::patchbukkit::world::WorldBorderData> {
|
||||
request: GetWorldBorderRequest,
|
||||
) -> Option<WorldBorderData> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
@ -151,7 +151,7 @@ pub fn ffi_native_bridge_get_world_border_impl(
|
||||
|
||||
let wb = world.worldborder.try_lock().ok()?;
|
||||
|
||||
Some(crate::proto::patchbukkit::world::WorldBorderData {
|
||||
Some(WorldBorderData {
|
||||
center_x: wb.center_x,
|
||||
center_z: wb.center_z,
|
||||
size: wb.old_diameter,
|
||||
@ -165,9 +165,7 @@ pub fn ffi_native_bridge_get_world_border_impl(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_border_impl(
|
||||
request: crate::proto::patchbukkit::world::SetWorldBorderRequest,
|
||||
) -> Option<()> {
|
||||
pub fn ffi_native_bridge_set_world_border_impl(request: SetWorldBorderRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
@ -198,8 +196,8 @@ pub fn ffi_native_bridge_set_world_border_impl(
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_world_info_impl(
|
||||
request: crate::proto::patchbukkit::world::GetWorldInfoRequest,
|
||||
) -> Option<crate::proto::patchbukkit::world::GetWorldInfoResponse> {
|
||||
request: GetWorldInfoRequest,
|
||||
) -> Option<GetWorldInfoResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
@ -214,11 +212,411 @@ pub fn ffi_native_bridge_get_world_info_impl(
|
||||
let min_height = world.dimension.min_y;
|
||||
let height = world.dimension.height;
|
||||
let max_height = min_height + height;
|
||||
let logical_height = world.dimension.logical_height;
|
||||
let sea_level = world.sea_level;
|
||||
let dimension = world.dimension.minecraft_name.to_string();
|
||||
|
||||
Some(crate::proto::patchbukkit::world::GetWorldInfoResponse {
|
||||
let level_data = world.level_info.load();
|
||||
let name = level_data.level_name.clone();
|
||||
let seed = 0i64;
|
||||
let difficulty = format!("{:?}", level_data.difficulty);
|
||||
let hardcore = false;
|
||||
let spawn_x = level_data.spawn_x;
|
||||
let spawn_y = level_data.spawn_y;
|
||||
let spawn_z = level_data.spawn_z;
|
||||
let spawn_angle = level_data.spawn_yaw;
|
||||
|
||||
let (time, full_time) = if let Ok(lt) = world.level_time.try_lock() {
|
||||
(lt.time_of_day, lt.world_age)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
let (is_storm, is_thundering, weather_duration, thunder_duration, clear_weather_duration) =
|
||||
if let Ok(w) = world.weather.try_lock() {
|
||||
(
|
||||
w.raining,
|
||||
w.thundering,
|
||||
w.rain_time,
|
||||
w.thunder_time,
|
||||
w.clear_weather_time,
|
||||
)
|
||||
} else {
|
||||
(false, false, 0, 0, 0)
|
||||
};
|
||||
|
||||
let pvp = ctx.plugin_context.server.advanced_config.pvp.enabled;
|
||||
|
||||
Some(GetWorldInfoResponse {
|
||||
min_height,
|
||||
max_height,
|
||||
height,
|
||||
seed: 0,
|
||||
seed,
|
||||
name,
|
||||
dimension,
|
||||
sea_level,
|
||||
logical_height,
|
||||
difficulty,
|
||||
hardcore,
|
||||
pvp,
|
||||
spawn_x,
|
||||
spawn_y,
|
||||
spawn_z,
|
||||
spawn_angle,
|
||||
time,
|
||||
full_time,
|
||||
is_storm,
|
||||
is_thundering,
|
||||
weather_duration,
|
||||
thunder_duration,
|
||||
clear_weather_duration,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_time_impl(request: SetWorldTimeRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
if let Ok(mut lt) = world.level_time.try_lock() {
|
||||
if request.time >= 0 {
|
||||
lt.time_of_day = request.time;
|
||||
}
|
||||
if request.full_time >= 0 {
|
||||
lt.world_age = request.full_time;
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_weather_impl(request: SetWorldWeatherRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
if let Ok(mut w) = world.weather.try_lock() {
|
||||
w.raining = request.storm;
|
||||
w.thundering = request.thundering;
|
||||
if request.weather_duration > 0 {
|
||||
w.rain_time = request.weather_duration;
|
||||
}
|
||||
if request.thunder_duration > 0 {
|
||||
w.thunder_time = request.thunder_duration;
|
||||
}
|
||||
if request.clear_weather_duration > 0 {
|
||||
w.clear_weather_time = request.clear_weather_duration;
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_spawn_impl(request: SetWorldSpawnRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let mut level_data = (**world.level_info.load()).clone();
|
||||
level_data.spawn_x = request.x;
|
||||
level_data.spawn_y = request.y;
|
||||
level_data.spawn_z = request.z;
|
||||
level_data.spawn_yaw = request.angle;
|
||||
world.level_info.store(Arc::new(level_data));
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_difficulty_impl(
|
||||
request: SetWorldDifficultyRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let diff = match request.difficulty.to_uppercase().as_str() {
|
||||
"PEACEFUL" => pumpkin_util::Difficulty::Peaceful,
|
||||
"EASY" => pumpkin_util::Difficulty::Easy,
|
||||
"HARD" => pumpkin_util::Difficulty::Hard,
|
||||
_ => pumpkin_util::Difficulty::Normal,
|
||||
};
|
||||
|
||||
let mut level_data = (**world.level_info.load()).clone();
|
||||
level_data.difficulty = diff;
|
||||
world.level_info.store(Arc::new(level_data));
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_pvp_impl(_request: SetWorldPvpRequest) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_world_gamerule_impl(_request: SetWorldGameruleRequest) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_world_gamerules_impl(
|
||||
_request: GetWorldGamerulesRequest,
|
||||
) -> Option<GetWorldGamerulesResponse> {
|
||||
let mut gamerules = std::collections::HashMap::new();
|
||||
gamerules.insert("doDaylightCycle".to_string(), "true".to_string());
|
||||
gamerules.insert("doMobSpawning".to_string(), "true".to_string());
|
||||
gamerules.insert("doFireTick".to_string(), "true".to_string());
|
||||
gamerules.insert("keepInventory".to_string(), "false".to_string());
|
||||
gamerules.insert("mobGriefing".to_string(), "true".to_string());
|
||||
gamerules.insert("doWeatherCycle".to_string(), "true".to_string());
|
||||
Some(GetWorldGamerulesResponse { gamerules })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_world_entities_impl(
|
||||
request: GetWorldEntitiesRequest,
|
||||
) -> Option<GetWorldEntitiesResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let mut entities = Vec::new();
|
||||
for p in world.players.load().iter() {
|
||||
let pos = p.living_entity.entity.pos.load();
|
||||
entities.push(EntitySummaryProto {
|
||||
uuid: Some(ProtoUuid {
|
||||
value: p.gameprofile.id.to_string(),
|
||||
}),
|
||||
entity_type: "PLAYER".to_string(),
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
z: pos.z,
|
||||
yaw: p.living_entity.entity.yaw.load(),
|
||||
pitch: p.living_entity.entity.pitch.load(),
|
||||
is_player: true,
|
||||
custom_name: p.gameprofile.name.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
for e in world.entities.load().iter() {
|
||||
let base = e.get_entity();
|
||||
let pos = base.pos.load();
|
||||
entities.push(EntitySummaryProto {
|
||||
uuid: Some(ProtoUuid {
|
||||
value: base.entity_uuid.to_string(),
|
||||
}),
|
||||
entity_type: format!("{:?}", base.entity_type),
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
z: pos.z,
|
||||
yaw: base.yaw.load(),
|
||||
pitch: base.pitch.load(),
|
||||
is_player: false,
|
||||
custom_name: String::new(),
|
||||
});
|
||||
}
|
||||
|
||||
Some(GetWorldEntitiesResponse { entities })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_spawn_world_entity_impl(
|
||||
request: SpawnWorldEntityRequest,
|
||||
) -> Option<SpawnWorldEntityResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let new_uuid = uuid::Uuid::new_v4();
|
||||
let pos = Vector3::new(request.x, request.y, request.z);
|
||||
|
||||
let w = world.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let entity_type: &'static pumpkin_data::entity::EntityType =
|
||||
match request.entity_type.to_uppercase().as_str() {
|
||||
"LIGHTNING_BOLT" | "LIGHTNING" => &pumpkin_data::entity::EntityType::LIGHTNING_BOLT,
|
||||
"ITEM" | "DROPPED_ITEM" => &pumpkin_data::entity::EntityType::ITEM,
|
||||
"ZOMBIE" => &pumpkin_data::entity::EntityType::ZOMBIE,
|
||||
"SKELETON" => &pumpkin_data::entity::EntityType::SKELETON,
|
||||
"CREEPER" => &pumpkin_data::entity::EntityType::CREEPER,
|
||||
"COW" => &pumpkin_data::entity::EntityType::COW,
|
||||
"PIG" => &pumpkin_data::entity::EntityType::PIG,
|
||||
"SHEEP" => &pumpkin_data::entity::EntityType::SHEEP,
|
||||
_ => &pumpkin_data::entity::EntityType::PIG,
|
||||
};
|
||||
let entity = pumpkin::entity::r#type::from_type(entity_type, pos, &w, new_uuid);
|
||||
w.spawn_entity(entity).await;
|
||||
});
|
||||
|
||||
Some(SpawnWorldEntityResponse {
|
||||
entity_uuid: Some(ProtoUuid {
|
||||
value: new_uuid.to_string(),
|
||||
}),
|
||||
success: true,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_create_world_explosion_impl(
|
||||
request: CreateWorldExplosionRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let pos = Vector3::new(request.x, request.y, request.z);
|
||||
let power = request.power;
|
||||
let interaction = if request.break_blocks {
|
||||
pumpkin::world::ExplosionInteraction::Block
|
||||
} else {
|
||||
pumpkin::world::ExplosionInteraction::None
|
||||
};
|
||||
|
||||
let w = world.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
w.explode(pos, power, interaction).await;
|
||||
});
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_play_world_sound_impl(request: PlayWorldSoundRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let pos = Vector3::new(request.x, request.y, request.z);
|
||||
let sound_name = request.sound;
|
||||
if let Some(sound) = pumpkin_data::sound::Sound::from_name(&sound_name) {
|
||||
world.play_sound_raw(
|
||||
sound as u16,
|
||||
pumpkin_data::sound::SoundCategory::Master,
|
||||
&pos,
|
||||
request.volume,
|
||||
request.pitch,
|
||||
);
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_set_chunk_force_loaded_impl(
|
||||
request: SetChunkForceLoadedRequest,
|
||||
) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let coord = pumpkin_util::math::vector2::Vector2::new(request.x, request.z);
|
||||
if let Ok(mut forced) = world.forced_chunks.lock() {
|
||||
if request.forced {
|
||||
forced.insert(coord);
|
||||
} else {
|
||||
forced.remove(&coord);
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_get_force_loaded_chunks_impl(
|
||||
request: GetForceLoadedChunksRequest,
|
||||
) -> Option<GetForceLoadedChunksResponse> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let mut chunks = Vec::new();
|
||||
if let Ok(forced) = world.forced_chunks.lock() {
|
||||
for coord in forced.iter() {
|
||||
chunks.push(ChunkCoordProto {
|
||||
x: coord.x,
|
||||
z: coord.y,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Some(GetForceLoadedChunksResponse { chunks })
|
||||
}
|
||||
|
||||
pub fn ffi_native_bridge_save_world_impl(request: SaveWorldRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let uuid_str = &request.world_uuid.as_ref()?.value;
|
||||
let world_uuid = uuid::Uuid::parse_str(uuid_str).ok()?;
|
||||
|
||||
let worlds = ctx.plugin_context.server.worlds.load_full();
|
||||
let world = worlds
|
||||
.iter()
|
||||
.find(|w| w.uuid == world_uuid)
|
||||
.cloned()
|
||||
.or_else(|| worlds.first().cloned())?;
|
||||
|
||||
let w = world.clone();
|
||||
ctx.runtime.spawn(async move {
|
||||
let _ = w.save().await;
|
||||
});
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
@ -50,6 +50,10 @@ pub mod patchbukkit {
|
||||
pub mod command {
|
||||
include!(concat!(env!("OUT_DIR"), "/patchbukkit.command.rs"));
|
||||
}
|
||||
|
||||
pub mod server {
|
||||
include!(concat!(env!("OUT_DIR"), "/patchbukkit.server.rs"));
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/ffi_init.rs"));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user