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.network.play.server.*;
|
||||||
import net.minecraft.server.integrated.IntegratedServer;
|
import net.minecraft.server.integrated.IntegratedServer;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
|
import net.minecraft.util.SoundCategory;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
|
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
|
@SubscribeEvent
|
||||||
public void onPlayerTick(PlayerTickEvent e) {
|
public void onPlayerTick(PlayerTickEvent e) {
|
||||||
try {
|
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": [],
|
"server": [],
|
||||||
"client": [
|
"client": [
|
||||||
"MixinNetHandlerPlayClient",
|
"MixinNetHandlerPlayClient",
|
||||||
"MixinRenderGlobal"
|
"MixinPlayerControllerMP",
|
||||||
|
"MixinRenderGlobal",
|
||||||
|
"MixinWorldClient"
|
||||||
],
|
],
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"refmap": "mixins.replaymod.refmap.json"
|
"refmap": "mixins.replaymod.refmap.json"
|
||||||
|
|||||||
Reference in New Issue
Block a user