Various fixes and improvements for Forge WE 1.13.

This commit is contained in:
wizjany 2019-06-09 11:18:10 -04:00
parent f2f9c26602
commit c361da11f1
14 changed files with 263 additions and 76 deletions

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.forge;
import com.google.common.collect.ImmutableList;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
@ -210,11 +211,23 @@ public final class ForgeAdapter {
if (baseItemStack.getNbtData() != null) {
forgeCompound = NBTConverter.toNative(baseItemStack.getNbtData());
}
return new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount(), forgeCompound);
final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount());
itemStack.setTag(forgeCompound);
return itemStack;
}
public static BaseItemStack adapt(ItemStack itemStack) {
CompoundTag tag = NBTConverter.fromNative(itemStack.serializeNBT());
if (tag.getValue().isEmpty()) {
tag = null;
} else {
final Tag tagTag = tag.getValue().get("tag");
if (tagTag instanceof CompoundTag) {
tag = ((CompoundTag) tagTag);
} else {
tag = null;
}
}
return new BaseItemStack(adapt(itemStack.getItem()), tag, itemStack.getCount());
}

View File

@ -0,0 +1,46 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.registry.Category;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.ResourceLocation;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
public class ForgeBlockCategoryRegistry implements BlockCategoryRegistry {
@Override
public Set<BlockType> getCategorisedByName(String category) {
return Optional.ofNullable(BlockTags.getCollection().get(new ResourceLocation(category)))
.map(Tag::getAllElements).orElse(Collections.emptySet())
.stream().map(ForgeAdapter::adapt).collect(Collectors.toSet());
}
@Override
public Set<BlockType> getAll(Category<BlockType> category) {
return getCategorisedByName(category.getId());
}
}

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.world.registry.BundledBlockRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.state.IProperty;
import net.minecraftforge.fml.loading.FMLLoader;
import java.util.Collection;
import java.util.HashMap;
@ -42,7 +43,7 @@ public class ForgeBlockRegistry extends BundledBlockRegistry {
@Override
public String getName(BlockType blockType) {
Block block = ForgeAdapter.adapt(blockType);
if (block != null) {
if (block != null && FMLLoader.getDist().isClient()) {
return block.getNameTextComponent().getFormattedText();
} else {
return super.getName(blockType);

View File

@ -212,13 +212,14 @@ class ForgeDataFixer extends DataFixerBuilder implements com.sk89q.worldedit.wor
INSTANCE = this;
registerConverters();
registerInspectors();
this.fixer = new WrappedDataFixer(DataFixesManager.getDataFixer());
}
// Called after fixers are built and ready for FIXING
@Override
public DataFixer build(final Executor executor) {
return this.fixer = new WrappedDataFixer(DataFixesManager.getDataFixer());
return fixer;
}
private class WrappedDataFixer implements DataFixer {

View File

@ -0,0 +1,46 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.registry.Category;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.ResourceLocation;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
public class ForgeItemCategoryRegistry implements ItemCategoryRegistry {
@Override
public Set<ItemType> getCategorisedByName(String category) {
return Optional.ofNullable(ItemTags.getCollection().get(new ResourceLocation(category)))
.map(Tag::getAllElements).orElse(Collections.emptySet())
.stream().map(ForgeAdapter::adapt).collect(Collectors.toSet());
}
@Override
public Set<ItemType> getAll(Category<ItemType> category) {
return getCategorisedByName(category.getId());
}
}

View File

@ -21,6 +21,11 @@ package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.BundledItemRegistry;
import net.minecraft.client.resources.I18n;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.registries.RegistryManager;
import javax.annotation.Nullable;
@ -29,6 +34,13 @@ public class ForgeItemRegistry extends BundledItemRegistry {
@Nullable
@Override
public String getName(ItemType itemType) {
return super.getName(itemType); // TODO
if (FMLLoader.getDist().isClient()) {
final Item item = RegistryManager.ACTIVE.getRegistry(Item.class)
.getValue(ResourceLocation.tryCreate(itemType.getId()));
if (item != null) {
return I18n.format(item.getTranslationKey());
}
}
return super.getName(itemType);
}
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.forge;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.entity.BaseEntity;
@ -33,12 +34,16 @@ import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import io.netty.buffer.Unpooled;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.SPacketBlockChange;
import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.util.EnumHand;
@ -48,12 +53,14 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import java.io.IOException;
import java.util.UUID;
import javax.annotation.Nullable;
public class ForgePlayer extends AbstractPlayerActor {
private static final int STRUCTURE_BLOCK_PACKET_ID = 7;
private final EntityPlayerMP player;
protected ForgePlayer(EntityPlayerMP player) {
@ -183,18 +190,35 @@ public class ForgePlayer extends AbstractPlayerActor {
@Override
public <B extends BlockStateHolder<B>> void sendFakeBlock(BlockVector3 pos, B block) {
World world = getWorld();
if (!(world instanceof ForgeWorld)) {
return;
}
BlockPos loc = ForgeAdapter.toBlockPos(pos);
if (block == null) {
// TODO
// player.sendBlockChange(loc, player.getWorld().getBlockAt(loc).getBlockData());
final SPacketBlockChange packetOut = new SPacketBlockChange(((ForgeWorld) world).getWorld(), loc);
player.connection.sendPacket(packetOut);
} else {
// TODO
// player.sendBlockChange(loc, BukkitAdapter.adapt(block));
if (block instanceof BaseBlock && ((BaseBlock) block).hasNbtData()) {
player.connection.sendPacket(new SPacketUpdateTileEntity(
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), 7,
NBTConverter.toNative(((BaseBlock) block).getNbtData()))
);
final SPacketBlockChange packetOut = new SPacketBlockChange();
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
buf.writeBlockPos(loc);
buf.writeVarInt(Block.getStateId(ForgeAdapter.adapt(block.toImmutableState())));
try {
packetOut.readPacketData(buf);
} catch (IOException e) {
return;
}
player.connection.sendPacket(packetOut);
if (block instanceof BaseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) {
final BaseBlock baseBlock = (BaseBlock) block;
final CompoundTag nbtData = baseBlock.getNbtData();
if (nbtData != null) {
player.connection.sendPacket(new SPacketUpdateTileEntity(
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()),
STRUCTURE_BLOCK_PACKET_ID,
NBTConverter.toNative(nbtData))
);
}
}
}
}

View File

@ -20,8 +20,10 @@
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import com.sk89q.worldedit.world.registry.BundledRegistries;
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
import com.sk89q.worldedit.world.registry.ItemRegistry;
/**
@ -33,6 +35,8 @@ class ForgeRegistries extends BundledRegistries {
private final BlockRegistry blockRegistry = new ForgeBlockRegistry();
private final BiomeRegistry biomeRegistry = new ForgeBiomeRegistry();
private final ItemRegistry itemRegistry = new ForgeItemRegistry();
private final BlockCategoryRegistry blockCategoryRegistry = new ForgeBlockCategoryRegistry();
private final ItemCategoryRegistry itemCategoryRegistry = new ForgeItemCategoryRegistry();
@Override
public BlockRegistry getBlockRegistry() {
@ -49,6 +53,16 @@ class ForgeRegistries extends BundledRegistries {
return itemRegistry;
}
@Override
public BlockCategoryRegistry getBlockCategoryRegistry() {
return blockCategoryRegistry;
}
@Override
public ItemCategoryRegistry getItemCategoryRegistry() {
return itemCategoryRegistry;
}
/**
* Get a static instance.
*

View File

@ -60,8 +60,11 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
@ -243,25 +246,26 @@ public class ForgeWorld extends AbstractWorld {
@Override
public boolean useItem(BlockVector3 position, BaseItem item, Direction face) {
Item nativeItem = ForgeAdapter.adapt(item.getType());
ItemStack stack;
if (item.getNbtData() == null) {
stack = new ItemStack(nativeItem, 1);
} else {
stack = new ItemStack(nativeItem, 1, NBTConverter.toNative(item.getNbtData()));
}
ItemStack stack = ForgeAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtData(), 1));
World world = getWorld();
ItemUseContext itemUseContext = new ItemUseContext(
new WorldEditFakePlayer((WorldServer) world),
stack,
ForgeAdapter.toBlockPos(position),
ForgeAdapter.adapt(face),
0f,
0f,
0f
);
final WorldEditFakePlayer fakePlayer = new WorldEditFakePlayer((WorldServer) world);
fakePlayer.setHeldItem(EnumHand.MAIN_HAND, stack);
fakePlayer.setLocationAndAngles(position.getBlockX(), position.getBlockY(), position.getBlockZ(),
(float) face.toVector().toYaw(), (float) face.toVector().toPitch());
final BlockPos blockPos = ForgeAdapter.toBlockPos(position);
final EnumFacing enumFacing = ForgeAdapter.adapt(face);
ItemUseContext itemUseContext = new ItemUseContext(fakePlayer, stack, blockPos, enumFacing, blockPos.getX(), blockPos.getY(), blockPos.getZ());
EnumActionResult used = stack.onItemUse(itemUseContext);
return used != EnumActionResult.FAIL;
if (used != EnumActionResult.SUCCESS) {
// try activating the block
if (getWorld().getBlockState(blockPos).onBlockActivated(world, blockPos, fakePlayer, EnumHand.MAIN_HAND,
enumFacing, blockPos.getX(), blockPos.getY(), blockPos.getZ())) {
used = EnumActionResult.SUCCESS;
} else {
used = stack.getItem().onItemRightClick(world, fakePlayer, EnumHand.MAIN_HAND).getType();
}
}
return used == EnumActionResult.SUCCESS;
}
@Override

View File

@ -46,6 +46,7 @@ import net.minecraft.command.CommandSource;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
@ -105,7 +106,6 @@ public class ForgeWorldEdit {
IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
modBus.addListener(this::init);
modBus.addListener(this::load);
MinecraftForge.EVENT_BUS.register(ThreadSafeCache.getInstance());
MinecraftForge.EVENT_BUS.register(this);
@ -131,24 +131,6 @@ public class ForgeWorldEdit {
LOGGER.info("WorldEdit for Forge (version " + getInternalVersion() + ") is loaded");
}
private void load(FMLLoadCompleteEvent event) {
if (FMLLoader.getDist() == Dist.CLIENT) {
// we want to setup platform before we hit the main menu
// but this event is async -- so we must delay until the first game loop:
Minecraft.getInstance().addScheduledTask(this::setupPlatform);
}
}
@SubscribeEvent
public void serverAboutToStart(FMLServerAboutToStartEvent event) {
if (this.platform != null) {
LOGGER.warn("FMLServerStartingEvent occurred when FMLServerStoppingEvent hasn't");
WorldEdit.getInstance().getPlatformManager().unregister(platform);
}
setupPlatform();
}
private void setupPlatform() {
this.platform = new ForgePlatform(this);
@ -159,11 +141,6 @@ public class ForgeWorldEdit {
// } else {
this.provider = new ForgePermissionsProvider.VanillaPermissionsProvider(platform);
// }
setupRegistries();
config = new ForgeConfiguration(this);
config.load();
}
private void setupRegistries() {
@ -214,6 +191,11 @@ public class ForgeWorldEdit {
@SubscribeEvent
public void serverStarted(FMLServerStartedEvent event) {
setupPlatform();
setupRegistries();
config = new ForgeConfiguration(this);
config.load();
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
}
@ -228,7 +210,7 @@ public class ForgeWorldEdit {
if (event.getWorld().isRemote && event instanceof LeftClickEmpty) {
// catch LCE, pass it to server
InternalPacketHandler.HANDLER.sendToServer(new LeftClickAirEventMessage());
InternalPacketHandler.getHandler().sendToServer(new LeftClickAirEventMessage());
return;
}
@ -239,7 +221,7 @@ public class ForgeWorldEdit {
event instanceof PlayerInteractEvent.RightClickBlock
&& ((PlayerInteractEvent.RightClickBlock) event)
.getUseItem() == Event.Result.DENY;
if (isLeftDeny || isRightDeny || event.getEntity().world.isRemote) {
if (isLeftDeny || isRightDeny || event.getEntity().world.isRemote || event.getHand() == EnumHand.OFF_HAND) {
return;
}
@ -248,10 +230,7 @@ public class ForgeWorldEdit {
ForgeWorld world = getWorld(event.getEntityPlayer().world);
if (event instanceof PlayerInteractEvent.LeftClickEmpty) {
if (we.handleArmSwing(player)) {
// this event cannot be canceled
// event.setCanceled(true);
}
we.handleArmSwing(player); // this event cannot be canceled
} else if (event instanceof PlayerInteractEvent.LeftClickBlock) {
Location pos = new Location(world, event.getPos().getX(), event.getPos().getY(), event.getPos().getZ());

View File

@ -33,4 +33,8 @@ public class WorldEditFakePlayer extends FakePlayer {
super(world, FAKE_GAME_PROFILE);
}
@Override
public boolean canEat(boolean ignoreHunger) {
return true;
}
}

View File

@ -19,20 +19,14 @@
package com.sk89q.worldedit.forge.net.handler;
import com.sk89q.worldedit.forge.ForgeWorldEdit;
import com.sk89q.worldedit.forge.net.packet.LeftClickAirEventMessage;
import com.sk89q.worldedit.forge.net.packet.LeftClickAirEventMessage.Handler;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkRegistry.ChannelBuilder;
import net.minecraftforge.fml.network.simple.SimpleChannel;
public final class InternalPacketHandler {
private static final String PROTOCOL_VERSION = Integer.toString(1);
public static SimpleChannel HANDLER = ChannelBuilder
.named(new ResourceLocation(ForgeWorldEdit.MOD_ID, "internal"))
.clientAcceptedVersions(PROTOCOL_VERSION::equals)
.serverAcceptedVersions(PROTOCOL_VERSION::equals)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
private static final int PROTOCOL_VERSION = 1;
private static SimpleChannel HANDLER = PacketHandlerUtil
.buildLenientHandler("internal", PROTOCOL_VERSION)
.simpleChannel();
private InternalPacketHandler() {
@ -42,4 +36,8 @@ public final class InternalPacketHandler {
HANDLER.registerMessage(0, LeftClickAirEventMessage.class,
LeftClickAirEventMessage::encode, LeftClickAirEventMessage::decode, Handler::handle);
}
public static SimpleChannel getHandler() {
return HANDLER;
}
}

View File

@ -0,0 +1,48 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge.net.handler;
import com.sk89q.worldedit.forge.ForgeWorldEdit;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkRegistry;
import java.util.function.Predicate;
final class PacketHandlerUtil {
private PacketHandlerUtil() {
}
static NetworkRegistry.ChannelBuilder buildLenientHandler(String id, int protocolVersion) {
final String verStr = Integer.toString(protocolVersion);
final Predicate<String> validator = validateLenient(verStr);
return NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(ForgeWorldEdit.MOD_ID, id))
.clientAcceptedVersions(validator)
.serverAcceptedVersions(validator)
.networkProtocolVersion(() -> verStr);
}
private static Predicate<String> validateLenient(String protocolVersion) {
return remoteVersion ->
protocolVersion.equals(remoteVersion)
|| NetworkRegistry.ABSENT.equals(remoteVersion)
|| NetworkRegistry.ACCEPTVANILLA.equals(remoteVersion);
}
}

View File

@ -29,7 +29,6 @@ import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkEvent.ClientCustomPayloadEvent;
import net.minecraftforge.fml.network.NetworkEvent.ServerCustomPayloadEvent;
import net.minecraftforge.fml.network.NetworkRegistry.ChannelBuilder;
import net.minecraftforge.fml.network.event.EventNetworkChannel;
import java.nio.charset.Charset;
@ -41,13 +40,11 @@ public final class WECUIPacketHandler {
}
public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8");
private static final String PROTOCOL_VERSION = Integer.toString(1);
public static EventNetworkChannel HANDLER = ChannelBuilder
.named(new ResourceLocation(ForgeWorldEdit.MOD_ID, ForgeWorldEdit.CUI_PLUGIN_CHANNEL))
.clientAcceptedVersions(PROTOCOL_VERSION::equals)
.serverAcceptedVersions(PROTOCOL_VERSION::equals)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
private static final int PROTOCOL_VERSION = 1;
private static EventNetworkChannel HANDLER = PacketHandlerUtil
.buildLenientHandler(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, PROTOCOL_VERSION)
.eventNetworkChannel();
public static void init() {
HANDLER.addListener(WECUIPacketHandler::onPacketData);