diff --git a/gradle.properties b/gradle.properties index ae2050fa..cba2fd01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.11.3 # Mod Properties - mod_version = 0.1.0-pre3-1.17 + mod_version = 0.1.0-pre4-1.17 maven_group = eu.pb4 archives_base_name = polymer diff --git a/src/main/java/eu/pb4/polymer/block/VirtualBlock.java b/src/main/java/eu/pb4/polymer/block/VirtualBlock.java index 63dc0e6b..71506a7c 100644 --- a/src/main/java/eu/pb4/polymer/block/VirtualBlock.java +++ b/src/main/java/eu/pb4/polymer/block/VirtualBlock.java @@ -5,6 +5,7 @@ import net.minecraft.block.BlockState; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; /** @@ -18,6 +19,17 @@ public interface VirtualBlock extends VirtualObject { */ Block getVirtualBlock(); + /** + * Returns block used on client for provided location; + * It's used to validate blocks + * + * @return Vanilla (or other) Block instance + */ + default Block getVirtualBlock(BlockPos pos, World world) { + return this.getVirtualBlock(); + } + + /** * Returns default virtual BlockState * diff --git a/src/main/java/eu/pb4/polymer/item/ItemHelper.java b/src/main/java/eu/pb4/polymer/item/ItemHelper.java index db150c82..37dad0fd 100644 --- a/src/main/java/eu/pb4/polymer/item/ItemHelper.java +++ b/src/main/java/eu/pb4/polymer/item/ItemHelper.java @@ -16,6 +16,7 @@ import net.minecraft.nbt.NbtString; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -141,7 +142,9 @@ public static ItemStack createBasicVirtualItemStack(ItemStack itemStack, @Nullab } List tooltip = itemStack.getTooltip(player, TooltipContext.Default.NORMAL); - out.setCustomName(tooltip.remove(0)); + MutableText name = tooltip.remove(0).shallowCopy(); + name.setStyle(name.getStyle().withParent(NON_ITALIC_STYLE)); + out.setCustomName(name); if (itemStack.getItem() instanceof VirtualItem) { ((VirtualItem) itemStack.getItem()).modifyTooltip(tooltip, itemStack, player); diff --git a/src/main/java/eu/pb4/polymer/mixin/block/BlockEventS2CPacketMixin.java b/src/main/java/eu/pb4/polymer/mixin/block/BlockEventS2CPacketMixin.java new file mode 100644 index 00000000..16def575 --- /dev/null +++ b/src/main/java/eu/pb4/polymer/mixin/block/BlockEventS2CPacketMixin.java @@ -0,0 +1,47 @@ +package eu.pb4.polymer.mixin.block; + +import eu.pb4.polymer.block.VirtualBlock; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.Block; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.s2c.play.BlockEventS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.*; +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 xyz.nucleoid.packettweaker.PacketContext; + +@Mixin(BlockEventS2CPacket.class) +public class BlockEventS2CPacketMixin { + @Shadow @Mutable + private Block block; + + @Shadow @Final private BlockPos pos; + + @Unique private Block oldBlock = null; + + @Environment(EnvType.CLIENT) + @Inject(method = "getBlock", at = @At("TAIL"), cancellable = true) + private void replaceBlockClient(CallbackInfoReturnable cir) { + ServerPlayerEntity player = MinecraftClient.getInstance().getServer().getPlayerManager().getPlayer(MinecraftClient.getInstance().player.getUuid()); + if (this.oldBlock instanceof VirtualBlock virtualBlock) { + cir.setReturnValue(virtualBlock.getVirtualBlock(this.pos, player.getServerWorld())); + } + } + + @Inject(method = "write", at = @At("TAIL")) + private void replaceBlock(PacketByteBuf byteBuf, CallbackInfo ci) { + if (oldBlock == null) { + this.oldBlock = block; + } + + if (this.oldBlock instanceof VirtualBlock virtualBlock) { + this.block = virtualBlock.getVirtualBlock(this.pos, PacketContext.get().getTarget().getServerWorld()); + } + } +} diff --git a/src/main/java/eu/pb4/polymer/mixin/block/PlayerActionResponseS2CPacketMixin.java b/src/main/java/eu/pb4/polymer/mixin/block/PlayerActionResponseS2CPacketMixin.java new file mode 100644 index 00000000..a28a4963 --- /dev/null +++ b/src/main/java/eu/pb4/polymer/mixin/block/PlayerActionResponseS2CPacketMixin.java @@ -0,0 +1,36 @@ +package eu.pb4.polymer.mixin.block; + +import eu.pb4.polymer.block.VirtualBlock; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.BlockState; +import net.minecraft.network.packet.s2c.play.PlayerActionResponseS2CPacket; +import org.spongepowered.asm.mixin.Final; +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.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerActionResponseS2CPacket.class) +public class PlayerActionResponseS2CPacketMixin { + @Shadow @Final private BlockState state; + + @ModifyArg(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;getRawIdFromState(Lnet/minecraft/block/BlockState;)I")) + private BlockState replaceWithVirtualBlockState(BlockState state) { + if (state.getBlock() instanceof VirtualBlock) { + return ((VirtualBlock) state.getBlock()).getVirtualBlockState(state); + } + return state; + } + + + @Environment(EnvType.CLIENT) + @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) + public void replaceWithVirtualState(CallbackInfoReturnable cir) { + if (this.state.getBlock() instanceof VirtualBlock virtualBlock) { + cir.setReturnValue(virtualBlock.getVirtualBlockState(this.state)); + } + } +} diff --git a/src/main/java/eu/pb4/polymer/mixin/item/ClickSlotC2SPacketMixin.java b/src/main/java/eu/pb4/polymer/mixin/item/ClickSlotC2SPacketMixin.java new file mode 100644 index 00000000..d1645d48 --- /dev/null +++ b/src/main/java/eu/pb4/polymer/mixin/item/ClickSlotC2SPacketMixin.java @@ -0,0 +1,30 @@ +package eu.pb4.polymer.mixin.item; + +import eu.pb4.polymer.item.ItemHelper; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClickSlotC2SPacket.class) +public class ClickSlotC2SPacketMixin { + @Inject(method = "getStack", at = @At("TAIL"), cancellable = true) + private void replaceWithReal(CallbackInfoReturnable cir) { + cir.setReturnValue(ItemHelper.getRealItemStack(cir.getReturnValue())); + } + + @Inject(method = "getModifiedStacks", at = @At("TAIL"), cancellable = true) + private void replaceMultipleReal(CallbackInfoReturnable> cir) { + Int2ObjectMap map = new Int2ObjectArrayMap(); + + for (Int2ObjectMap.Entry entry : cir.getReturnValue().int2ObjectEntrySet()) { + map.put(entry.getIntKey(), ItemHelper.getRealItemStack(entry.getValue())); + } + + cir.setReturnValue(map); + } +} diff --git a/src/main/java/eu/pb4/polymer/mixin/item/CreativeInventoryActionC2SPacketMixin.java b/src/main/java/eu/pb4/polymer/mixin/item/CreativeInventoryActionC2SPacketMixin.java new file mode 100644 index 00000000..888721fc --- /dev/null +++ b/src/main/java/eu/pb4/polymer/mixin/item/CreativeInventoryActionC2SPacketMixin.java @@ -0,0 +1,17 @@ +package eu.pb4.polymer.mixin.item; + +import eu.pb4.polymer.item.ItemHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(CreativeInventoryActionC2SPacket.class) +public class CreativeInventoryActionC2SPacketMixin { + @Inject(method = "getItemStack", at = @At("TAIL"), cancellable = true) + private void replaceWithReal(CallbackInfoReturnable cir) { + cir.setReturnValue(ItemHelper.getRealItemStack(cir.getReturnValue())); + } +} diff --git a/src/main/java/eu/pb4/polymer/mixin/item/ItemStackMixin.java b/src/main/java/eu/pb4/polymer/mixin/item/ItemStackMixin.java new file mode 100644 index 00000000..5414718a --- /dev/null +++ b/src/main/java/eu/pb4/polymer/mixin/item/ItemStackMixin.java @@ -0,0 +1,16 @@ +package eu.pb4.polymer.mixin.item; + +import eu.pb4.polymer.item.ItemHelper; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(ItemStack.class) +public class ItemStackMixin { + @ModifyArg(method = "getTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/LiteralText;(Ljava/lang/String;)V", ordinal = 3)) + private String changeId(String id) { + ItemStack stack = (ItemStack) (Object) this; + return stack.hasTag() && stack.getTag().contains(ItemHelper.VIRTUAL_ITEM_ID) ? stack.getTag().getString(ItemHelper.VIRTUAL_ITEM_ID) : id; + } +} diff --git a/src/main/java/eu/pb4/polymer/resourcepack/DefaultRPBuilder.java b/src/main/java/eu/pb4/polymer/resourcepack/DefaultRPBuilder.java index 5a0e583a..8541a0f3 100644 --- a/src/main/java/eu/pb4/polymer/resourcepack/DefaultRPBuilder.java +++ b/src/main/java/eu/pb4/polymer/resourcepack/DefaultRPBuilder.java @@ -94,11 +94,15 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Path fileOut; try { - fileOut = output.resolve(assets.relativize(file)); + fileOut = output.resolve(assets.relativize(file).toString()); } catch (Exception e) { - fileOut = file; + fileOut = output.resolve(file.toString()); + } - fileOut.getParent().toFile().mkdirs(); + + try { + fileOut.getParent().toFile().mkdirs(); + } catch (Exception e) { } Files.copy(file, fileOut); return FileVisitResult.CONTINUE; diff --git a/src/main/resources/polymer.mixins.json b/src/main/resources/polymer.mixins.json index 7b9d20f2..4e9c5649 100644 --- a/src/main/resources/polymer.mixins.json +++ b/src/main/resources/polymer.mixins.json @@ -8,12 +8,14 @@ "block.AbstractBlockAccessor", "block.AbstractBlockMixin", "block.AbstractBlockSettingAccessor", + "block.BlockEventS2CPacketMixin", "block.BlockPaletteMixin", "block.BlockUpdateS2CPacketMixin", "block.ChunkDataS2CPacketMixin", "block.ChunkDeltaUpdateS2CPacketAccessor", "block.ChunkDeltaUpdateS2CPacketMixin", "block.FallingBlockEntityMixin", + "block.PlayerActionResponseS2CPacketMixin", "block.ServerChunkManagerMixin", "block.ServerPlayerInteractionManagerMixin", "block.ServerPlayNetworkHandlerMixin", @@ -28,6 +30,7 @@ "entity.LivingEntityMixin", "entity.MobSpawnS2CPacketMixin", "item.ItemStackContentMixin", + "item.ItemStackMixin", "item.PacketByteBufMixin", "item.ServerPlayNetworkHandlerMixin", "other.CommandManagerMixin", @@ -37,6 +40,8 @@ "polymc.BlockPolyGeneratorMixin" ], "client": [ + "item.ClickSlotC2SPacketMixin", + "item.CreativeInventoryActionC2SPacketMixin", "item.EntityEquipmentUpdateS2CPacketMixin", "item.InventoryS2CPacketMixin", "item.ScreenHandlerSlotUpdateS2CPacketMixin"