Skip to content

[Savestates] Fix world resourcepacks not correctly applying after savestate #255

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/java/com/minecrafttas/tasmod/TASmod.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.minecrafttas.tasmod.playback.metadata.builtin.StartpositionMetadataExtension;
import com.minecrafttas.tasmod.registries.TASmodPackets;
import com.minecrafttas.tasmod.savestates.SavestateHandlerServer;
import com.minecrafttas.tasmod.savestates.handlers.SavestateResourcePackHandler;
import com.minecrafttas.tasmod.savestates.storage.builtin.SavestateMotionStorage;
import com.minecrafttas.tasmod.tickratechanger.TickrateChangerServer;
import com.minecrafttas.tasmod.ticksync.TickSyncServer;
Expand Down Expand Up @@ -119,6 +120,9 @@ public void onInitialize() {
SavestateMotionStorage motionStorage = new SavestateMotionStorage();
PacketHandlerRegistry.register(motionStorage);
EventListenerRegistry.register(motionStorage);
SavestateResourcePackHandler resourcepackHandler = new SavestateResourcePackHandler();
PacketHandlerRegistry.register(resourcepackHandler);
EventListenerRegistry.register(resourcepackHandler);
PacketHandlerRegistry.register(playUntil);
EventListenerRegistry.register(playUntil);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.minecrafttas.tasmod.mixin.savestates;

import java.util.concurrent.locks.ReentrantLock;

import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

import com.google.common.util.concurrent.ListenableFuture;
import com.minecrafttas.tasmod.util.Ducks.ResourcePackRepositoryDuck;

import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.ResourcePackRepository;

@Mixin(ResourcePackRepository.class)
public class MixinResourcePackRepository implements ResourcePackRepositoryDuck {

@Shadow
@Final
private ReentrantLock lock;
@Shadow
private ListenableFuture<Object> downloadingPacks;
@Shadow
private IResourcePack serverResourcePack;

@Override
public void clearServerResourcePackBlocking() {
this.lock.lock();

try {
if (this.downloadingPacks != null) {
this.downloadingPacks.cancel(true);
}

this.downloadingPacks = null;
if (this.serverResourcePack != null) {
this.serverResourcePack = null;
Minecraft.getMinecraft().refreshResources();
}
} finally {
this.lock.unlock();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ public enum TASmodPackets implements PacketID {
Minecraft mc = Minecraft.getMinecraft();
((ScoreboardDuck) mc.world.getScoreboard()).clearScoreboard();
}),
/**
* <p>Clears the resourcepack on the client side
* <p>SIDE: Client<br>
* ARGS: none
*/
SAVESTATE_CLEAR_RESOURCEPACK,
/**
* <p>Notifies the client to clear all inputs from the input buffer in {@link PlaybackControllerClient}
* <p>SIDE: Both<br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.minecrafttas.tasmod.savestates.exceptions.SavestateException;
import com.minecrafttas.tasmod.savestates.gui.GuiSavestateSavingScreen;
import com.minecrafttas.tasmod.util.Ducks.ChunkProviderDuck;
import com.minecrafttas.tasmod.util.Ducks.ResourcePackRepositoryDuck;
import com.minecrafttas.tasmod.util.Ducks.SubtickDuck;
import com.minecrafttas.tasmod.util.Ducks.WorldClientDuck;
import com.minecrafttas.tasmod.util.LoggerMarkers;
Expand Down Expand Up @@ -151,6 +152,8 @@ public static void loadstate(String nameOfSavestate) throws Exception {
return;
}

((ResourcePackRepositoryDuck) Minecraft.getMinecraft().getResourcePackRepository()).clearServerResourcePackBlocking();

PlaybackControllerClient controller = TASmodClient.controller;

TASstate state = controller.getState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.minecrafttas.tasmod.savestates.files.SavestateDataFile.DataValues;
import com.minecrafttas.tasmod.savestates.files.SavestateTrackerFile;
import com.minecrafttas.tasmod.savestates.handlers.SavestatePlayerHandler;
import com.minecrafttas.tasmod.savestates.handlers.SavestateResourcePackHandler;
import com.minecrafttas.tasmod.savestates.handlers.SavestateWorldHandler;
import com.minecrafttas.tasmod.util.LoggerMarkers;
import com.minecrafttas.tasmod.util.Scheduler.Task;
Expand Down Expand Up @@ -386,6 +387,9 @@ public void loadState(int savestateIndex, boolean tickrate0, boolean changeIndex
// Reenable level saving
worldHandler.enableLevelSaving();

// Refresh server resourcepacks on the client
SavestateResourcePackHandler.refreshServerResourcepack(server);

// Incrementing info file
SavestateTrackerFile tracker = new SavestateTrackerFile(savestateDirectory.resolve(worldname + "-info.txt"));
tracker.increaseLoadstateCount();
Expand All @@ -398,6 +402,8 @@ public void loadState(int savestateIndex, boolean tickrate0, boolean changeIndex

worldHandler.sendChunksToClient();

playerHandler.updateServerResourcePack();

try {
TASmod.server.sendToAll(new TASmodBufferBuilder(CLEAR_SCREEN));
} catch (Exception e) {
Expand Down Expand Up @@ -753,9 +759,9 @@ private int legacyIndexFile(Path savestateDat) {
public PacketID[] getAcceptedPacketIDs() {
return new TASmodPackets[] {
//@formatter:off
TASmodPackets.SAVESTATE_SAVE,
TASmodPackets.SAVESTATE_LOAD,
TASmodPackets.SAVESTATE_SCREEN,
TASmodPackets.SAVESTATE_SAVE,
TASmodPackets.SAVESTATE_LOAD,
TASmodPackets.SAVESTATE_SCREEN,
TASmodPackets.SAVESTATE_UNLOAD_CHUNKS
//@formatter:on
};
Expand All @@ -770,7 +776,7 @@ public void onServerPacket(PacketID id, ByteBuffer buf, String username) throws

switch (packet) {
case SAVESTATE_SAVE:
Integer index = TASmodBufferBuilder.readInt(buf);
int index = TASmodBufferBuilder.readInt(buf);

Task savestateTask = () -> {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,13 @@ public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws
break;
}
}

public void updateServerResourcePack() {
if (!this.server.getResourcePackUrl().isEmpty()) {
List<EntityPlayerMP> players = server.getPlayerList().getPlayers();
for (EntityPlayerMP player : players) {
player.loadResourcePack(this.server.getResourcePackUrl(), this.server.getResourcePackHash());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.minecrafttas.tasmod.savestates.handlers;

import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import com.minecrafttas.mctcommon.networking.Client.Side;
import com.minecrafttas.mctcommon.networking.exception.PacketNotImplementedException;
import com.minecrafttas.mctcommon.networking.exception.WrongSideException;
import com.minecrafttas.mctcommon.networking.interfaces.ClientPacketHandler;
import com.minecrafttas.mctcommon.networking.interfaces.PacketID;
import com.minecrafttas.mctcommon.networking.interfaces.ServerPacketHandler;
import com.minecrafttas.tasmod.TASmod;
import com.minecrafttas.tasmod.TASmodClient;
import com.minecrafttas.tasmod.events.EventSavestate;
import com.minecrafttas.tasmod.networking.TASmodBufferBuilder;
import com.minecrafttas.tasmod.registries.TASmodPackets;
import com.minecrafttas.tasmod.savestates.exceptions.SavestateException;
import com.minecrafttas.tasmod.util.Ducks.ResourcePackRepositoryDuck;
import com.minecrafttas.tasmod.util.LoggerMarkers;

import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;

public class SavestateResourcePackHandler implements EventSavestate.EventServerLoadstate, ServerPacketHandler, ClientPacketHandler {

private CompletableFuture<String> future;

@Override
public void onServerLoadstate(MinecraftServer server, int index, Path target, Path current) {
if (server.getResourcePackUrl().isEmpty() || server.isDedicatedServer())
return;

String serverOwnerName = server.getServerOwner();

try {
TASmod.server.sendTo(serverOwnerName, new TASmodBufferBuilder(TASmodPackets.SAVESTATE_CLEAR_RESOURCEPACK));
} catch (Exception e) {
TASmod.LOGGER.catching(e);
}
future = new CompletableFuture<>();

String playername = null;
try {
playername = future.get(2L, TimeUnit.MINUTES);
} catch (TimeoutException e) {
throw new SavestateException(e, "Clearing resourcepacks %s timed out!", serverOwnerName);
} catch (ExecutionException | InterruptedException e) {
throw new SavestateException(e, "Clearing resourcepacks %s", serverOwnerName);
}

TASmod.LOGGER.debug(LoggerMarkers.Savestate, "Cleared resourcepack for player {}", playername);
}

@Override
public PacketID[] getAcceptedPacketIDs() {
return new TASmodPackets[] { TASmodPackets.SAVESTATE_CLEAR_RESOURCEPACK };
}

@Override
public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws PacketNotImplementedException, WrongSideException, Exception {
TASmodPackets packetId = (TASmodPackets) id;

Minecraft mc = Minecraft.getMinecraft();
switch (packetId) {
case SAVESTATE_CLEAR_RESOURCEPACK:
mc.addScheduledTask(() -> {
ResourcePackRepositoryDuck duck = (ResourcePackRepositoryDuck) mc.getResourcePackRepository();
duck.clearServerResourcePackBlocking();
try {
TASmodClient.client.send(new TASmodBufferBuilder(TASmodPackets.SAVESTATE_CLEAR_RESOURCEPACK));
} catch (Exception e) {
TASmod.LOGGER.catching(e);
}
});
break;

default:
throw new WrongSideException(packetId, Side.CLIENT);
}
}

@Override
public void onServerPacket(PacketID id, ByteBuffer buf, String username) throws PacketNotImplementedException, WrongSideException, Exception {
TASmodPackets packetId = (TASmodPackets) id;

switch (packetId) {
case SAVESTATE_CLEAR_RESOURCEPACK:
future.complete(username);
break;

default:
throw new WrongSideException(packetId, Side.SERVER);
}
}

public static void refreshServerResourcepack(MinecraftServer server) {
List<EntityPlayerMP> players = server.getPlayerList().getPlayers();
players.forEach((player) -> {
player.loadResourcePack(server.getResourcePackUrl(), server.getResourcePackHash());
});
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/minecrafttas/tasmod/util/Ducks.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,8 @@ public static interface PlayerChunkMapDuck {
*/
public void forceTick();
}

public static interface ResourcePackRepositoryDuck {
public void clearServerResourcePackBlocking();
}
}
1 change: 1 addition & 0 deletions src/main/resources/tasmod.mixin.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
// Savestates
"savestates.MixinChunkProviderClient",
"savestates.MixinWorldClient",
"savestates.MixinResourcePackRepository",

// Interpolation
"MixinFrustum",
Expand Down