mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-05 19:47:00 -04:00
ClientSerializable for block entities
This commit is contained in:
parent
b291a955de
commit
c5915afee7
5 changed files with 170 additions and 0 deletions
src/main
java/net/fabricmc/fabric
block/entity
mixin/block/entity
resources
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.block.entity;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
/**
|
||||
* Implement this interace on a BlockEntity which you would like to be
|
||||
* synchronized with the client side using the built-in engine methods.
|
||||
*/
|
||||
public interface ClientSerializable {
|
||||
void fromClientTag(CompoundTag tag);
|
||||
CompoundTag toClientTag(CompoundTag tag);
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.block.entity;
|
||||
|
||||
import net.fabricmc.fabric.block.entity.ClientSerializable;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.packet.BlockEntityUpdateClientPacket;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(BlockEntity.class)
|
||||
public abstract class MixinBlockEntity {
|
||||
@Shadow
|
||||
public abstract BlockEntityType<?> getType();
|
||||
|
||||
@Shadow
|
||||
public abstract BlockPos getPos();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "getUpdatePacket", cancellable = true)
|
||||
public void getUpdatePacket(CallbackInfoReturnable<BlockEntityUpdateClientPacket> info) {
|
||||
Object self = (Object) this;
|
||||
|
||||
if (self instanceof ClientSerializable) {
|
||||
// Mojang's serialization of x/y/z into the update packet is redundant,
|
||||
// as we have a separate fromClientTag() we don't do it.
|
||||
// However, we use the "id" field for type discernment, as actionId
|
||||
// is capped at 8 bits of size with the values presumably reserved
|
||||
// by Mojang.
|
||||
|
||||
CompoundTag tag = new CompoundTag();
|
||||
Identifier entityId = BlockEntityType.getId(getType());
|
||||
if (entityId == null) {
|
||||
throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!");
|
||||
}
|
||||
|
||||
tag.putString("id", entityId.toString());
|
||||
((ClientSerializable) self).toClientTag(tag);
|
||||
info.setReturnValue(new BlockEntityUpdateClientPacket(getPos(), 127, tag));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "serializeInitialChunkData")
|
||||
public void serializeInitialChunkData(CallbackInfoReturnable<CompoundTag> info) {
|
||||
Object self = (Object) this;
|
||||
|
||||
if (self instanceof ClientSerializable && info.getReturnValue() != null) {
|
||||
info.setReturnValue(((ClientSerializable) self).toClientTag(info.getReturnValue()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.block.entity;
|
||||
|
||||
import net.fabricmc.fabric.block.entity.ClientSerializable;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.packet.BlockEntityUpdateClientPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ClientPlayNetworkHandler.class)
|
||||
public class MixinClientPlayNetworkHandler {
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/packet/BlockEntityUpdateClientPacket;getActionId()I", ordinal = 0), method = "onBlockEntityUpdate", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void onBlockEntityUpdate(BlockEntityUpdateClientPacket packet, CallbackInfo info, BlockEntity entity) {
|
||||
if (entity instanceof ClientSerializable) {
|
||||
if (packet.getActionId() == 127) {
|
||||
ClientSerializable serializable = (ClientSerializable) entity;
|
||||
String id = packet.getCompoundTag().getString("id");
|
||||
if (id != null) {
|
||||
Identifier otherIdObj = BlockEntityType.getId(entity.getType());
|
||||
;
|
||||
if (otherIdObj == null) {
|
||||
LOGGER.error(entity.getClass() + " is missing a mapping! This is a bug!");
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
String otherId = otherIdObj.toString();
|
||||
|
||||
if (otherId.equals(id)) {
|
||||
serializable.fromClientTag(packet.getCompoundTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
"package": "net.fabricmc.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"block.entity.MixinClientPlayNetworkHandler",
|
||||
"events.MixinClientPlayerInteractionManager",
|
||||
"events.MixinMinecraftClient",
|
||||
"networking.MixinClientPlayNetworkHandler",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"package": "net.fabricmc.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"block.entity.MixinBlockEntity",
|
||||
"commands.MixinServerCommandManager",
|
||||
"events.MixinMinecraftServer",
|
||||
"events.MixinServerPlayNetworkHandler",
|
||||
|
|
Loading…
Add table
Reference in a new issue