Skip to content

Commit

Permalink
Stop syncing VirtualObjects to client, improve entity and item handli…
Browse files Browse the repository at this point in the history
…ng, replace blockstate in falling block packets
  • Loading branch information
Patbox committed May 18, 2021
1 parent 24257a1 commit 05003e1
Show file tree
Hide file tree
Showing 25 changed files with 295 additions and 18 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ After that, it's as easy as making your items implement `VirtualItem`, blocks `V
It's also recommended registering block entities with `PolymerMod.registerVirtualBlockEntity(Identifier)`.

### Limitations
Most command arguments that refer to entity types, items and blocks will be warning that
it's are incorrect. However, commands itself should work just fine.

While it's supported, please limit creation of VirtualBlock light sources. Because of how Minecraft
handles light updates on server/client, these can be little laggy (as it needs to be send updates every time light changes).

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.11.3

# Mod Properties
mod_version = 0.0.2
mod_version = 0.0.3
maven_group = eu.pb4
archives_base_name = polymer

Expand Down
32 changes: 30 additions & 2 deletions src/main/java/eu/pb4/polymer/item/ItemHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -88,7 +89,24 @@ public static ItemStack getRealItemStack(ItemStack itemStack) {
return out;
}

public static ItemStack createBasicVirtualItemStack(ItemStack itemStack, ServerPlayerEntity player) {
public static ItemStack createMinimalVirtualItemStack(ItemStack itemStack) {
Item item = itemStack.getItem();
if (itemStack.getItem() instanceof VirtualItem) {
item = ((VirtualItem) itemStack.getItem()).getVirtualItem();
}

ItemStack out = new ItemStack(item, itemStack.getCount());

if (itemStack.getTag() != null) {
out.getOrCreateTag().put(ItemHelper.REAL_TAG, itemStack.getTag());
}

out.getOrCreateTag().putString(ItemHelper.VIRTUAL_ITEM_ID, Registry.ITEM.getId(itemStack.getItem()).toString());

return out;
}

public static ItemStack createBasicVirtualItemStack(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
Item item = itemStack.getItem();
if (itemStack.getItem() instanceof VirtualItem) {
item = ((VirtualItem) itemStack.getItem()).getVirtualItem();
Expand Down Expand Up @@ -159,7 +177,7 @@ public static ItemStack createBasicVirtualItemStack(ItemStack itemStack, ServerP
return out;
}

protected static List<Text> buildTooltip(ItemStack stack, ServerPlayerEntity player) {
protected static List<Text> buildTooltip(ItemStack stack, @Nullable ServerPlayerEntity player) {
List<Text> list = Lists.newArrayList();
int hideFlags = getHideFlags(stack);

Expand Down Expand Up @@ -210,6 +228,7 @@ protected static List<Text> buildTooltip(ItemStack stack, ServerPlayerEntity pla
EntityAttributeModifier entityAttributeModifier = entry.getValue();
double value = entityAttributeModifier.getValue();
boolean bl = false;

if (player != null) {
if (entityAttributeModifier.getId().equals(ATTACK_DAMAGE_MODIFIER_ID)) {
value += player.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE);
Expand All @@ -219,6 +238,15 @@ protected static List<Text> buildTooltip(ItemStack stack, ServerPlayerEntity pla
value += player.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_SPEED);
bl = true;
}
} else {
if (entityAttributeModifier.getId().equals(ATTACK_DAMAGE_MODIFIER_ID)) {
value += 1;
value += EnchantmentHelper.getAttackDamage(stack, EntityGroup.DEFAULT);
bl = true;
} else if (entityAttributeModifier.getId().equals(ATTACK_SPEED_MODIFIER_ID)) {
value += 4;
bl = true;
}
}

double g;
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/eu/pb4/polymer/item/VirtualItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.*;
import org.jetbrains.annotations.Nullable;

import java.util.List;

Expand All @@ -27,7 +28,7 @@ public interface VirtualItem extends VirtualObject {
* @param player Player for which it's send
* @return Client-side ItemStack
*/
default ItemStack getVirtualItemStack(ItemStack itemStack, ServerPlayerEntity player) {
default ItemStack getVirtualItemStack(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
return ItemHelper.createBasicVirtualItemStack(itemStack, player);
}

Expand All @@ -39,5 +40,5 @@ default ItemStack getVirtualItemStack(ItemStack itemStack, ServerPlayerEntity pl
* @param stack Server-side ItemStack
* @param player Target player
*/
default void addTextToTooltip(List<Text> tooltip, ItemStack stack, ServerPlayerEntity player) {}
default void addTextToTooltip(List<Text> tooltip, ItemStack stack, @Nullable ServerPlayerEntity player) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket;
import net.minecraft.world.chunk.WorldChunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
Expand All @@ -15,6 +16,7 @@

@Mixin(ChunkDataS2CPacket.class)
public class ChunkDataS2CPacketMixin implements ChunkDataS2CPacketInterface {
@Unique
private WorldChunk worldChunk;

@Inject(method = "<init>(Lnet/minecraft/world/chunk/WorldChunk;I)V", at = @At("TAIL"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ private BlockState replaceWithVirtualBlockState(BlockState state) {
return state;
}



@Environment(EnvType.CLIENT)
@ModifyArg(method = "visitUpdates", at = @At(value = "INVOKE", target = "Ljava/util/function/BiConsumer;accept(Ljava/lang/Object;Ljava/lang/Object;)V"), index = 1)
private Object replaceBlockStateOnClient(Object state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eu.pb4.polymer.mixin.block;

import eu.pb4.polymer.block.VirtualBlock;
import net.minecraft.block.BlockState;
import net.minecraft.entity.FallingBlockEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;

@Mixin(FallingBlockEntity.class)
public class FallingBlockEntityMixin {

@ModifyArg(method = "createSpawnPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;getRawIdFromState(Lnet/minecraft/block/BlockState;)I"))
private BlockState replaceWithVirtual(BlockState state) {
if (state.getBlock() instanceof VirtualBlock) {
return ((VirtualBlock) state.getBlock()).getVirtualBlockState(state);
} else {
return state;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -46,6 +47,7 @@ public abstract class ServerChunkManagerMixin {
@Nullable
public abstract WorldChunk getWorldChunk(int chunkX, int chunkZ);

@Unique
private final Object2LongArrayMap<ChunkPos> lastUpdates = new Object2LongArrayMap<>();

@Inject(method = "onLightUpdate", at = @At("TAIL"))
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/eu/pb4/polymer/mixin/block/WorldChunkMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand Down Expand Up @@ -54,6 +55,7 @@ private void virtualBlocksInit2(World world, ProtoChunk protoChunk, CallbackInfo
}


@Unique
private void generateVirtualBlockSet() {
for (byte x = 0; x < 16; x++) {
for (byte z = 0; z < 16; z++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package eu.pb4.polymer.mixin.entity;

import eu.pb4.polymer.entity.VirtualEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;


@Mixin(EntitySpawnS2CPacket.class)
public class EntitySpawnS2CPacketMixin {
@Redirect(method = "<init>(Lnet/minecraft/entity/Entity;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getType()Lnet/minecraft/entity/EntityType;"))
private static EntityType<?> replaceWithVirtual(Entity entity) {
if (entity instanceof VirtualEntity) {
return ((VirtualEntity) entity).getVirtualEntityType();
} else {
return entity.getType();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

@Mixin(EntityTrackerEntry.class)
public class EntityTrackerEntryMixin {

@Shadow
@Final
private Entity entity;
Expand All @@ -47,7 +46,7 @@ private void sendVirtualStuff(Consumer<Packet<?>> sender, CallbackInfo ci) {
sender.accept(new EntityEquipmentUpdateS2CPacket(this.entity.getEntityId(), list));
((VirtualEntity) this.entity).sendPacketsAfterCreation(sender);
}
} catch(Exception e) {
} catch (Exception e) {
e.printStackTrace();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

@Mixin(EntityTrackerUpdateS2CPacket.class)
public class EntityTrackerUpdateS2CPacketMixin {

@Shadow private List<DataTracker.Entry<?>> trackedValues;

@Inject(method = "<init>(ILnet/minecraft/entity/data/DataTracker;Z)V", at = @At("TAIL"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ private void sendVirtualInventory(Map<EquipmentSlot, ItemStack> map, CallbackInf
}



public LivingEntityMixin(EntityType<?> type, World world) {
super(type, world);
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/eu/pb4/polymer/mixin/item/ItemStackContentMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package eu.pb4.polymer.mixin.item;

import eu.pb4.polymer.item.ItemHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.text.HoverEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(HoverEvent.ItemStackContent.class)
public class ItemStackContentMixin {
@ModifyVariable(method = "<init>(Lnet/minecraft/item/ItemStack;)V", at = @At("HEAD"), ordinal = 0)
private static ItemStack replaceWithVirtual(ItemStack stack) {
return ItemHelper.getVirtualItemStack(stack, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.minecraft.item.BucketItem;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
Expand All @@ -15,11 +16,15 @@
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.ArrayList;
import java.util.List;

@Mixin(ServerPlayNetworkHandler.class)
public abstract class ServerPlayNetworkHandlerMixin {

Expand Down Expand Up @@ -55,4 +60,43 @@ private void updateMoreBlocks(PlayerInteractBlockC2SPacket packet, CallbackInfo
this.player.networkHandler.sendPacket(new BlockUpdateS2CPacket(this.player.world, base.offset(direction)));
}
}

@Unique
private List<ItemStack> armorItems = new ArrayList<>();

@Inject(method = "onClickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;updateLastActionTime()V", shift = At.Shift.AFTER))
private void storeSomeData(ClickSlotC2SPacket packet, CallbackInfo ci) {
if (this.player.currentScreenHandler == this.player.playerScreenHandler) {
for (ItemStack stack : this.player.inventory.armor) {
armorItems.add(stack.copy());
}
}
}

@Inject(method = "onClickSlot", at = @At("TAIL"))
private void resendArmorIfNeeded(ClickSlotC2SPacket packet, CallbackInfo ci) {
if (this.player.currentScreenHandler == this.player.playerScreenHandler && packet.getSlot() != -999) {
int x = 0;
for (ItemStack stack : this.player.inventory.armor) {
if (stack.getItem() instanceof VirtualItem && !ItemStack.areEqual(this.armorItems.get(x), stack)) {
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(this.player.playerScreenHandler.syncId,
8 - x,
stack));

if (packet.getSlot() != 8 - x) {
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(this.player.playerScreenHandler.syncId, packet.getSlot(),
this.player.playerScreenHandler.getSlot(packet.getSlot()).getStack()));
}

this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(-1,
0,
this.player.inventory.getCursorStack()));
return;
}
x++;
}
}

this.armorItems.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

@Mixin(PacketByteBuf.class)
public class PacketByteBufContextMixin implements PlayerContextInterface {
@Unique ServerPlayerEntity player;
@Unique
ServerPlayerEntity player;

@Override
public void setPolymerPlayer(ServerPlayerEntity player) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package eu.pb4.polymer.mixin.other;

import eu.pb4.polymer.interfaces.VirtualObject;
import net.fabricmc.fabric.impl.registry.sync.RegistrySyncManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(RegistrySyncManager.class)
public class RegistrySyncManagerMixin {

@Redirect(method = "toTag", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/Registry;getId(Ljava/lang/Object;)Lnet/minecraft/util/Identifier;"))
private static Identifier skipVirtualObjects(Registry<Object> registry, Object obj, boolean isClientSync) {
if (isClientSync && obj instanceof VirtualObject) {
return null;
} else {
return registry.getId(obj);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import eu.pb4.polymer.interfaces.PlayerContextInterface;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -18,9 +19,7 @@ public class ServerPlayNetworkHandlerContextMixin {
@Shadow
public ServerPlayerEntity player;


@Inject(method = "sendPacket(Lnet/minecraft/network/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V",
at = @At("HEAD"))
@Inject(method = "sendPacket(Lnet/minecraft/network/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V", at = @At("HEAD"))
public void setPlayerInPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> listener, CallbackInfo ci) {
if (packet instanceof PlayerContextInterface) {
((PlayerContextInterface) packet).setPolymerPlayer(this.player);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package eu.pb4.polymer.mixin.other;

import eu.pb4.polymer.PolymerMod;
import eu.pb4.polymer.interfaces.VirtualObject;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket;
import net.minecraft.recipe.Recipe;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
Expand Down
Loading

0 comments on commit 05003e1

Please sign in to comment.