mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 18:09:27 +00:00
feat(resource-pack): 实现资源包推送功能
This commit is contained in:
@@ -2,10 +2,13 @@ package net.momirealms.craftengine.bukkit.pack;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.event.AsyncResourcePackGenerateEvent;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.util.ResourcePackUtils;
|
||||
import net.momirealms.craftengine.core.pack.AbstractPackManager;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -18,6 +21,7 @@ import org.bukkit.event.player.PlayerResourcePackStatusEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
@@ -53,6 +57,7 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
if (Config.sendPackOnJoin()) {
|
||||
this.modifyServerSettings();
|
||||
}
|
||||
@@ -64,9 +69,9 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
Object properties = Reflections.field$DedicatedServerSettings$properties.get(settings);
|
||||
Object info;
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance(new UUID(0, 0), "", "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance(new UUID(0, 0), "https://127.0.0.1:65536", "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
} else {
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance(new UUID(0, 0), "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance("https://127.0.0.1:65536", "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
}
|
||||
Reflections.field$DedicatedServerProperties$serverResourcePackInfo.set(properties, Optional.of(info));
|
||||
} catch (Exception e) {
|
||||
@@ -102,4 +107,23 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
// generate pack
|
||||
super.generateResourcePack();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onAsyncResourcePackGenerate(AsyncResourcePackGenerateEvent event) {
|
||||
Bukkit.getOnlinePlayers().forEach(p -> {
|
||||
BukkitServerPlayer user = this.plugin.adapt(p);
|
||||
CompletableFuture<ResourcePackDownloadData> future = resourcePackHost().requestResourcePackDownloadLink(user.uuid());
|
||||
if (future.isDone()) {
|
||||
try {
|
||||
ResourcePackDownloadData data = future.get();
|
||||
user.sendPacket(ResourcePackUtils.createPacket(
|
||||
data.uuid(), data.url(), data.sha1()
|
||||
), true);
|
||||
user.setCurrentResourcePackUUID(data.uuid());
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to send resource pack to player " + p.getName(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.EDIT_BOOK, Reflections.clazz$ServerboundEditBookPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CUSTOM_PAYLOAD, Reflections.clazz$ServerboundCustomPayloadPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_PUSH, Reflections.clazz$ClientboundResourcePackPushPacket);
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_21_3() ? PacketConsumers.LEVEL_PARTICLE_1_21_3 : (VersionHelper.isVersionNewerThan1_20_5() ? PacketConsumers.LEVEL_PARTICLE_1_20_5 : PacketConsumers.LEVEL_PARTICLE_1_20), this.packetIds.clientboundLevelParticlesPacket());
|
||||
|
||||
@@ -21,11 +21,14 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
@@ -44,6 +47,8 @@ import org.bukkit.util.RayTraceResult;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class PacketConsumers {
|
||||
@@ -51,6 +56,7 @@ public class PacketConsumers {
|
||||
private static int[] mappingsMOD;
|
||||
private static IntIdentityList BLOCK_LIST;
|
||||
private static IntIdentityList BIOME_LIST;
|
||||
private static final UUID EMPTY_UUID = new UUID(0, 0);
|
||||
|
||||
public static void init(Map<Integer, Integer> map, int registrySize) {
|
||||
mappings = new int[registrySize];
|
||||
@@ -1158,7 +1164,6 @@ public class PacketConsumers {
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HELLO_C2S = (user, event, packet) -> {
|
||||
try {
|
||||
if (!user.isOnline()) return;
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
String name = (String) Reflections.field$ServerboundHelloPacket$name.get(packet);
|
||||
UUID uuid = (UUID) Reflections.field$ServerboundHelloPacket$uuid.get(packet);
|
||||
@@ -2096,4 +2101,45 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetScorePacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_PUSH = (user, event, packet) -> {
|
||||
try {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_2()) return;
|
||||
if (user.handleResourcePackPush()) return;
|
||||
event.setCancelled(true);
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
user.receivePacket(Reflections.constructor$ServerboundResourcePackPacket.newInstance(
|
||||
EMPTY_UUID, Reflections.instance$ServerboundResourcePackPacket$Action$ACCEPTED
|
||||
));
|
||||
} else {
|
||||
user.receivePacket(Reflections.constructor$ServerboundResourcePackPacket.newInstance(
|
||||
Reflections.instance$ServerboundResourcePackPacket$Action$ACCEPTED
|
||||
));
|
||||
}
|
||||
|
||||
SchedulerTask timeoutTask = CraftEngine.instance().scheduler().asyncLater(() -> {
|
||||
Thread.currentThread().interrupt();
|
||||
}, 27, TimeUnit.SECONDS);
|
||||
|
||||
Object newPacket = packet;
|
||||
out : try {
|
||||
ResourcePackHost host = CraftEngine.instance().packManager().resourcePackHost();
|
||||
CompletableFuture<ResourcePackDownloadData> future = host.requestResourcePackDownloadLink(user.uuid());
|
||||
if (!future.isDone()) break out;
|
||||
ResourcePackDownloadData data = future.get();
|
||||
newPacket = ResourcePackUtils.createPacket(data.uuid(), data.url(), data.sha1());
|
||||
user.setCurrentResourcePackUUID(data.uuid());
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to get resource pack url", e);
|
||||
} finally {
|
||||
timeoutTask.cancel();
|
||||
}
|
||||
|
||||
if (!user.nettyChannel().isActive()) return;
|
||||
user.setHandleResourcePackPush(true);
|
||||
user.nettyChannel().writeAndFlush(newPacket);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundResourcePackPushPacket", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ public class BukkitServerPlayer extends Player {
|
||||
private Key lastUsedRecipe = null;
|
||||
// has fabric client mod or not
|
||||
private boolean hasClientMod = false;
|
||||
// resource pack
|
||||
private boolean handleResourcePackPush = false;
|
||||
// cache if player can break blocks
|
||||
private boolean clientSideCanBreak = true;
|
||||
// prevent AFK players from consuming too much CPU resource on predicting
|
||||
@@ -754,6 +756,14 @@ public class BukkitServerPlayer extends Player {
|
||||
return this.resourcePackUUID;
|
||||
}
|
||||
|
||||
public boolean handleResourcePackPush() {
|
||||
return this.handleResourcePackPush;
|
||||
}
|
||||
|
||||
public void setHandleResourcePackPush(boolean handleResourcePackPush) {
|
||||
this.handleResourcePackPush = handleResourcePackPush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView() {
|
||||
this.entityTypeView.clear();
|
||||
|
||||
@@ -6440,8 +6440,8 @@ public class Reflections {
|
||||
|
||||
public static final Class<?> clazz$ServerboundHelloPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundHelloPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketLoginInStart")
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.login.ServerboundHelloPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.login.PacketLoginInStart")
|
||||
)
|
||||
);
|
||||
|
||||
@@ -6456,4 +6456,56 @@ public class Reflections {
|
||||
clazz$ServerboundHelloPacket, UUID.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundResourcePackPushPacket$id =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundResourcePackPushPacket, UUID.class, 0
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundResourcePackPushPacket$prompt = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundResourcePackPushPacket,
|
||||
VersionHelper.isVersionNewerThan1_20_5() ? Optional.class : clazz$Component,
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundResourcePackPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundResourcePackPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInResourcePackStatus")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundResourcePackPacket$Action = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundResourcePackPacket$Action"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundResourcePackPacket$a"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundResourcePackPacket$Action"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInResourcePackStatus$EnumResourcePackStatus")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ServerboundResourcePackPacket$Action$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$ServerboundResourcePackPacket$Action, clazz$ServerboundResourcePackPacket$Action.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$ServerboundResourcePackPacket$Action$ACCEPTED;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$ServerboundResourcePackPacket$Action$values.invoke(null);
|
||||
instance$ServerboundResourcePackPacket$Action$ACCEPTED = values[3];
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Constructor<?> constructor$ServerboundResourcePackPacket = requireNonNull(
|
||||
field$ClientboundResourcePackPushPacket$id != null
|
||||
? ReflectionUtils.getConstructor(clazz$ServerboundResourcePackPacket, UUID.class, clazz$ServerboundResourcePackPacket$Action)
|
||||
: ReflectionUtils.getConstructor(clazz$ServerboundResourcePackPacket, clazz$ServerboundResourcePackPacket$Action)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ResourcePackUtils {
|
||||
|
||||
public static Object createPacket(UUID uuid, String url, String hash) throws InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
return Reflections.constructor$ClientboundResourcePackPushPacket.newInstance(uuid, url, hash, Config.kickOnDeclined(), Optional.of(ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt())));
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
return Reflections.constructor$ClientboundResourcePackPushPacket.newInstance(uuid, url, hash, Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
} else {
|
||||
return Reflections.constructor$ClientboundResourcePackPushPacket.newInstance(url, hash, Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import net.momirealms.craftengine.core.font.BitmapImage;
|
||||
import net.momirealms.craftengine.core.font.Font;
|
||||
import net.momirealms.craftengine.core.item.EquipmentData;
|
||||
import net.momirealms.craftengine.core.pack.conflict.resolution.ConditionalResolution;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
||||
import net.momirealms.craftengine.core.pack.host.impl.SelfHost;
|
||||
import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration;
|
||||
import net.momirealms.craftengine.core.pack.model.ItemModel;
|
||||
import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel;
|
||||
@@ -65,6 +67,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
private final Map<String, ConfigSectionParser> sectionParsers = new HashMap<>();
|
||||
private final TreeMap<ConfigSectionParser, List<CachedConfig>> cachedConfigs = new TreeMap<>();
|
||||
protected BiConsumer<Path, Path> zipGenerator;
|
||||
protected ResourcePackHost resourcePackHost;
|
||||
|
||||
public AbstractPackManager(CraftEngine plugin, BiConsumer<Path, Path> eventDispatcher) {
|
||||
this.plugin = plugin;
|
||||
@@ -143,6 +146,15 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.resourcePackHost = new SelfHost(Config.hostIP(), Config.hostPort());
|
||||
if (Files.exists(resourcePackPath())) {
|
||||
this.resourcePackHost.upload(resourcePackPath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePackHost resourcePackHost() {
|
||||
return this.resourcePackHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,6 +524,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
long end = System.currentTimeMillis();
|
||||
this.plugin.logger().info("Finished generating resource pack in " + (end - start) + "ms");
|
||||
|
||||
this.resourcePackHost.upload(zipFile);
|
||||
this.eventDispatcher.accept(generatedPackPath, zipFile);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.pack;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,4 +34,6 @@ public interface PackManager extends Manageable {
|
||||
void generateResourcePack();
|
||||
|
||||
Path resourcePackPath();
|
||||
|
||||
ResourcePackHost resourcePackHost();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public class SelfHost implements ResourcePackHost {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ResourcePackDownloadData> requestResourcePackDownloadLink(UUID player) {
|
||||
return CompletableFuture.completedFuture(SelfHostHttpServer.instance().generateOneTimeUrl(player));
|
||||
return CompletableFuture.completedFuture(SelfHostHttpServer.instance().generateOneTimeUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,6 @@ import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -23,7 +22,9 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class SelfHostHttpServer {
|
||||
@@ -37,7 +38,7 @@ public class SelfHostHttpServer {
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
private final ExecutorService threadPool = Executors.newFixedThreadPool(1);
|
||||
private ExecutorService threadPool;
|
||||
private HttpServer server;
|
||||
|
||||
private final AtomicLong totalRequests = new AtomicLong();
|
||||
@@ -57,7 +58,7 @@ public class SelfHostHttpServer {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ResourcePackDownloadData generateOneTimeUrl(UUID player) {
|
||||
public ResourcePackDownloadData generateOneTimeUrl() {
|
||||
String token = UUID.randomUUID().toString();
|
||||
this.oneTimePackUrls.put(token, true);
|
||||
return new ResourcePackDownloadData(
|
||||
@@ -102,11 +103,15 @@ public class SelfHostHttpServer {
|
||||
}
|
||||
|
||||
public void updatePort(int port) {
|
||||
if (port <= 0 || port > 65535) {
|
||||
throw new IllegalArgumentException("Invalid port number: " + port);
|
||||
}
|
||||
if (port == this.port) return;
|
||||
if (server != null) disable();
|
||||
this.port = port;
|
||||
try {
|
||||
server = HttpServer.create(new InetSocketAddress("::", port), 0);
|
||||
threadPool = Executors.newFixedThreadPool(1);
|
||||
server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
server.createContext("/download", new ResourcePackHandler());
|
||||
server.createContext("/metrics", this::handleMetrics);
|
||||
server.setExecutor(threadPool);
|
||||
@@ -134,7 +139,9 @@ public class SelfHostHttpServer {
|
||||
if (server != null) {
|
||||
server.stop(0);
|
||||
server = null;
|
||||
threadPool.shutdownNow();
|
||||
if (threadPool != null) {
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,6 @@ public class SimpleExternalHost implements ResourcePackHost {
|
||||
return CompletableFuture.completedFuture(this.downloadData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePackDownloadData getResourcePackDownloadLink(UUID player) {
|
||||
return this.downloadData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> upload(Path resourcePackPath) {
|
||||
return CompletableFuture.completedFuture(true);
|
||||
|
||||
@@ -55,4 +55,8 @@ public interface NetWorkUser {
|
||||
|
||||
@Nullable
|
||||
UUID currentResourcePackUUID();
|
||||
|
||||
boolean handleResourcePackPush();
|
||||
|
||||
void setHandleResourcePackPush(boolean handleFinishConfiguration);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user