Fix several sounds and the block break effect not being recorded (fixes #8)
This commit is contained in:
@@ -11,6 +11,8 @@ import net.minecraft.network.datasync.EntityDataManager;
|
||||
import net.minecraft.network.play.server.*;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
|
||||
@@ -69,6 +71,25 @@ public class RecordingEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void onClientSound(SoundEvent sound, SoundCategory category,
|
||||
double x, double y, double z, float volume, float pitch) {
|
||||
try {
|
||||
// Send to all other players in ServerWorldEventHandler#playSoundToAllNearExcept
|
||||
packetListener.save(new SPacketSoundEffect(sound, category, x, y, z, volume, pitch));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void onClientEffect(int type, BlockPos pos, int data) {
|
||||
try {
|
||||
// Send to all other players in ServerWorldEventHandler#playEvent
|
||||
packetListener.save(new SPacketEffect(type, pos, data, false));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPlayerTick(PlayerTickEvent e) {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import com.replaymod.recording.handler.RecordingEventHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(PlayerControllerMP.class)
|
||||
public abstract class MixinPlayerControllerMP implements RecordingEventHandler.RecordingEventSender {
|
||||
|
||||
@Shadow
|
||||
private Minecraft mc;
|
||||
|
||||
// Redirects the call to playEvent without the initial player argument to the method with that argument
|
||||
// The new method will then play it and (if applicable) record it. (See MixinWorldClient)
|
||||
// This is necessary for the block break event (particles and sound) to be recorded. Otherwise it looks like the
|
||||
// event was emitted because of a packet (player will be null) and not as it actually was (by the player).
|
||||
@Redirect(method = "onPlayerDestroyBlock", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/World;playEvent(ILnet/minecraft/util/math/BlockPos;I)V"))
|
||||
public void replayModRecording_playEvent_fixed(World world, int type, BlockPos pos, int data) {
|
||||
world.playEvent(mc.thePlayer, type, pos, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import com.replaymod.recording.handler.RecordingEventHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.profiler.Profiler;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldProvider;
|
||||
import net.minecraft.world.storage.ISaveHandler;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(WorldClient.class)
|
||||
public abstract class MixinWorldClient extends World implements RecordingEventHandler.RecordingEventSender {
|
||||
@Shadow
|
||||
private Minecraft mc;
|
||||
|
||||
protected MixinWorldClient(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client) {
|
||||
super(saveHandlerIn, info, providerIn, profilerIn, client);
|
||||
}
|
||||
|
||||
private RecordingEventHandler replayModRecording_getRecordingEventHandler() {
|
||||
return ((RecordingEventHandler.RecordingEventSender) mc.renderGlobal).getRecordingEventHandler();
|
||||
}
|
||||
|
||||
// Sounds that are emitted by thePlayer no longer take the long way over the server
|
||||
// but are instead played directly by the client. The server only sends these sounds to
|
||||
// other clients so we have to record them manually.
|
||||
// E.g. Block place sounds
|
||||
@Inject(method = "playSound", at = @At("HEAD"))
|
||||
public void replayModRecording_recordClientSound(EntityPlayer player, double x, double y, double z, SoundEvent sound, SoundCategory category,
|
||||
float volume, float pitch, CallbackInfo ci) {
|
||||
if (player == mc.thePlayer) {
|
||||
RecordingEventHandler handler = replayModRecording_getRecordingEventHandler();
|
||||
if (handler != null) {
|
||||
handler.onClientSound(sound, category, x, y, z, volume, pitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same goes for level events (also called effects). E.g. door open, block break, etc.
|
||||
// These are handled in the World class, so we override the method in WorldClient and add our special handling.
|
||||
@Override
|
||||
public void playEvent(EntityPlayer player, int type, BlockPos pos, int data) {
|
||||
if (player == mc.thePlayer) {
|
||||
// We caused this event, the server won't send it to us
|
||||
RecordingEventHandler handler = replayModRecording_getRecordingEventHandler();
|
||||
if (handler != null) {
|
||||
handler.onClientEffect(type, pos, data);
|
||||
}
|
||||
}
|
||||
super.playEvent(player, type, pos, data);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,9 @@
|
||||
"server": [],
|
||||
"client": [
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinRenderGlobal"
|
||||
"MixinPlayerControllerMP",
|
||||
"MixinRenderGlobal",
|
||||
"MixinWorldClient"
|
||||
],
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "mixins.replaymod.refmap.json"
|
||||
|
||||
Reference in New Issue
Block a user