9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 01:49:16 +00:00

Updated Upstream (Leaves)

Upstream has released updates that appear to apply and compile correctly

Leaves Changes:
LeavesMC/Leaves@9c12d296 Update Paper
LeavesMC/Leaves@357a03df Fix LitematicaEasyPlaceProtocol * 2
LeavesMC/Leaves@46cccfc3 Fix #609 & #612, add maxNbt in litematics, improve protocol invoker (#611)
LeavesMC/Leaves@c245ee67 Remove a useless patch (#614)
LeavesMC/Leaves@eb3d87b8 feat: finish MOVE_ITEM_NEW_PACKET, fix rei protocol packet transformer (#615)
LeavesMC/Leaves@6a2b9ee6 Fix long config (#617)
LeavesMC/Leaves@2c9f83c7 fix: fix a bug in redstoneShearsWrench (#621)
LeavesMC/Leaves@9cba2ea2 Fix #622 (#624)
LeavesMC/Leaves@1242a2a6 Update Paper and Leavesclip
LeavesMC/Leaves@cadc1269 Fix replay api and add null check in botlist (#627)
LeavesMC/Leaves@e68eb3fe Chat command max length
LeavesMC/Leaves@4c4712d3 Fix endermite spawn (#632)
LeavesMC/Leaves@c581f131 Some fix, and clear
This commit is contained in:
Dreeam
2025-07-31 14:21:26 +08:00
parent 9ba16f36ed
commit 6686e0f507
6 changed files with 69 additions and 58 deletions

View File

@@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -65,6 +66,8 @@ public abstract class AbstractInvokerHolder<T> {
} else {
return invoker.invoke(owner, args);
}
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getCause());
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@@ -26,14 +26,17 @@ import net.minecraft.network.protocol.configuration.ClientboundUpdateEnabledFeat
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import net.minecraft.network.protocol.game.ClientboundSystemChatPacket;
import net.minecraft.network.protocol.game.ClientboundTrackedWaypointPacket;
import net.minecraft.network.protocol.login.ClientboundLoginFinishedPacket;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.packs.repository.KnownPack;
import net.minecraft.tags.TagNetworkSerialization;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.flag.FeatureFlags;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,23 +44,26 @@ import org.leavesmc.leaves.LeavesLogger;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class Recorder extends Connection {
public static final Executor saveService = Executors.newVirtualThreadPerTaskExecutor();
public static final LeavesLogger LOGGER = LeavesLogger.LOGGER;
public final ExecutorService saveService = Executors.newSingleThreadExecutor();
private final ReplayFile replayFile;
private final ServerPhotographer photographer;
private final RecorderOption recorderOption;
private final RecordMetaData metaData;
private final AtomicBoolean isSaving = new AtomicBoolean(false);
private boolean stopped = false;
private boolean paused = false;
@@ -68,7 +74,6 @@ public class Recorder extends Connection {
private long timeShift = 0;
private boolean isSaved;
private boolean isSaving;
private ConnectionProtocol state = ConnectionProtocol.LOGIN;
public Recorder(ServerPhotographer photographer, RecorderOption recorderOption, File replayFile) throws IOException {
@@ -77,7 +82,7 @@ public class Recorder extends Connection {
this.photographer = photographer;
this.recorderOption = recorderOption;
this.metaData = new RecordMetaData();
this.replayFile = new ReplayFile(replayFile);
this.replayFile = new ReplayFile(replayFile, saveService);
this.channel = new LocalChannel();
}
@@ -93,6 +98,8 @@ public class Recorder extends Connection {
this.savePacket(new ClientboundLoginFinishedPacket(photographer.getGameProfile()), ConnectionProtocol.LOGIN);
this.startConfiguration();
savePacket(ClientboundPlayerPositionPacket.of(photographer.getId(), PositionMoveRotation.of(photographer), Collections.emptySet()));
if (recorderOption.forceWeather != null) {
setWeather(recorderOption.forceWeather);
}
@@ -170,40 +177,46 @@ public class Recorder extends Connection {
@Override
public void send(@NotNull Packet<?> packet, @Nullable ChannelFutureListener callbacks, boolean flush) {
if (!stopped) {
if (packet instanceof BundlePacket<?> packet1) {
if (stopped) {
return;
}
switch (packet) {
case BundlePacket<?> packet1 -> {
packet1.subPackets().forEach(subPacket -> send(subPacket, null));
return;
}
if (packet instanceof ClientboundAddEntityPacket packet1) {
case ClientboundAddEntityPacket packet1 -> {
if (packet1.getType() == EntityType.PLAYER) {
metaData.players.add(packet1.getUUID());
saveMetadata();
}
}
if (packet instanceof ClientboundDisconnectPacket) {
case ClientboundDisconnectPacket ignored -> {
return;
}
if (recorderOption.forceDayTime != -1 && packet instanceof ClientboundSetTimePacket packet1) {
packet = new ClientboundSetTimePacket(packet1.dayTime(), recorderOption.forceDayTime, false);
}
if (recorderOption.forceWeather != null && packet instanceof ClientboundGameEventPacket packet1) {
ClientboundGameEventPacket.Type type = packet1.getEvent();
if (type == ClientboundGameEventPacket.START_RAINING || type == ClientboundGameEventPacket.STOP_RAINING || type == ClientboundGameEventPacket.RAIN_LEVEL_CHANGE || type == ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE) {
return;
}
}
if (recorderOption.ignoreChat && (packet instanceof ClientboundSystemChatPacket || packet instanceof ClientboundPlayerChatPacket)) {
case ClientboundTrackedWaypointPacket ignored -> {
return;
}
savePacket(packet);
default -> {
}
}
if (recorderOption.forceDayTime != -1 && packet instanceof ClientboundSetTimePacket packet1) {
packet = new ClientboundSetTimePacket(packet1.dayTime(), recorderOption.forceDayTime, false);
}
if (recorderOption.forceWeather != null && packet instanceof ClientboundGameEventPacket packet1) {
ClientboundGameEventPacket.Type type = packet1.getEvent();
if (type == ClientboundGameEventPacket.START_RAINING || type == ClientboundGameEventPacket.STOP_RAINING || type == ClientboundGameEventPacket.RAIN_LEVEL_CHANGE || type == ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE) {
return;
}
}
if (recorderOption.ignoreChat && (packet instanceof ClientboundSystemChatPacket || packet instanceof ClientboundPlayerChatPacket)) {
return;
}
savePacket(packet);
}
private void saveMetadata() {
@@ -235,36 +248,23 @@ public class Recorder extends Connection {
}
public CompletableFuture<Void> saveRecording(File dest, boolean save) {
isSaved = true;
if (!isSaving) {
isSaving = true;
metaData.duration = (int) lastPacket;
return CompletableFuture.runAsync(() -> {
saveMetadata();
boolean interrupted = false;
try {
if (save) {
replayFile.closeAndSave(dest);
} else {
replayFile.closeNotSave();
}
} catch (IOException e) {
e.printStackTrace();
throw new CompletionException(e);
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}, runnable -> {
final Thread thread = new Thread(runnable, "Recording file save thread");
thread.start();
});
} else {
if (!isSaving.compareAndSet(false, true)) {
LOGGER.warning("saveRecording() called twice");
return CompletableFuture.supplyAsync(() -> {
throw new IllegalStateException("saveRecording() called twice");
});
return CompletableFuture.failedFuture(new IllegalStateException("saveRecording() called twice"));
}
isSaved = true;
metaData.duration = (int) lastPacket;
return CompletableFuture.runAsync(() -> {
try {
replayFile.saveMetaData(metaData);
if (save) {
replayFile.closeAndSave(dest);
} else {
replayFile.closeNotSave();
}
} catch (IOException e) {
throw new CompletionException(e);
}
}, saveService);
}
}

View File

@@ -34,12 +34,12 @@ import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.leavesmc.leaves.replay.Recorder.LOGGER;
import static org.leavesmc.leaves.replay.Recorder.saveService;
public class ReplayFile {
@@ -59,8 +59,10 @@ public class ReplayFile {
private final File metaFile;
private final Map<ConnectionProtocol, ProtocolInfo<?>> protocols;
private final ExecutorService saveService;
public ReplayFile(@NotNull File name) throws IOException {
public ReplayFile(@NotNull File name, ExecutorService saveService) throws IOException {
this.saveService = saveService;
this.tmpDir = new File(name.getParentFile(), name.getName() + ".tmp");
if (tmpDir.exists()) {
if (!ReplayFile.deleteDir(tmpDir)) {

View File

@@ -55,6 +55,8 @@ public class ServerPhotographer extends ServerPlayer {
GameProfile profile = new GameProfile(UUID.randomUUID(), state.id);
ServerPhotographer photographer = new ServerPhotographer(server, world, profile);
photographer.absSnapTo(state.loc.x(), state.loc.y(), state.loc.z(), state.loc.getYaw(), state.loc.getPitch());
photographer.recorder = new Recorder(photographer, state.option, new File("replay", state.id));
photographer.saveFile = new File("replay", state.id + ".mcpr");
photographer.createState = state;
@@ -146,6 +148,10 @@ public class ServerPhotographer extends ServerPlayer {
this.followPlayer = followPlayer;
}
public ServerPlayer getFollowPlayer() {
return followPlayer;
}
public void setSaveFile(File saveFile) {
this.saveFile = saveFile;
}