diff --git a/patches/minecraft/net/minecraft/tileentity/TileEntityType.java.patch b/patches/minecraft/net/minecraft/tileentity/TileEntityType.java.patch new file mode 100644 index 0000000000..761d0df6e8 --- /dev/null +++ b/patches/minecraft/net/minecraft/tileentity/TileEntityType.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/tileentity/TileEntityType.java ++++ b/net/minecraft/tileentity/TileEntityType.java +@@ -12,9 +12,9 @@ + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +-public class TileEntityType { ++public class TileEntityType extends net.minecraftforge.registries.ForgeRegistryEntry> { + private static final Logger field_206866_A = LogManager.getLogger(); +- public static final RegistryNamespaced> field_200970_a = new RegistryNamespaced>(); ++ public static final RegistryNamespaced> field_200970_a = net.minecraftforge.registries.GameData.getWrapper(TileEntityType.class); + public static final TileEntityType field_200971_b = func_200966_a("furnace", TileEntityType.Builder.func_200963_a(TileEntityFurnace::new)); + public static final TileEntityType field_200972_c = func_200966_a("chest", TileEntityType.Builder.func_200963_a(TileEntityChest::new)); + public static final TileEntityType field_200973_d = func_200966_a("trapped_chest", TileEntityType.Builder.func_200963_a(TileEntityTrappedChest::new)); diff --git a/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch index 88c6d519c6..ee3a954736 100644 --- a/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch +++ b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch @@ -1,27 +1,23 @@ --- a/net/minecraft/world/chunk/storage/AnvilChunkLoader.java +++ b/net/minecraft/world/chunk/storage/AnvilChunkLoader.java -@@ -445,7 +445,20 @@ +@@ -445,6 +445,16 @@ compound.setTag("Heightmaps", nbttagcompound2); compound.setTag("Structures", this.func_202160_a(chunkIn.x, chunkIn.z, chunkIn.func_201609_c(), chunkIn.func_201604_d())); -+ ++ + try + { + final NBTTagCompound capTag = chunkIn.writeCapsToNBT(); -+ if (capTag != null) -+ { -+ compound.setTag("ForgeCaps", capTag); - } ++ if (capTag != null) compound.setTag("ForgeCaps", capTag); + } + catch (Exception exception) + { + org.apache.logging.log4j.LogManager.getLogger().error("A capability provider has thrown an exception trying to write state. It will not persist. Report this to the mod author", exception); + } -+ } + } private Chunk readChunkFromNBT(IWorld worldIn, NBTTagCompound compound) { - int i = compound.getInteger("xPos"); -@@ -511,6 +524,10 @@ +@@ -511,6 +521,10 @@ chunk.setModified(true); } @@ -32,3 +28,12 @@ return chunk; } +@@ -813,4 +827,8 @@ + + return flag; + } ++ ++ public int getPendingSaveCount() { ++ return this.chunksToSave.size(); ++ } + } diff --git a/src/main/java/net/minecraftforge/common/DimensionManager.java b/src/main/java/net/minecraftforge/common/DimensionManager.java index 47c9fafcd6..dc790ce044 100644 --- a/src/main/java/net/minecraftforge/common/DimensionManager.java +++ b/src/main/java/net/minecraftforge/common/DimensionManager.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Stream; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -207,6 +208,11 @@ public class DimensionManager return worlds.keySet().toArray(new Integer[0]); // Only loaded dims, since usually used to cycle through loaded worlds } + public static Stream getIDStream() + { + return worlds.keySet().stream(); + } + public static void setWorld(int id, @Nullable WorldServer world, MinecraftServer server) { if (world != null) diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java deleted file mode 100644 index 659e1ecce9..0000000000 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java +++ /dev/null @@ -1,806 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fluids; - -import java.util.Map; -import java.util.Random; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockLiquid; -import net.minecraft.block.BlockStairs; -import net.minecraft.block.material.Material; -import net.minecraft.block.properties.PropertyBool; -import net.minecraft.block.properties.PropertyInteger; -import net.minecraft.block.state.BlockFaceShape; -import net.minecraft.block.state.BlockStateContainer; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.entity.Entity; -import net.minecraft.init.Blocks; -import net.minecraft.init.Items; -import net.minecraft.item.Item; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.property.ExtendedBlockState; -import net.minecraftforge.common.property.IExtendedBlockState; -import net.minecraftforge.common.property.IUnlistedProperty; -import net.minecraftforge.common.property.Properties; -import net.minecraftforge.common.property.PropertyFloat; -import net.minecraftforge.api.distmarker.Dist; - -/** - * This is a base implementation for Fluid blocks. - * - * It is highly recommended that you extend this class or one of the Forge-provided child classes. - * - */ -public abstract class BlockFluidBase extends Block implements IFluidBlock -{ - protected final static Map defaultDisplacements = Maps.newHashMap(); - - static - { - defaultDisplacements.put(Blocks.OAK_DOOR, false); - defaultDisplacements.put(Blocks.SPRUCE_DOOR, false); - defaultDisplacements.put(Blocks.BIRCH_DOOR, false); - defaultDisplacements.put(Blocks.JUNGLE_DOOR, false); - defaultDisplacements.put(Blocks.ACACIA_DOOR, false); - defaultDisplacements.put(Blocks.DARK_OAK_DOOR, false); - defaultDisplacements.put(Blocks.TRAPDOOR, false); - defaultDisplacements.put(Blocks.IRON_TRAPDOOR, false); - defaultDisplacements.put(Blocks.OAK_FENCE, false); - defaultDisplacements.put(Blocks.SPRUCE_FENCE, false); - defaultDisplacements.put(Blocks.BIRCH_FENCE, false); - defaultDisplacements.put(Blocks.JUNGLE_FENCE, false); - defaultDisplacements.put(Blocks.DARK_OAK_FENCE, false); - defaultDisplacements.put(Blocks.ACACIA_FENCE, false); - defaultDisplacements.put(Blocks.NETHER_BRICK_FENCE, false); - defaultDisplacements.put(Blocks.OAK_FENCE_GATE, false); - defaultDisplacements.put(Blocks.SPRUCE_FENCE_GATE, false); - defaultDisplacements.put(Blocks.BIRCH_FENCE_GATE, false); - defaultDisplacements.put(Blocks.JUNGLE_FENCE_GATE, false); - defaultDisplacements.put(Blocks.DARK_OAK_FENCE_GATE, false); - defaultDisplacements.put(Blocks.ACACIA_FENCE_GATE, false); - defaultDisplacements.put(Blocks.WOODEN_PRESSURE_PLATE, false); - defaultDisplacements.put(Blocks.STONE_PRESSURE_PLATE, false); - defaultDisplacements.put(Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE, false); - defaultDisplacements.put(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE, false); - defaultDisplacements.put(Blocks.LADDER, false); - defaultDisplacements.put(Blocks.IRON_BARS, false); - defaultDisplacements.put(Blocks.GLASS_PANE, false); - defaultDisplacements.put(Blocks.STAINED_GLASS_PANE, false); - defaultDisplacements.put(Blocks.PORTAL, false); - defaultDisplacements.put(Blocks.END_PORTAL, false); - defaultDisplacements.put(Blocks.COBBLESTONE_WALL, false); - defaultDisplacements.put(Blocks.BARRIER, false); - defaultDisplacements.put(Blocks.STANDING_BANNER, false); - defaultDisplacements.put(Blocks.WALL_BANNER, false); - defaultDisplacements.put(Blocks.CAKE, false); - - defaultDisplacements.put(Blocks.IRON_DOOR, false); - defaultDisplacements.put(Blocks.STANDING_SIGN, false); - defaultDisplacements.put(Blocks.WALL_SIGN, false); - defaultDisplacements.put(Blocks.REEDS, false); - } - protected Map displacements = Maps.newHashMap(); - - private static final class UnlistedPropertyBool extends Properties.PropertyAdapter - { - public UnlistedPropertyBool(String name) - { - super(PropertyBool.create(name)); - } - } - - public static final PropertyInteger LEVEL = PropertyInteger.create("level", 0, 15); - public static final PropertyFloat[] LEVEL_CORNERS = new PropertyFloat[4]; - public static final PropertyFloat FLOW_DIRECTION = new PropertyFloat("flow_direction", -1000f, 1000f); - public static final UnlistedPropertyBool[] SIDE_OVERLAYS = new UnlistedPropertyBool[4]; - public static final ImmutableList> FLUID_RENDER_PROPS; - - static - { - ImmutableList.Builder> builder = ImmutableList.builder(); - builder.add(FLOW_DIRECTION); - for(int i = 0; i < 4; i++) - { - LEVEL_CORNERS[i] = new PropertyFloat("level_corner_" + i, 0f, 1f); - builder.add(LEVEL_CORNERS[i]); - - SIDE_OVERLAYS[i] = new UnlistedPropertyBool("side_overlay_" + i); - builder.add(SIDE_OVERLAYS[i]); - } - FLUID_RENDER_PROPS = builder.build(); - } - - protected int quantaPerBlock = 8; - protected float quantaPerBlockFloat = 8F; - protected float quantaFraction = 8f / 9f; - protected int density = 1; - protected int densityDir = -1; - protected int temperature = 295; - - protected int tickRate = 20; - protected BlockRenderLayer renderLayer = BlockRenderLayer.TRANSLUCENT; - protected int maxScaledLight = 0; - - protected final String fluidName; - - /** - * This is the fluid used in the constructor. Use this reference to configure things - * like icons for your block. It might not be active in the registry, so do - * NOT expose it. - */ - protected final Fluid definedFluid; - - public BlockFluidBase(Fluid fluid, Material material) - { - super(material); - this.setTickRandomly(true); - this.disableStats(); - - this.fluidName = fluid.getName(); - this.density = fluid.density; - this.temperature = fluid.temperature; - this.maxScaledLight = fluid.luminosity; - this.tickRate = fluid.viscosity / 200; - this.densityDir = fluid.density > 0 ? -1 : 1; - fluid.setBlock(this); - - this.definedFluid = fluid; - displacements.putAll(defaultDisplacements); - this.setDefaultState(blockState.getBaseState().withProperty(LEVEL, getMaxRenderHeightMeta())); - } - - @Override - @Nonnull - protected BlockStateContainer createBlockState() - { - return new BlockStateContainer.Builder(this) - .add(LEVEL) - .add(FLUID_RENDER_PROPS.toArray(new IUnlistedProperty[0])) - .build(); - } - - @Override - public int getMetaFromState(@Nonnull IBlockState state) - { - return state.getValue(LEVEL); - } - @Override - @Deprecated - @Nonnull - public IBlockState getStateFromMeta(int meta) - { - return this.getDefaultState().withProperty(LEVEL, meta); - } - - public BlockFluidBase setQuantaPerBlock(int quantaPerBlock) - { - if (quantaPerBlock > 16 || quantaPerBlock < 1) quantaPerBlock = 8; - this.quantaPerBlock = quantaPerBlock; - this.quantaPerBlockFloat = quantaPerBlock; - this.quantaFraction = quantaPerBlock / (quantaPerBlock + 1f); - return this; - } - - public BlockFluidBase setDensity(int density) - { - if (density == 0) density = 1; - this.density = density; - this.densityDir = density > 0 ? -1 : 1; - return this; - } - - public BlockFluidBase setTemperature(int temperature) - { - this.temperature = temperature; - return this; - } - - public BlockFluidBase setTickRate(int tickRate) - { - if (tickRate <= 0) tickRate = 20; - this.tickRate = tickRate; - return this; - } - - public BlockFluidBase setRenderLayer(BlockRenderLayer renderLayer) - { - this.renderLayer = renderLayer; - return this; - } - - public BlockFluidBase setMaxScaledLight(int maxScaledLight) - { - this.maxScaledLight = maxScaledLight; - return this; - } - - public final int getDensity() - { - return density; - } - - public final int getTemperature() - { - return temperature; - } - - /** - * Returns true if the block at (pos) is displaceable. Does not displace the block. - */ - public boolean canDisplace(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - - if (block.isAir(state, world, pos)) - { - return true; - } - - if (block == this) - { - return false; - } - - if (displacements.containsKey(block)) - { - return displacements.get(block); - } - - Material material = state.getMaterial(); - if (material.blocksMovement() || material == Material.PORTAL || material == Material.STRUCTURE_VOID) - { - return false; - } - - int density = getDensity(world, pos); - if (density == Integer.MAX_VALUE) - { - return true; - } - - return this.density > density; - } - - /** - * Attempt to displace the block at (pos), return true if it was displaced. - */ - public boolean displaceIfPossible(World world, BlockPos pos) - { - boolean canDisplace = canDisplace(world, pos); - if (canDisplace) - { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - - if (!block.isAir(state, world, pos) && !isFluid(state)) - { - // Forge: Vanilla has a 'bug' where snowballs don't drop like every other block. So special case because ewww... - if (block != Blocks.SNOW_LAYER) block.dropBlockAsItem(world, pos, state, 0); - } - } - return canDisplace; - } - - public abstract int getQuantaValue(IBlockAccess world, BlockPos pos); - - @Override - public abstract boolean canCollideCheck(@Nonnull IBlockState state, boolean fullHit); - - public abstract int getMaxRenderHeightMeta(); - - /* BLOCK FUNCTIONS */ - @Override - public void onBlockAdded(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state) - { - world.scheduleUpdate(pos, this, tickRate); - } - - @Override - public void neighborChanged(@Nonnull IBlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Block neighborBlock, @Nonnull BlockPos neighbourPos) - { - world.scheduleUpdate(pos, this, tickRate); - } - - // Used to prevent updates on chunk generation - @Override - public boolean requiresUpdates() - { - return false; - } - - @Override - public boolean isPassable(@Nonnull IBlockAccess world, @Nonnull BlockPos pos) - { - return true; - } - - @Override - @Nonnull - public Item getItemDropped(@Nonnull IBlockState state, @Nonnull Random rand, int fortune) - { - return Items.AIR; - } - - @Override - public int quantityDropped(@Nonnull Random par1Random) - { - return 0; - } - - @Override - public int tickRate(@Nonnull World world) - { - return tickRate; - } - - @Override - @Nonnull - public Vec3d modifyAcceleration(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Entity entity, @Nonnull Vec3d vec) - { - return densityDir > 0 ? vec : vec.add(getFlowVector(world, pos)); - } - - @Override - public int getLightValue(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) - { - if (maxScaledLight == 0) - { - return super.getLightValue(state, world, pos); - } - return (int) (getQuantaPercentage(world, pos) * maxScaledLight); - } - - @Override - public boolean isOpaqueCube(@Nonnull IBlockState state) - { - return false; - } - - @Override - public boolean isFullCube(@Nonnull IBlockState state) - { - return false; - } - - @Override - public int getPackedLightmapCoords(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) - { - int lightThis = world.getCombinedLight(pos, 0); - int lightUp = world.getCombinedLight(pos.up(), 0); - int lightThisBase = lightThis & 255; - int lightUpBase = lightUp & 255; - int lightThisExt = lightThis >> 16 & 255; - int lightUpExt = lightUp >> 16 & 255; - return (lightThisBase > lightUpBase ? lightThisBase : lightUpBase) | - ((lightThisExt > lightUpExt ? lightThisExt : lightUpExt) << 16); - } - - @Override - @OnlyIn(Dist.CLIENT) - @Nonnull - public BlockRenderLayer getBlockLayer() - { - return this.renderLayer; - } - - @Override - @Nonnull - public BlockFaceShape getBlockFaceShape(@Nonnull IBlockAccess worldIn, @Nonnull IBlockState state, @Nonnull BlockPos pos, @Nonnull EnumFacing face) - { - return BlockFaceShape.UNDEFINED; - } - - @Override - public boolean shouldSideBeRendered(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos, @Nonnull EnumFacing side) - { - IBlockState neighbor = world.getBlockState(pos.offset(side)); - if (neighbor.getMaterial() == state.getMaterial()) - { - return false; - } - if (side == (densityDir < 0 ? EnumFacing.UP : EnumFacing.DOWN)) - { - return true; - } - return super.shouldSideBeRendered(state, world, pos, side); - } - - private static boolean isFluid(@Nonnull IBlockState blockstate) - { - return blockstate.getMaterial().isLiquid() || blockstate.getBlock() instanceof IFluidBlock; - } - - @Override - @Nonnull - public IBlockState getExtendedState(@Nonnull IBlockState oldState, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) - { - IExtendedBlockState state = (IExtendedBlockState)oldState; - state = state.withProperty(FLOW_DIRECTION, (float)getFlowDirection(world, pos)); - IBlockState[][] upBlockState = new IBlockState[3][3]; - float[][] height = new float[3][3]; - float[][] corner = new float[2][2]; - upBlockState[1][1] = world.getBlockState(pos.down(densityDir)); - height[1][1] = getFluidHeightForRender(world, pos, upBlockState[1][1]); - if (height[1][1] == 1) - { - for (int i = 0; i < 2; i++) - { - for (int j = 0; j < 2; j++) - { - corner[i][j] = 1; - } - } - } - else - { - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - { - if (i != 1 || j != 1) - { - upBlockState[i][j] = world.getBlockState(pos.add(i - 1, 0, j - 1).down(densityDir)); - height[i][j] = getFluidHeightForRender(world, pos.add(i - 1, 0, j - 1), upBlockState[i][j]); - } - } - } - for (int i = 0; i < 2; i++) - { - for (int j = 0; j < 2; j++) - { - corner[i][j] = getFluidHeightAverage(height[i][j], height[i][j + 1], height[i + 1][j], height[i + 1][j + 1]); - } - } - //check for downflow above corners - boolean n = isFluid(upBlockState[0][1]); - boolean s = isFluid(upBlockState[2][1]); - boolean w = isFluid(upBlockState[1][0]); - boolean e = isFluid(upBlockState[1][2]); - boolean nw = isFluid(upBlockState[0][0]); - boolean ne = isFluid(upBlockState[0][2]); - boolean sw = isFluid(upBlockState[2][0]); - boolean se = isFluid(upBlockState[2][2]); - if (nw || n || w) - { - corner[0][0] = 1; - } - if (ne || n || e) - { - corner[0][1] = 1; - } - if (sw || s || w) - { - corner[1][0] = 1; - } - if (se || s || e) - { - corner[1][1] = 1; - } - } - - for (int i = 0; i < 4; i++) - { - EnumFacing side = EnumFacing.getHorizontal(i); - BlockPos offset = pos.offset(side); - boolean useOverlay = world.getBlockState(offset).getBlockFaceShape(world, offset, side.getOpposite()) == BlockFaceShape.SOLID; - state = state.withProperty(SIDE_OVERLAYS[i], useOverlay); - } - - state = state.withProperty(LEVEL_CORNERS[0], corner[0][0]); - state = state.withProperty(LEVEL_CORNERS[1], corner[0][1]); - state = state.withProperty(LEVEL_CORNERS[2], corner[1][1]); - state = state.withProperty(LEVEL_CORNERS[3], corner[1][0]); - return state; - } - - /* FLUID FUNCTIONS */ - public static int getDensity(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - - if (block instanceof BlockFluidBase) - { - return ((BlockFluidBase)block).getDensity(); - } - - Fluid fluid = getFluid(state); - if (fluid != null) - { - return fluid.getDensity(); - } - return Integer.MAX_VALUE; - } - - public static int getTemperature(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - - if (block instanceof BlockFluidBase) - { - return ((BlockFluidBase)block).getTemperature(); - } - - Fluid fluid = getFluid(state); - if (fluid != null) - { - return fluid.getTemperature(); - } - return Integer.MAX_VALUE; - } - - @Nullable - private static Fluid getFluid(IBlockState state) - { - Block block = state.getBlock(); - - if (block instanceof IFluidBlock) - { - return ((IFluidBlock)block).getFluid(); - } - if (block instanceof BlockLiquid) - { - if (state.getMaterial() == Material.WATER) - { - return FluidRegistry.WATER; - } - if (state.getMaterial() == Material.LAVA) - { - return FluidRegistry.LAVA; - } - } - return null; - } - - public static double getFlowDirection(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - if (!state.getMaterial().isLiquid()) - { - return -1000.0; - } - Vec3d vec = ((BlockFluidBase)state.getBlock()).getFlowVector(world, pos); - return vec.x == 0.0D && vec.z == 0.0D ? -1000.0D : MathHelper.atan2(vec.z, vec.x) - Math.PI / 2D; - } - - public final int getQuantaValueBelow(IBlockAccess world, BlockPos pos, int belowThis) - { - int quantaRemaining = getQuantaValue(world, pos); - if (quantaRemaining >= belowThis) - { - return -1; - } - return quantaRemaining; - } - - public final int getQuantaValueAbove(IBlockAccess world, BlockPos pos, int aboveThis) - { - int quantaRemaining = getQuantaValue(world, pos); - if (quantaRemaining <= aboveThis) - { - return -1; - } - return quantaRemaining; - } - - public final float getQuantaPercentage(IBlockAccess world, BlockPos pos) - { - int quantaRemaining = getQuantaValue(world, pos); - return quantaRemaining / quantaPerBlockFloat; - } - - public float getFluidHeightAverage(float... flow) - { - float total = 0; - int count = 0; - - for (int i = 0; i < flow.length; i++) - { - if (flow[i] >= quantaFraction) - { - total += flow[i] * 10; - count += 10; - } - - if (flow[i] >= 0) - { - total += flow[i]; - count++; - } - } - - return total / count; - } - - public float getFluidHeightForRender(IBlockAccess world, BlockPos pos, @Nonnull IBlockState up) - { - IBlockState here = world.getBlockState(pos); - if (here.getBlock() == this) - { - if (isFluid(up)) - { - return 1; - } - - if (getMetaFromState(here) == getMaxRenderHeightMeta()) - { - return quantaFraction; - } - } - if (here.getBlock() instanceof BlockLiquid) - { - return Math.min(1 - BlockLiquid.getLiquidHeightPercent(here.getValue(BlockLiquid.LEVEL)), quantaFraction); - } - return !here.getMaterial().isSolid() && up.getBlock() == this ? 1 : this.getQuantaPercentage(world, pos) * quantaFraction; - } - - public Vec3d getFlowVector(IBlockAccess world, BlockPos pos) - { - Vec3d vec = new Vec3d(0.0D, 0.0D, 0.0D); - int decay = getFlowDecay(world, pos); - - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - BlockPos offset = pos.offset(side); - int otherDecay = getFlowDecay(world, offset); - if (otherDecay >= quantaPerBlock) - { - if (!world.getBlockState(offset).getMaterial().blocksMovement()) - { - otherDecay = getFlowDecay(world, offset.up(densityDir)); - if (otherDecay < quantaPerBlock) - { - int power = otherDecay - (decay - quantaPerBlock); - vec = vec.addVector(side.getFrontOffsetX() * power, 0, side.getFrontOffsetZ() * power); - } - } - } - else - { - int power = otherDecay - decay; - vec = vec.addVector(side.getFrontOffsetX() * power, 0, side.getFrontOffsetZ() * power); - } - } - - if (hasVerticalFlow(world, pos)) - { - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - BlockPos offset = pos.offset(side); - if (causesDownwardCurrent(world, offset, side) || causesDownwardCurrent(world, offset.down(densityDir), side)) - { - vec = vec.normalize().addVector(0.0, 6.0 * densityDir, 0.0); - break; - } - } - } - - return vec.normalize(); - } - - private int getFlowDecay(IBlockAccess world, BlockPos pos) - { - int quantaValue = getQuantaValue(world, pos); - return quantaValue > 0 && hasVerticalFlow(world, pos) ? 0 : quantaPerBlock - quantaValue; - } - - private boolean hasVerticalFlow(IBlockAccess world, BlockPos pos) - { - return world.getBlockState(pos.down(densityDir)).getBlock() == this; - } - - protected boolean causesDownwardCurrent(IBlockAccess world, BlockPos pos, EnumFacing face) - { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - - if (block == this) return false; - if (face == (densityDir < 0 ? EnumFacing.UP : EnumFacing.DOWN)) return true; - if (state.getMaterial() == Material.ICE) return false; - - boolean flag = isExceptBlockForAttachWithPiston(block) || block instanceof BlockStairs; - return !flag && state.getBlockFaceShape(world, pos, face) == BlockFaceShape.SOLID; - } - - /* IFluidBlock */ - @Override - public Fluid getFluid() - { - return FluidRegistry.getFluid(fluidName); - } - - @Override - public float getFilledPercentage(World world, BlockPos pos) - { - return getFilledPercentage((IBlockAccess) world, pos); - } - - public float getFilledPercentage(IBlockAccess world, BlockPos pos) - { - int quantaRemaining = getQuantaValue(world, pos); - float remaining = (quantaRemaining + 1f) / (quantaPerBlockFloat + 1f); - return remaining * (density > 0 ? 1 : -1); - } - - @Override - public AxisAlignedBB getCollisionBoundingBox(@Nonnull IBlockState blockState, @Nonnull IBlockAccess worldIn, @Nonnull BlockPos pos) - { - return NULL_AABB; - } - - @Override - @OnlyIn(Dist.CLIENT) - public Vec3d getFogColor(World world, BlockPos pos, IBlockState state, Entity entity, Vec3d originalColor, float partialTicks) - { - if (!isWithinFluid(world, pos, ActiveRenderInfo.projectViewFromEntity(entity, partialTicks))) - { - BlockPos otherPos = pos.down(densityDir); - IBlockState otherState = world.getBlockState(otherPos); - return otherState.getBlock().getFogColor(world, otherPos, otherState, entity, originalColor, partialTicks); - } - - if (getFluid() != null) - { - int color = getFluid().getColor(); - float red = (color >> 16 & 0xFF) / 255.0F; - float green = (color >> 8 & 0xFF) / 255.0F; - float blue = (color & 0xFF) / 255.0F; - return new Vec3d(red, green, blue); - } - - return super.getFogColor(world, pos, state, entity, originalColor, partialTicks); - } - - @Override - public IBlockState getStateAtViewpoint(IBlockState state, IBlockAccess world, BlockPos pos, Vec3d viewpoint) - { - if (!isWithinFluid(world, pos, viewpoint)) - { - return world.getBlockState(pos.down(densityDir)); - } - - return super.getStateAtViewpoint(state, world, pos, viewpoint); - } - - private boolean isWithinFluid(IBlockAccess world, BlockPos pos, Vec3d vec) - { - float filled = getFilledPercentage(world, pos); - return filled < 0 ? vec.y > pos.getY() + filled + 1 - : vec.y < pos.getY() + filled; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidClassic.java b/src/main/java/net/minecraftforge/fluids/BlockFluidClassic.java deleted file mode 100644 index 75cab406cc..0000000000 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidClassic.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fluids; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -import com.google.common.primitives.Ints; - -import net.minecraft.block.material.Material; -import net.minecraft.block.state.IBlockState; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.event.ForgeEventFactory; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * This is a fluid block implementation which emulates vanilla Minecraft fluid behavior. - * - * It is highly recommended that you use/extend this class for "classic" fluid blocks. - * - */ -public class BlockFluidClassic extends BlockFluidBase -{ - protected static final List SIDES = Collections.unmodifiableList(Arrays.asList( - EnumFacing.WEST, EnumFacing.EAST, EnumFacing.NORTH, EnumFacing.SOUTH)); - - protected boolean[] isOptimalFlowDirection = new boolean[4]; - protected int[] flowCost = new int[4]; - - protected boolean canCreateSources = false; - - protected FluidStack stack; - - public BlockFluidClassic(Fluid fluid, Material material) - { - super(fluid, material); - stack = new FluidStack(fluid, Fluid.BUCKET_VOLUME); - } - - public BlockFluidClassic setFluidStack(FluidStack stack) - { - this.stack = stack; - return this; - } - - public BlockFluidClassic setFluidStackAmount(int amount) - { - this.stack.amount = amount; - return this; - } - - @Override - public int getQuantaValue(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - if (state.getBlock().isAir(state, world, pos)) - { - return 0; - } - - if (state.getBlock() != this) - { - return -1; - } - - return quantaPerBlock - state.getValue(LEVEL); - } - - @Override - public boolean canCollideCheck(@Nonnull IBlockState state, boolean fullHit) - { - return fullHit && state.getValue(LEVEL) == 0; - } - - @Override - public int getMaxRenderHeightMeta() - { - return 0; - } - - @Override - public void updateTick(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Random rand) - { - int quantaRemaining = quantaPerBlock - state.getValue(LEVEL); - int expQuanta = -101; - - // check adjacent block levels if non-source - if (quantaRemaining < quantaPerBlock) - { - int adjacentSourceBlocks = 0; - - if (ForgeEventFactory.canCreateFluidSource(world, pos, state, canCreateSources)) - { - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - if (isSourceBlock(world, pos.offset(side))) adjacentSourceBlocks++; - } - } - - // new source block - if (adjacentSourceBlocks >= 2 && (world.getBlockState(pos.up(densityDir)).getMaterial().isSolid() || isSourceBlock(world, pos.up(densityDir)))) - { - expQuanta = quantaPerBlock; - } - // unobstructed flow from 'above' - else if (world.getBlockState(pos.down(densityDir)).getBlock() == this - || hasDownhillFlow(world, pos, EnumFacing.EAST) - || hasDownhillFlow(world, pos, EnumFacing.WEST) - || hasDownhillFlow(world, pos, EnumFacing.NORTH) - || hasDownhillFlow(world, pos, EnumFacing.SOUTH)) - { - expQuanta = quantaPerBlock - 1; - } - else - { - int maxQuanta = -100; - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - maxQuanta = getLargerQuanta(world, pos.offset(side), maxQuanta); - } - expQuanta = maxQuanta - 1; - } - - // decay calculation - if (expQuanta != quantaRemaining) - { - quantaRemaining = expQuanta; - - if (expQuanta <= 0) - { - world.setBlockToAir(pos); - } - else - { - world.setBlockState(pos, state.withProperty(LEVEL, quantaPerBlock - expQuanta), 2); - world.scheduleUpdate(pos, this, tickRate); - world.notifyNeighborsOfStateChange(pos, this, false); - } - } - } - - // Flow vertically if possible - if (canDisplace(world, pos.up(densityDir))) - { - flowIntoBlock(world, pos.up(densityDir), 1); - return; - } - - // Flow outward if possible - int flowMeta = quantaPerBlock - quantaRemaining + 1; - if (flowMeta >= quantaPerBlock) - { - return; - } - - if (isSourceBlock(world, pos) || !isFlowingVertically(world, pos)) - { - if (world.getBlockState(pos.down(densityDir)).getBlock() == this) - { - flowMeta = 1; - } - boolean flowTo[] = getOptimalFlowDirections(world, pos); - for (int i = 0; i < 4; i++) - { - if (flowTo[i]) flowIntoBlock(world, pos.offset(SIDES.get(i)), flowMeta); - } - } - } - - protected final boolean hasDownhillFlow(IBlockAccess world, BlockPos pos, EnumFacing direction) - { - return world.getBlockState(pos.offset(direction).down(densityDir)).getBlock() == this - && (canFlowInto(world, pos.offset(direction)) - || canFlowInto(world, pos.down(densityDir))); - } - - public boolean isFlowingVertically(IBlockAccess world, BlockPos pos) - { - return world.getBlockState(pos.up(densityDir)).getBlock() == this || - (world.getBlockState(pos).getBlock() == this && canFlowInto(world, pos.up(densityDir))); - } - - public boolean isSourceBlock(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - return state.getBlock() == this && state.getValue(LEVEL) == 0; - } - - protected boolean[] getOptimalFlowDirections(World world, BlockPos pos) - { - for (int side = 0; side < 4; side++) - { - flowCost[side] = 1000; - - BlockPos pos2 = pos.offset(SIDES.get(side)); - - if (!canFlowInto(world, pos2) || isSourceBlock(world, pos2)) - { - continue; - } - - if (canFlowInto(world, pos2.up(densityDir))) - { - flowCost[side] = 0; - } - else - { - flowCost[side] = calculateFlowCost(world, pos2, 1, side); - } - } - - int min = Ints.min(flowCost); - for (int side = 0; side < 4; side++) - { - isOptimalFlowDirection[side] = flowCost[side] == min; - } - return isOptimalFlowDirection; - } - - protected int calculateFlowCost(World world, BlockPos pos, int recurseDepth, int side) - { - int cost = 1000; - for (int adjSide = 0; adjSide < 4; adjSide++) - { - if (SIDES.get(adjSide) == SIDES.get(side).getOpposite()) - { - continue; - } - - BlockPos pos2 = pos.offset(SIDES.get(adjSide)); - - if (!canFlowInto(world, pos2) || isSourceBlock(world, pos2)) - { - continue; - } - - if (canFlowInto(world, pos2.up(densityDir))) - { - return recurseDepth; - } - - if (recurseDepth >= quantaPerBlock / 2) - { - continue; - } - - cost = Math.min(cost, calculateFlowCost(world, pos2, recurseDepth + 1, adjSide)); - } - return cost; - } - - protected void flowIntoBlock(World world, BlockPos pos, int meta) - { - if (meta < 0) return; - if (displaceIfPossible(world, pos)) - { - world.setBlockState(pos, this.getDefaultState().withProperty(LEVEL, meta), 3); - } - } - - protected boolean canFlowInto(IBlockAccess world, BlockPos pos) - { - return world.getBlockState(pos).getBlock() == this || canDisplace(world, pos); - } - - protected int getLargerQuanta(IBlockAccess world, BlockPos pos, int compare) - { - int quantaRemaining = getQuantaValue(world, pos); - if (quantaRemaining <= 0) - { - return compare; - } - return quantaRemaining >= compare ? quantaRemaining : compare; - } - - /* IFluidBlock */ - @Override - public int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace) - { - if (fluidStack.amount < Fluid.BUCKET_VOLUME) - { - return 0; - } - if (doPlace) - { - FluidUtil.destroyBlockOnFluidPlacement(world, pos); - world.setBlockState(pos, this.getDefaultState(), 11); - } - return Fluid.BUCKET_VOLUME; - } - - @Override - @Nullable - public FluidStack drain(World world, BlockPos pos, boolean doDrain) - { - if (!isSourceBlock(world, pos)) - { - return null; - } - - if (doDrain) - { - world.setBlockToAir(pos); - } - - return stack.copy(); - } - - @Override - public boolean canDrain(World world, BlockPos pos) - { - return isSourceBlock(world, pos); - } -} diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidFinite.java b/src/main/java/net/minecraftforge/fluids/BlockFluidFinite.java deleted file mode 100644 index 6bd46026e1..0000000000 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidFinite.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fluids; - -import java.util.Random; - -import net.minecraft.block.material.Material; -import net.minecraft.block.state.IBlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.EnumFacing; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -/** - * This is a cellular-automata based finite fluid block implementation. - * - * It is highly recommended that you use/extend this class for finite fluid blocks. - * - */ -public class BlockFluidFinite extends BlockFluidBase -{ - public BlockFluidFinite(Fluid fluid, Material material) - { - super(fluid, material); - } - - @Override - public int getQuantaValue(IBlockAccess world, BlockPos pos) - { - IBlockState state = world.getBlockState(pos); - if (state.getBlock().isAir(state, world, pos)) - { - return 0; - } - - if (state.getBlock() != this) - { - return -1; - } - return state.getValue(LEVEL) + 1; - } - - @Override - public boolean canCollideCheck(@Nonnull IBlockState state, boolean fullHit) - { - return fullHit; - } - - @Override - public int getMaxRenderHeightMeta() - { - return quantaPerBlock - 1; - } - - @Override - public void updateTick(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Random rand) - { - boolean changed = false; - int quantaRemaining = state.getValue(LEVEL) + 1; - - // Flow vertically if possible - int prevRemaining = quantaRemaining; - quantaRemaining = tryToFlowVerticallyInto(world, pos, quantaRemaining); - - if (quantaRemaining < 1) - { - return; - } - else if (quantaRemaining != prevRemaining) - { - changed = true; - if (quantaRemaining == 1) - { - world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2); - return; - } - } - else if (quantaRemaining == 1) - { - return; - } - - // Flow out if possible - int lowerThan = quantaRemaining - 1; - int total = quantaRemaining; - int count = 1; - - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - BlockPos off = pos.offset(side); - if (displaceIfPossible(world, off)) - world.setBlockToAir(off); - - int quanta = getQuantaValueBelow(world, off, lowerThan); - if (quanta >= 0) - { - count++; - total += quanta; - } - } - - if (count == 1) - { - if (changed) - { - world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2); - } - return; - } - - int each = total / count; - int rem = total % count; - - for (EnumFacing side : EnumFacing.Plane.HORIZONTAL) - { - BlockPos off = pos.offset(side); - int quanta = getQuantaValueBelow(world, off, lowerThan); - if (quanta >= 0) - { - int newQuanta = each; - if (rem == count || rem > 1 && rand.nextInt(count - rem) != 0) - { - ++newQuanta; - --rem; - } - - if (newQuanta != quanta) - { - if (newQuanta == 0) - { - world.setBlockToAir(off); - } - else - { - world.setBlockState(off, getDefaultState().withProperty(LEVEL, newQuanta - 1), 2); - } - world.scheduleUpdate(off, this, tickRate); - } - --count; - } - } - - if (rem > 0) - { - ++each; - } - world.setBlockState(pos, state.withProperty(LEVEL, each - 1), 2); - } - - public int tryToFlowVerticallyInto(World world, BlockPos pos, int amtToInput) - { - IBlockState myState = world.getBlockState(pos); - BlockPos other = pos.add(0, densityDir, 0); - if (other.getY() < 0 || other.getY() >= world.getHeight()) - { - world.setBlockToAir(pos); - return 0; - } - - int amt = getQuantaValueBelow(world, other, quantaPerBlock); - if (amt >= 0) - { - amt += amtToInput; - if (amt > quantaPerBlock) - { - world.setBlockState(other, myState.withProperty(LEVEL, quantaPerBlock - 1), 3); - world.scheduleUpdate(other, this, tickRate); - return amt - quantaPerBlock; - } - else if (amt > 0) - { - world.setBlockState(other, myState.withProperty(LEVEL, amt - 1), 3); - world.scheduleUpdate(other, this, tickRate); - world.setBlockToAir(pos); - return 0; - } - return amtToInput; - } - else - { - int density_other = getDensity(world, other); - if (density_other == Integer.MAX_VALUE) - { - if (displaceIfPossible(world, other)) - { - world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3); - world.scheduleUpdate(other, this, tickRate); - world.setBlockToAir(pos); - return 0; - } - else - { - return amtToInput; - } - } - - if (densityDir < 0) - { - if (density_other < density) // then swap - { - IBlockState state = world.getBlockState(other); - world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3); - world.setBlockState(pos, state, 3); - world.scheduleUpdate(other, this, tickRate); - world.scheduleUpdate(pos, state.getBlock(), state.getBlock().tickRate(world)); - return 0; - } - } - else - { - if (density_other > density) - { - IBlockState state = world.getBlockState(other); - world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3); - world.setBlockState(pos, state, 3); - world.scheduleUpdate(other, this, tickRate); - world.scheduleUpdate(pos, state.getBlock(), state.getBlock().tickRate(world)); - return 0; - } - } - return amtToInput; - } - } - - /* IFluidBlock */ - @Override - public int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace) - { - IBlockState existing = world.getBlockState(pos); - float quantaAmount = Fluid.BUCKET_VOLUME / quantaPerBlockFloat; - // If the stack contains more available fluid than the full source block, - // set a source block - int closest = Fluid.BUCKET_VOLUME; - int quanta = quantaPerBlock; - if (fluidStack.amount < closest) - { - // Figure out maximum level to match stack amount - closest = MathHelper.floor(quantaAmount * MathHelper.floor(fluidStack.amount / quantaAmount)); - quanta = MathHelper.floor(closest / quantaAmount); - } - if (existing.getBlock() == this) - { - int existingQuanta = existing.getValue(LEVEL) + 1; - int missingQuanta = quantaPerBlock - existingQuanta; - closest = Math.min(closest, MathHelper.floor(missingQuanta * quantaAmount)); - quanta = Math.min(quanta + existingQuanta, quantaPerBlock); - } - - // If too little (or too much, technically impossible) fluid is to be placed, abort - if (quanta < 1 || quanta > 16) - return 0; - - if (doPlace) - { - FluidUtil.destroyBlockOnFluidPlacement(world, pos); - world.setBlockState(pos, getDefaultState().withProperty(LEVEL, quanta - 1), 11); - } - - return closest; - } - - @Override - public FluidStack drain(World world, BlockPos pos, boolean doDrain) - { - final FluidStack fluidStack = new FluidStack(getFluid(), MathHelper.floor(getQuantaPercentage(world, pos) * Fluid.BUCKET_VOLUME)); - - if (doDrain) - { - world.setBlockToAir(pos); - } - - return fluidStack; - } - - @Override - public boolean canDrain(World world, BlockPos pos) - { - return true; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/Fluid.java b/src/main/java/net/minecraftforge/fluids/Fluid.java index 559b540142..5fc4e2ac77 100644 --- a/src/main/java/net/minecraftforge/fluids/Fluid.java +++ b/src/main/java/net/minecraftforge/fluids/Fluid.java @@ -30,11 +30,9 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.translation.I18n; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.item.EnumRarity; @@ -131,7 +129,7 @@ public class Fluid * The default value of null should remain for any Fluid without a Block implementation. */ protected Block block = null; - + /** * Color used by universal bucket and the ModelFluid baked model. * Note that this int includes the alpha so converting this to RGB with alpha would be @@ -245,13 +243,13 @@ public class Fluid this.emptySound = emptySound; return this; } - + public Fluid setColor(Color color) { this.color = color.getRGB(); return this; } - + public Fluid setColor(int color) { this.color = color; @@ -275,15 +273,10 @@ public class Fluid public final boolean isLighterThanAir() { - int density = this.density; - if (block instanceof BlockFluidBase) - { - density = ((BlockFluidBase) block).getDensity(); - } - return density <= 0; + return this.density <= 0; } - /** + /** * Determines if this fluid should vaporize in dimensions where water vaporizes when placed. * To preserve the intentions of vanilla, fluids that can turn lava into obsidian should vaporize. * This prevents players from making the nether safe with a single bucket. @@ -299,7 +292,7 @@ public class Fluid return block.getDefaultState().getMaterial() == Material.WATER; } - /** + /** * Called instead of placing the fluid block if {@link WorldProvider#doesWaterVaporize()} and {@link #doesVaporize(FluidStack)} are true. * Override this to make your explosive liquid blow up instead of the default smoke, etc. * Based on {@link net.minecraft.item.ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)} diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 773c023ea6..606274e264 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -19,39 +19,11 @@ package net.minecraftforge.fluids; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import net.minecraftforge.fml.ModThreadContext; - -import net.minecraft.block.Block; -import net.minecraft.init.Blocks; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagString; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.MinecraftForge; - -import com.google.common.base.Strings; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.registries.IRegistryDelegate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.MarkerManager; -import javax.annotation.Nullable; - /** * Handles Fluid registrations. Fluids MUST be registered in order to function. */ @@ -59,196 +31,8 @@ public abstract class FluidRegistry { private static final Logger LOGGER = LogManager.getLogger(); private static final Marker FLUIDS = MarkerManager.getMarker("FLUIDS"); - static int maxID = 0; - - static BiMap fluids = HashBiMap.create(); - static BiMap fluidIDs = HashBiMap.create(); - static BiMap fluidNames = HashBiMap.create(); //Caching this just makes some other calls faster - static BiMap fluidBlocks; - - // the globally unique fluid map - only used to associate non-defaults during world/server loading - static BiMap masterFluidReference = HashBiMap.create(); - static BiMap defaultFluidName = HashBiMap.create(); - static Map delegates = Maps.newHashMap(); static boolean universalBucketEnabled = false; - static Set bucketFluids = Sets.newHashSet(); - - public static final Fluid WATER = new Fluid("water", new ResourceLocation("blocks/water_still"), new ResourceLocation("blocks/water_flow"), new ResourceLocation("blocks/water_overlay")) { - @Override - public String getLocalizedName(FluidStack fs) { - return I18n.translateToLocal("tile.water.name"); - } - }.setBlock(Blocks.WATER).setUnlocalizedName(Blocks.WATER.getUnlocalizedName()); - - public static final Fluid LAVA = new Fluid("lava", new ResourceLocation("blocks/lava_still"), new ResourceLocation("blocks/lava_flow")) { - @Override - public String getLocalizedName(FluidStack fs) { - return I18n.translateToLocal("tile.lava.name"); - } - }.setBlock(Blocks.LAVA).setLuminosity(15).setDensity(3000).setViscosity(6000).setTemperature(1300).setUnlocalizedName(Blocks.LAVA.getUnlocalizedName()); - - static - { - registerFluid(WATER); - registerFluid(LAVA); - } - - private FluidRegistry(){} - - /** - * Called by Forge to prepare the ID map for server -> client sync. - * Modders, DO NOT call this. - */ - public static void initFluidIDs(BiMap newfluidIDs, Set defaultNames) - { - maxID = newfluidIDs.size(); - loadFluidDefaults(newfluidIDs, defaultNames); - } - - /** - * Called by forge to load default fluid IDs from the world or from server -> client for syncing - * DO NOT call this and expect useful behaviour. - * @param localFluidIDs - * @param defaultNames - */ - private static void loadFluidDefaults(BiMap localFluidIDs, Set defaultNames) - { - // If there's an empty set of default names, use the defaults as defined locally - if (defaultNames.isEmpty()) { - defaultNames.addAll(defaultFluidName.values()); - } - BiMap localFluids = HashBiMap.create(fluids); - for (String defaultName : defaultNames) - { - Fluid fluid = masterFluidReference.get(defaultName); - if (fluid == null) { - String derivedName = defaultName.split(":",2)[1]; - String localDefault = defaultFluidName.get(derivedName); - if (localDefault == null) { - LOGGER.error(FLUIDS, "The fluid {} (specified as {}) is missing from this instance - it will be removed",derivedName,defaultName); - continue; - } - fluid = masterFluidReference.get(localDefault); - LOGGER.error(FLUIDS, "The fluid {} specified as default is not present - it will be reverted to default {}",defaultName,localDefault); - } - LOGGER.debug(FLUIDS, "The fluid {} has been selected as the default fluid for {}",defaultName,fluid.getName()); - Fluid oldFluid = localFluids.put(fluid.getName(), fluid); - Integer id = localFluidIDs.remove(oldFluid); - localFluidIDs.put(fluid, id); - } - BiMap localFluidNames = HashBiMap.create(); - for (Entry e : localFluidIDs.entrySet()) { - localFluidNames.put(e.getValue(), e.getKey().getName()); - } - fluidIDs = localFluidIDs; - fluids = localFluids; - fluidNames = localFluidNames; - fluidBlocks = null; - for (FluidDelegate fd : delegates.values()) - { - fd.rebind(); - } - } - - /** - * Register a new Fluid. If a fluid with the same name already exists, registration the alternative fluid is tracked - * in case it is the default in another place - * - * @param fluid - * The fluid to register. - * @return True if the fluid was registered as the current default fluid, false if it was only registered as an alternative - */ - public static boolean registerFluid(Fluid fluid) - { - masterFluidReference.put(uniqueName(fluid), fluid); - delegates.put(fluid, new FluidDelegate(fluid, fluid.getName())); - if (fluids.containsKey(fluid.getName())) - { - return false; - } - fluids.put(fluid.getName(), fluid); - maxID++; - fluidIDs.put(fluid, maxID); - fluidNames.put(maxID, fluid.getName()); - defaultFluidName.put(fluid.getName(), uniqueName(fluid)); - - MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID)); - return true; - } - - private static String uniqueName(Fluid fluid) - { - return ModThreadContext.get().getActiveContainer().getPrefix() +":"+fluid.getName(); - } - - /** - * Is the supplied fluid the current default fluid for it's name - * @param fluid the fluid we're testing - * @return if the fluid is default - */ - public static boolean isFluidDefault(Fluid fluid) - { - return fluids.containsValue(fluid); - } - - /** - * Does the supplied fluid have an entry for it's name (whether or not the fluid itself is default) - * @param fluid the fluid we're testing - * @return if the fluid's name has a registration entry - */ - public static boolean isFluidRegistered(Fluid fluid) - { - return fluid != null && fluids.containsKey(fluid.getName()); - } - - public static boolean isFluidRegistered(String fluidName) - { - return fluids.containsKey(fluidName); - } - - public static Fluid getFluid(String fluidName) - { - return fluids.get(fluidName); - } - - public static String getFluidName(Fluid fluid) - { - return fluids.inverse().get(fluid); - } - - public static String getFluidName(FluidStack stack) - { - return getFluidName(stack.getFluid()); - } - - @Nullable - public static FluidStack getFluidStack(String fluidName, int amount) - { - if (!fluids.containsKey(fluidName)) - { - return null; - } - return new FluidStack(getFluid(fluidName), amount); - } - - /** - * Returns a read-only map containing Fluid Names and their associated Fluids. - */ - public static Map getRegisteredFluids() - { - return ImmutableMap.copyOf(fluids); - } - - /** - * Returns a read-only map containing Fluid Names and their associated IDs. - * Modders should never actually use this, use the String names. - */ - @Deprecated - public static Map getRegisteredFluidIDs() - { - return ImmutableMap.copyOf(fluidIDs); - } /** * Enables the universal bucket in forge. @@ -264,205 +48,4 @@ public abstract class FluidRegistry { return universalBucketEnabled; } - - /** - * Registers a fluid with the universal bucket. - * This only has an effect if the universal bucket is enabled. - * @param fluid The fluid that the bucket shall be able to hold - * @return True if the fluid was added successfully, false if it already was registered or couldn't be registered with the bucket. - */ - public static boolean addBucketForFluid(Fluid fluid) - { - if(fluid == null) { - return false; - } - // register unregistered fluids - if (!isFluidRegistered(fluid)) - { - registerFluid(fluid); - } - return bucketFluids.add(fluid); - } - - /** - * All fluids registered with the universal bucket - * @return An immutable set containing the fluids - */ - public static Set getBucketFluids() - { - return Collections.unmodifiableSet(bucketFluids); - } - - - public static Fluid lookupFluidForBlock(Block block) - { - if (fluidBlocks == null) - { - BiMap tmp = HashBiMap.create(); - for (Fluid fluid : fluids.values()) - { - if (fluid.canBePlacedInWorld() && fluid.getBlock() != null) - { - tmp.put(fluid.getBlock(), fluid); - } - } - fluidBlocks = tmp; - } - if (block == Blocks.FLOWING_WATER) - { - block = Blocks.WATER; - } - else if (block == Blocks.FLOWING_LAVA) - { - block = Blocks.LAVA; - } - return fluidBlocks.get(block); - } - - public static class FluidRegisterEvent extends Event - { - private final String fluidName; - private final int fluidID; - - public FluidRegisterEvent(String fluidName, int fluidID) - { - this.fluidName = fluidName; - this.fluidID = fluidID; - } - - public String getFluidName() - { - return fluidName; - } - - public int getFluidID() - { - return fluidID; - } - } - - public static int getMaxID() - { - return maxID; - } - - public static String getDefaultFluidName(Fluid key) - { - String name = masterFluidReference.inverse().get(key); - if (Strings.isNullOrEmpty(name)) { - LOGGER.error(FLUIDS, "The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken",key.getClass().getName(),key.getName()); - throw new IllegalStateException("The fluid registry is corrupted"); - } - return name; - } - - @Nullable - public static String getModId(@Nullable FluidStack fluidStack) - { - if (fluidStack != null) - { - String defaultFluidName = getDefaultFluidName(fluidStack.getFluid()); - if (defaultFluidName != null) - { - ResourceLocation fluidResourceName = new ResourceLocation(defaultFluidName); - return fluidResourceName.getResourceDomain(); - } - } - return null; - } - - public static void loadFluidDefaults(NBTTagCompound tag) - { - Set defaults = Sets.newHashSet(); - if (tag.hasKey("DefaultFluidList",9)) - { - LOGGER.debug(FLUIDS, "Loading persistent fluid defaults from world"); - NBTTagList tl = tag.getTagList("DefaultFluidList", 8); - for (int i = 0; i < tl.tagCount(); i++) - { - defaults.add(tl.getStringTagAt(i)); - } - } - else - { - LOGGER.debug(FLUIDS,"World is missing persistent fluid defaults - using local defaults"); - } - loadFluidDefaults(HashBiMap.create(fluidIDs), defaults); - } - - public static void writeDefaultFluidList(NBTTagCompound forgeData) - { - NBTTagList tagList = new NBTTagList(); - - for (Entry def : fluids.entrySet()) - { - tagList.appendTag(new NBTTagString(getDefaultFluidName(def.getValue()))); - } - - forgeData.setTag("DefaultFluidList", tagList); - } - - public static void validateFluidRegistry() - { - Set illegalFluids = Sets.newHashSet(); - for (Fluid f : fluids.values()) - { - if (!masterFluidReference.containsValue(f)) - { - illegalFluids.add(f); - } - } - - if (!illegalFluids.isEmpty()) - { - LOGGER.fatal(FLUIDS, "The fluid registry is corrupted. Something has inserted a fluid without registering it"); - LOGGER.fatal(FLUIDS, "There is {} unregistered fluids",illegalFluids.size()); - for (Fluid f: illegalFluids) - { - LOGGER.fatal(FLUIDS, " Fluid name : {}, type: {}",f.getName(),f.getClass().getName()); - } - LOGGER.fatal(FLUIDS, "The mods that own these fluids need to register them properly"); - throw new IllegalStateException("The fluid map contains fluids unknown to the master fluid registry"); - } - } - - static IRegistryDelegate makeDelegate(Fluid fl) - { - return delegates.get(fl); - } - - - private static class FluidDelegate implements IRegistryDelegate - { - private String name; - private Fluid fluid; - - FluidDelegate(Fluid fluid, String name) - { - this.fluid = fluid; - this.name = name; - } - - @Override - public Fluid get() - { - return fluid; - } - - @Override - public ResourceLocation name() { - return new ResourceLocation(name); - } - - @Override - public Class type() - { - return Fluid.class; - } - - void rebind() - { - fluid = fluids.get(name); - } - } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidUtil.java b/src/main/java/net/minecraftforge/fluids/FluidUtil.java index 608c999550..6053c549dd 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidUtil.java +++ b/src/main/java/net/minecraftforge/fluids/FluidUtil.java @@ -43,7 +43,6 @@ import net.minecraftforge.common.capabilities.OptionalCapabilityInstance; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.fluids.capability.wrappers.BlockLiquidWrapper; import net.minecraftforge.fluids.capability.wrappers.BlockWrapper; import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper; import net.minecraftforge.items.CapabilityItemHandler; diff --git a/src/main/java/net/minecraftforge/registries/ForgeRegistries.java b/src/main/java/net/minecraftforge/registries/ForgeRegistries.java index 4718a50e5d..d9f2e2295b 100644 --- a/src/main/java/net/minecraftforge/registries/ForgeRegistries.java +++ b/src/main/java/net/minecraftforge/registries/ForgeRegistries.java @@ -21,13 +21,13 @@ package net.minecraftforge.registries; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.init.Bootstrap; import net.minecraft.item.Item; import net.minecraft.item.crafting.IRecipe; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionType; +import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.SoundEvent; import net.minecraft.world.biome.Biome; import net.minecraftforge.fml.common.registry.GameRegistry; @@ -39,6 +39,7 @@ import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfessio * Created to have a central place to access the registries directly if modders need. * It is still advised that if you are registering things to go through {@link GameRegistry} register methods, but queries and iterations can use this. */ +@SuppressWarnings("unchecked") public class ForgeRegistries { static { init(); } // This must be above the fields so we guarantee it's run before findRegistry is called. Yay static inializers @@ -52,6 +53,7 @@ public class ForgeRegistries public static final IForgeRegistry ENCHANTMENTS = RegistryManager.ACTIVE.getRegistry(Enchantment.class); public static final IForgeRegistry VILLAGER_PROFESSIONS = RegistryManager.ACTIVE.getRegistry(VillagerProfession.class); public static final IForgeRegistry> ENTITIES = RegistryManager.ACTIVE.getRegistry(EntityType.class); + public static final IForgeRegistry> TILE_ENTITIES = RegistryManager.ACTIVE.getRegistry(TileEntityType.class); public static final IForgeRegistry RECIPES = RegistryManager.ACTIVE.getRegistry(IRecipe.class); /** diff --git a/src/main/java/net/minecraftforge/registries/GameData.java b/src/main/java/net/minecraftforge/registries/GameData.java index f501bed6cc..1f231a1804 100644 --- a/src/main/java/net/minecraftforge/registries/GameData.java +++ b/src/main/java/net/minecraftforge/registries/GameData.java @@ -33,6 +33,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionType; +import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.ObjectIntIdentityMap; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; @@ -87,6 +88,7 @@ public class GameData public static final ResourceLocation POTIONTYPES = new ResourceLocation("minecraft:potiontypes"); public static final ResourceLocation ENCHANTMENTS = new ResourceLocation("minecraft:enchantments"); public static final ResourceLocation ENTITIES = new ResourceLocation("minecraft:entities"); + public static final ResourceLocation TILEENTITIES = new ResourceLocation("minecraft:tileentities"); public static final ResourceLocation RECIPES = new ResourceLocation("minecraft:recipes"); public static final ResourceLocation PROFESSIONS = new ResourceLocation("minecraft:villagerprofessions"); private static final int MAX_BLOCK_ID = 4095; @@ -98,6 +100,7 @@ public class GameData private static final int MAX_POTIONTYPE_ID = Integer.MAX_VALUE >> 5; // Int (SPacketEffect) private static final int MAX_ENCHANTMENT_ID = Short.MAX_VALUE - 1; // Short - serialized as a short in ItemStack NBTs. private static final int MAX_ENTITY_ID = Integer.MAX_VALUE >> 5; // Varint (SPacketSpawnMob) + private static final int MAX_TILE_ENTITY_ID = Integer.MAX_VALUE; //Doesnt seem to be serialized anywhere, so no max. private static final int MAX_RECIPE_ID = Integer.MAX_VALUE >> 5; // Varint CPacketRecipeInfo/SPacketRecipeBook private static final int MAX_PROFESSION_ID = 1024; //TODO: Is this serialized anywhere anymore? @@ -111,6 +114,7 @@ public class GameData init(); } + @SuppressWarnings("unchecked") public static void init() { if ( DISABLE_VANILLA_REGISTRIES) @@ -132,6 +136,7 @@ public class GameData makeRegistry(PROFESSIONS, VillagerProfession.class, MAX_PROFESSION_ID).create(); // TODO do we need the callback and the static field anymore? makeRegistry(ENTITIES, EntityType.class, MAX_ENTITY_ID).create(); + makeRegistry(TILEENTITIES, TileEntityType.class, MAX_TILE_ENTITY_ID).disableSaving().create(); } private static > RegistryBuilder makeRegistry(ResourceLocation name, Class type, int min, int max) diff --git a/src/main/java/net/minecraftforge/server/command/ChunkGenWorker.java b/src/main/java/net/minecraftforge/server/command/ChunkGenWorker.java index f4d805202b..d15913f32a 100644 --- a/src/main/java/net/minecraftforge/server/command/ChunkGenWorker.java +++ b/src/main/java/net/minecraftforge/server/command/ChunkGenWorker.java @@ -23,21 +23,21 @@ import java.io.IOException; import java.util.ArrayDeque; import java.util.Queue; -import net.minecraft.command.ICommandSender; +import net.minecraft.command.CommandSource; import net.minecraft.server.management.PlayerChunkMapEntry; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentBase; import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.world.MinecraftException; import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.AnvilChunkLoader; +import net.minecraft.world.storage.SessionLockException; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.WorldWorkerManager.IWorker; public class ChunkGenWorker implements IWorker { - private final ICommandSender listener; + private final CommandSource listener; protected final BlockPos start; protected final int total; private final int dim; @@ -48,7 +48,7 @@ public class ChunkGenWorker implements IWorker private int genned = 0; private Boolean keepingLoaded; - public ChunkGenWorker(ICommandSender listener, BlockPos start, int total, int dim, int interval) + public ChunkGenWorker(CommandSource listener, BlockPos start, int total, int dim, int interval) { this.listener = listener; this.start = start; @@ -85,17 +85,11 @@ public class ChunkGenWorker implements IWorker return ret; } - @Deprecated // TODO remove in 1.13 - public TextComponentTranslation getStartMessage() + public TextComponentBase getStartMessage(CommandSource sender) { return new TextComponentTranslation("commands.forge.gen.start", total, start.getX(), start.getZ(), dim); } - public TextComponentBase getStartMessage(ICommandSender sender) - { - return TextComponentHelper.createComponentTranslation(sender, "commands.forge.gen.start", total, start.getX(), start.getZ(), dim); - } - @Override public boolean hasWork() { @@ -112,7 +106,7 @@ public class ChunkGenWorker implements IWorker world = DimensionManager.getWorld(dim); if (world == null) { - listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.dim_fail", dim)); + listener.func_197030_a(new TextComponentTranslation("commands.forge.gen.dim_fail", dim), true); queue.clear(); return false; } @@ -124,7 +118,7 @@ public class ChunkGenWorker implements IWorker if (lastNotifcationTime < System.currentTimeMillis() - 10*1000) { - listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.progress", total - queue.size(), total)); + listener.func_197030_a(new TextComponentTranslation("commands.forge.gen.progress", total - queue.size(), total), true); lastNotifcationTime = System.currentTimeMillis(); } return false; @@ -142,7 +136,7 @@ public class ChunkGenWorker implements IWorker if (++lastNotification >= notificationFrequency || lastNotifcationTime < System.currentTimeMillis() - 60*1000) { - listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.progress", total - queue.size(), total)); + listener.func_197030_a(new TextComponentTranslation("commands.forge.gen.progress", total - queue.size(), total), true); lastNotification = 0; lastNotifcationTime = System.currentTimeMillis(); } @@ -150,27 +144,27 @@ public class ChunkGenWorker implements IWorker int x = next.getX(); int z = next.getZ(); - Chunk target = world.getChunkFromChunkCoords(x, z); + Chunk target = world.getChunk(x, z); Chunk[] chunks = { target }; - if (!target.isTerrainPopulated()) + if (!target.isPopulated()) { // In order for a chunk to populate, The chunks around its bottom right corner need to be loaded. // So lets load those chunks, but this needs to be done in a certain order to make this trigger. // So this does load more chunks then it should, and is a hack, but lets go!. chunks = new Chunk[] { target, - world.getChunkFromChunkCoords(x + 1, z), - world.getChunkFromChunkCoords(x + 1, z + 1), - world.getChunkFromChunkCoords(x, z + 1), + world.getChunk(x + 1, z), + world.getChunk(x + 1, z + 1), + world.getChunk(x, z + 1), }; try { world.getChunkProvider().chunkLoader.saveChunk(world, target); } - catch (IOException | MinecraftException e) + catch (IOException | SessionLockException e) { - listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.saveerror", e.getMessage())); + listener.func_197030_a(new TextComponentTranslation("commands.forge.gen.saveerror", e.getMessage()), true); } genned++; } @@ -185,7 +179,7 @@ public class ChunkGenWorker implements IWorker if (queue.size() == 0) { - listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.complete", genned, total, dim)); + listener.func_197030_a(new TextComponentTranslation("commands.forge.gen.complete", genned, total, dim), true); if (keepingLoaded != null && keepingLoaded) { DimensionManager.keepDimensionLoaded(dim, false); diff --git a/src/main/java/net/minecraftforge/server/command/CommandDimensions.java b/src/main/java/net/minecraftforge/server/command/CommandDimensions.java index 05bea7ad0a..084843455f 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandDimensions.java +++ b/src/main/java/net/minecraftforge/server/command/CommandDimensions.java @@ -20,49 +20,30 @@ package net.minecraftforge.server.command; import it.unimi.dsi.fastutil.ints.IntSortedSet; -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.server.MinecraftServer; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; import net.minecraft.util.text.TextComponentString; -import net.minecraft.world.DimensionType; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.common.DimensionManager; import java.util.Map; -public class CommandDimensions extends CommandBase +import com.mojang.brigadier.builder.ArgumentBuilder; + +public class CommandDimensions { - @Override - public String getName() + static ArgumentBuilder register() { - return "dimensions"; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.dimensions.usage"; - } - - @Override - public int getRequiredPermissionLevel() - { - return 0; - } - - @Override - public boolean checkPermission(MinecraftServer server, ICommandSender sender) - { - return true; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.dimensions.list")); - for (Map.Entry entry : DimensionManager.getRegisteredDimensions().entrySet()) - { - sender.sendMessage(new TextComponentString(entry.getKey().getName() + ": " + entry.getValue())); - } + return Commands.func_197057_a("dimensions") + .requires(cs->cs.func_197034_c(0)) //permission + .executes(ctx -> { + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.dimensions.list"), true); + for (Map.Entry entry : DimensionManager.getRegisteredDimensions().entrySet()) + { + ctx.getSource().func_197030_a(new TextComponentString(entry.getKey().getName() + ": " + entry.getValue()), true); + } + return 0; + }); } } diff --git a/src/main/java/net/minecraftforge/server/command/CommandEntity.java b/src/main/java/net/minecraftforge/server/command/CommandEntity.java index 301bf6d724..0ede29c5d8 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandEntity.java +++ b/src/main/java/net/minecraftforge/server/command/CommandEntity.java @@ -29,94 +29,77 @@ import java.util.Set; import java.util.stream.Collectors; import com.google.common.collect.Maps; -import net.minecraft.command.CommandBase; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.WrongUsageException; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.command.ISuggestionProvider; +import net.minecraft.command.arguments.BlockPosArgument; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityType; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.registries.ForgeRegistries; + import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; -class CommandEntity extends CommandTreeBase +class CommandEntity { - public CommandEntity() + static ArgumentBuilder register() { - addSubcommand(new EntityListCommand()); - addSubcommand(new CommandTreeHelp(this)); + return Commands.func_197057_a("entity") + .then(EntityListCommand.register()); //TODO: //Kill, spawn, etc.. } - @Override - public String getUsage(ICommandSender sender) + private static class EntityListCommand { - return "commands.forge.entity.usage"; - } - - @Override - public int getRequiredPermissionLevel() - { - return 2; - } - - @Override - public String getName() - { - return "entity"; - } - - private static class EntityListCommand extends CommandBase - { - @Override - public String getName() + private static final SimpleCommandExceptionType INVALID_FILTER = new SimpleCommandExceptionType(new TextComponentTranslation("commands.forge.entity.list.invalid")); + private static final DynamicCommandExceptionType INVALID_DIMENSION = new DynamicCommandExceptionType(dim -> new TextComponentTranslation("commands.forge.entity.list.invalidworld", dim)); + private static final SimpleCommandExceptionType NO_ENTITIES = new SimpleCommandExceptionType(new TextComponentTranslation("commands.forge.entity.list.none")); + static ArgumentBuilder register() { - return "list"; + return Commands.func_197057_a("list") + .requires(cs->cs.func_197034_c(2)) //permission + .then(Commands.func_197056_a("filter", StringArgumentType.string()) + .suggests((ctx, builder) -> ISuggestionProvider.func_197013_a(ForgeRegistries.ENTITIES.getKeys().stream().map(id -> id.toString()), builder)) + .then(Commands.func_197056_a("dim", IntegerArgumentType.integer()) + .suggests((ctx, builder) -> ISuggestionProvider.func_197013_a(DimensionManager.getIDStream().sorted().map(id -> id.toString()), builder)) + .executes(ctx -> execute(ctx.getSource(), StringArgumentType.getString(ctx, "filter"), IntegerArgumentType.getInteger(ctx, "dim"))) + ) + .executes(ctx -> execute(ctx.getSource(), StringArgumentType.getString(ctx, "filter"), ctx.getSource().func_197023_e().provider.getDimension())) + ) + .executes(ctx -> execute(ctx.getSource(), "*", ctx.getSource().func_197023_e().provider.getDimension())); } - @Override - public int getRequiredPermissionLevel() + private static int execute(CommandSource sender, String filter, int dim) throws CommandException { - return 2; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.entity.list.usage"; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - String filter = "*"; - if (args.length > 0) - { - filter = args[0]; - } final String cleanFilter = filter.replace("?", ".?").replace("*", ".*?"); - Set names = EntityList.getEntityNameList().stream().filter(n -> n.toString().matches(cleanFilter)).collect(Collectors.toSet()); + + Set names = ForgeRegistries.ENTITIES.getKeys().stream().filter(n -> n.toString().matches(cleanFilter)).collect(Collectors.toSet()); if (names.isEmpty()) - throw new WrongUsageException("commands.forge.entity.list.invalid"); - - int dim = args.length > 1 ? parseInt(args[1]) : sender.getEntityWorld().provider.getDimension(); + throw INVALID_FILTER.create(); WorldServer world = DimensionManager.getWorld(dim); if (world == null) - throw new WrongUsageException("commands.forge.entity.list.invalidworld", dim); + throw INVALID_DIMENSION.create(dim); Map>> list = Maps.newHashMap(); List entities = world.loadedEntityList; entities.forEach(e -> { - ResourceLocation key = EntityList.getKey(e); - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + MutablePair> info = list.computeIfAbsent(e.func_200600_R().getRegistryName(), k -> MutablePair.of(0, Maps.newHashMap())); ChunkPos chunk = new ChunkPos(e.getPosition()); info.left++; info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); @@ -127,25 +110,23 @@ class CommandEntity extends CommandTreeBase ResourceLocation name = names.iterator().next(); Pair> info = list.get(name); if (info == null) - throw new WrongUsageException("commands.forge.entity.list.none"); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.entity.list.single.header", name, info.getLeft())); + throw NO_ENTITIES.create(); + + sender.func_197030_a(new TextComponentTranslation("commands.forge.entity.list.single.header", name, info.getLeft()), true); List> toSort = new ArrayList<>(); toSort.addAll(info.getRight().entrySet()); toSort.sort((a, b) -> { if (Objects.equals(a.getValue(), b.getValue())) - { return a.getKey().toString().compareTo(b.getKey().toString()); - } else - { return b.getValue() - a.getValue(); - } }); + long limit = 10; for (Map.Entry e : toSort) { if (limit-- == 0) break; - sender.sendMessage(new TextComponentString(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z)); + sender.func_197030_a(new TextComponentString(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z), true); } } else @@ -161,33 +142,19 @@ class CommandEntity extends CommandTreeBase }); info.sort((a, b) -> { if (Objects.equals(a.getRight(), b.getRight())) - { return a.getKey().toString().compareTo(b.getKey().toString()); - } else - { return b.getRight() - a.getRight(); - } }); if (info.size() == 0) - throw new WrongUsageException("commands.forge.entity.list.none"); + throw NO_ENTITIES.create(); int count = info.stream().mapToInt(Pair::getRight).sum(); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.entity.list.multiple.header", count)); - info.forEach(e -> sender.sendMessage(new TextComponentString(" " + e.getValue() + ": " + e.getKey()))); + sender.func_197030_a(new TextComponentTranslation("commands.forge.entity.list.multiple.header", count), true); + info.forEach(e -> sender.func_197030_a(new TextComponentString(" " + e.getValue() + ": " + e.getKey()), true)); } } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) - { - if (args.length == 1) - { - String[] entityNames = EntityList.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new); - return getListOfStringsMatchingLastWord(args, entityNames); - } - return Collections.emptyList(); - } } + } diff --git a/src/main/java/net/minecraftforge/server/command/CommandGenerate.java b/src/main/java/net/minecraftforge/server/command/CommandGenerate.java index eed2189da0..5fc1d8463f 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandGenerate.java +++ b/src/main/java/net/minecraftforge/server/command/CommandGenerate.java @@ -20,72 +20,61 @@ package net.minecraftforge.server.command; import javax.annotation.Nullable; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; + +import it.unimi.dsi.fastutil.ints.IntSortedSet; + import java.util.Collections; import java.util.List; +import java.util.Map; -import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.WrongUsageException; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.command.ISuggestionProvider; +import net.minecraft.command.arguments.BlockPosArgument; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.dimension.DimensionType; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.WorldWorkerManager; -class CommandGenerate extends CommandBase +class CommandGenerate { - @Override - public String getName() + static ArgumentBuilder register() { - return "generate"; + return Commands.func_197057_a("generate") + .requires(cs->cs.func_197034_c(4)) //permission + .then(Commands.func_197056_a("pos", BlockPosArgument.func_197276_a()) + .then(Commands.func_197056_a("count", IntegerArgumentType.integer(1)) + .then(Commands.func_197056_a("dim", IntegerArgumentType.integer()) + .suggests((ctx, builder) -> ISuggestionProvider.func_197013_a(DimensionManager.getIDStream().sorted().map(id -> id.toString()), builder)) + .then(Commands.func_197056_a("interval", IntegerArgumentType.integer()) + .executes(ctx -> execute(ctx.getSource(), BlockPosArgument.func_197274_b(ctx, "pos"), getInt(ctx, "count"), getInt(ctx, "dim"), getInt(ctx, "interval"))) + ) + .executes(ctx -> execute(ctx.getSource(), BlockPosArgument.func_197274_b(ctx, "pos"), getInt(ctx, "count"), getInt(ctx, "dim"), -1)) + ) + .executes(ctx -> execute(ctx.getSource(), BlockPosArgument.func_197274_b(ctx, "pos"), getInt(ctx, "count"), ctx.getSource().func_197023_e().provider.getDimension(), -1)) + ) + ); } - @Override - public List getAliases() + private static int getInt(CommandContext ctx, String name) { - return Collections.singletonList("gen"); + return IntegerArgumentType.getInteger(ctx, name); } - @Override - public String getUsage(ICommandSender sender) + private static int execute(CommandSource source, BlockPos pos, int count, int dim, int interval) throws CommandException { - return "commands.forge.gen.usage"; - } + BlockPos chunkpos = new BlockPos(pos.getX() >> 4, 0, pos.getZ() >> 4); - @Override - public int getRequiredPermissionLevel() - { - return 4; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - // x y z chunkCount [dim] [interval] - if (args.length < 4) - { - throw new WrongUsageException("commands.forge.gen.usage"); - } - - BlockPos blockpos = parseBlockPos(sender, args, 0, false); - int count = parseInt(args[3], 10); - int dim = args.length >= 5 ? parseInt(args[4]) : sender.getEntityWorld().provider.getDimension(); - int interval = args.length >= 6 ? parseInt(args[5]) : -1; - BlockPos chunkpos = new BlockPos(blockpos.getX() >> 4, 0, blockpos.getZ() >> 4); - - ChunkGenWorker worker = new ChunkGenWorker(sender, chunkpos, count, dim, interval); - sender.sendMessage(worker.getStartMessage(sender)); + ChunkGenWorker worker = new ChunkGenWorker(source, chunkpos, count, dim, interval); + source.func_197030_a(worker.getStartMessage(source), true); WorldWorkerManager.addWorker(worker); } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) - { - if (args.length < 4) - { - return getTabCompletionCoordinate(args, 0, targetPos); - } - // Chunk Count? No completion - // Dimension, Add support for names? Get list of ids? Meh - return Collections.emptyList(); - } } diff --git a/src/main/java/net/minecraftforge/server/command/CommandSetDimension.java b/src/main/java/net/minecraftforge/server/command/CommandSetDimension.java index f5edc52ca7..9b173dc9b0 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandSetDimension.java +++ b/src/main/java/net/minecraftforge/server/command/CommandSetDimension.java @@ -21,85 +21,76 @@ package net.minecraftforge.server.command; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; import net.minecraft.command.ICommandSender; +import net.minecraft.command.ISuggestionProvider; import net.minecraft.command.WrongUsageException; +import net.minecraft.command.arguments.BlockPosArgument; +import net.minecraft.command.arguments.EntityArgument; import net.minecraft.entity.Entity; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.util.ITeleporter; import javax.annotation.Nullable; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + +import it.unimi.dsi.fastutil.ints.IntSortedSet; + +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; -public class CommandSetDimension extends CommandBase +public class CommandSetDimension { - @Override - public String getName() + private static final SimpleCommandExceptionType NO_ENTITIES = new SimpleCommandExceptionType(new TextComponentTranslation("commands.forge.setdim.invalid.entity")); + private static final DynamicCommandExceptionType INVALID_DIMENSION = new DynamicCommandExceptionType(dim -> new TextComponentTranslation("commands.forge.setdim.invalid.dim", dim)); + static ArgumentBuilder register() { - return "setdimension"; + return Commands.func_197057_a("setdimension") + .requires(cs->cs.func_197034_c(2)) //permission + .then(Commands.func_197056_a("targets", EntityArgument.func_197093_b()) + .then(Commands.func_197056_a("dim", IntegerArgumentType.integer()) + .suggests((ctx, builder) -> ISuggestionProvider.func_197013_a(DimensionManager.getIDStream().sorted().map(id -> id.toString()), builder)) + .then(Commands.func_197056_a("pos", BlockPosArgument.func_197276_a()) + .executes(ctx -> execute(ctx.getSource(), EntityArgument.func_197087_c(ctx, "targets"), IntegerArgumentType.getInteger(ctx, "dim"), BlockPosArgument.func_197274_b(ctx, "pos"))) + ) + .executes(ctx -> execute(ctx.getSource(), EntityArgument.func_197087_c(ctx, "targets"), IntegerArgumentType.getInteger(ctx, "dim"), new BlockPos(ctx.getSource().func_197036_d()))) + ) + ); } - @Override - public List getAliases() + private static int execute(CommandSource sender, Collection entities, int dim, BlockPos pos) throws CommandException { - return Collections.singletonList("setdim"); - } + entities.removeIf(CommandSetDimension::checkEntity); + if (entities.isEmpty()) + throw NO_ENTITIES.create(); - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.setdim.usage"; - } + if (!DimensionManager.isDimensionRegistered(dim)) + throw INVALID_DIMENSION.create(dim); - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) - { - if (args.length > 2 && args.length <= 5) - { - return getTabCompletionCoordinate(args, 2, targetPos); - } - return Collections.emptyList(); - } + final ITeleporter teleporter = new CommandTeleporter(pos); + entities.stream().filter(e -> e.dimension == dim).forEach(e -> sender.func_197030_a(new TextComponentTranslation("commands.forge.setdim.invalid.nochange", e.getDisplayName(), dim), true)); + entities.stream().filter(e -> e.dimension != dim).forEach(e -> e.changeDimension(dim, teleporter)); - @Override - public int getRequiredPermissionLevel() - { - return 2; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - // args: [ ] - if (args.length != 2 && args.length != 5) - { - throw new WrongUsageException("commands.forge.setdim.usage"); - } - Entity entity = getEntity(server, sender, args[0]); - if (!checkEntity(entity)) - { - throw new CommandException("commands.forge.setdim.invalid.entity", entity.getName()); - } - int dimension = parseInt(args[1]); - if (!DimensionManager.isDimensionRegistered(dimension)) - { - throw new CommandException("commands.forge.setdim.invalid.dim", dimension); - } - if (dimension == entity.dimension) - { - throw new CommandException("commands.forge.setdim.invalid.nochange", entity.getName(), dimension); - } - BlockPos pos = args.length == 5 ? parseBlockPos(sender, args, 2, false) : sender.getPosition(); - entity.changeDimension(dimension, new CommandTeleporter(pos)); + return 0; } private static boolean checkEntity(Entity entity) { // use vanilla portal logic, try to avoid doing anything too silly - return !entity.isRiding() && !entity.isBeingRidden() && entity.isNonBoss(); + return entity.isRiding() || entity.isBeingRidden() || entity.isNonBoss(); } private static class CommandTeleporter implements ITeleporter diff --git a/src/main/java/net/minecraftforge/server/command/CommandTps.java b/src/main/java/net/minecraftforge/server/command/CommandTps.java index b7940b792a..97a67bf9fb 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandTps.java +++ b/src/main/java/net/minecraftforge/server/command/CommandTps.java @@ -20,93 +20,74 @@ package net.minecraftforge.server.command; import java.text.DecimalFormat; +import java.util.stream.Collectors; -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.DimensionType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.command.ISuggestionProvider; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.common.DimensionManager; -class CommandTps extends CommandBase +class CommandTps { + private static final DynamicCommandExceptionType INVALID_DIMENSION = new DynamicCommandExceptionType(dim -> new TextComponentTranslation("commands.forge.tps.invalid", dim, DimensionManager.getIDStream().sorted().map(id -> id.toString()).collect(Collectors.joining(", ")))); private static final DecimalFormat TIME_FORMATTER = new DecimalFormat("########0.000"); - @Override - public String getName() + static ArgumentBuilder register() { - return "tps"; - } + return Commands.func_197057_a("tps") + .requires(cs->cs.func_197034_c(0)) //permission + .then(Commands.func_197056_a("dim", IntegerArgumentType.integer()) + .suggests((ctx, builder) -> ISuggestionProvider.func_197013_a(DimensionManager.getIDStream().sorted().map(id -> id.toString()), builder)) + .executes(ctx -> sendTime(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "dim"))) + ) + .executes(ctx -> { + for (Integer dim : (Iterable)DimensionManager.getIDStream().sorted()::iterator) + sendTime(ctx.getSource(), dim); - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tps.usage"; - } + double meanTickTime = mean(ctx.getSource().func_197028_i().tickTimeArray) * 1.0E-6D; + double meanTPS = Math.min(1000.0/meanTickTime, 20); + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.tps.summary.all", TIME_FORMATTER.format(meanTickTime), TIME_FORMATTER.format(meanTPS)), true); - @Override - public int getRequiredPermissionLevel() - { - return 0; - } - - @Override - public boolean checkPermission(MinecraftServer server, ICommandSender sender) - { - return true; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - int dim = 0; - boolean summary = true; - if (args.length > 0) - { - dim = parseInt(args[0]); - summary = false; - } - - if (summary) - { - for (Integer dimId : DimensionManager.getIDs()) - { - double worldTickTime = mean(server.worldTickTimes.get(dimId)) * 1.0E-6D; - double worldTPS = Math.min(1000.0/worldTickTime, 20); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tps.summary", getDimensionPrefix(dimId), TIME_FORMATTER.format(worldTickTime), TIME_FORMATTER.format(worldTPS))); + return 0; } - double meanTickTime = mean(server.tickTimeArray) * 1.0E-6D; - double meanTPS = Math.min(1000.0/meanTickTime, 20); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tps.summary","Overall", TIME_FORMATTER.format(meanTickTime), TIME_FORMATTER.format(meanTPS))); - } - else - { - double worldTickTime = mean(server.worldTickTimes.get(dim)) * 1.0E-6D; - double worldTPS = Math.min(1000.0/worldTickTime, 20); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tps.summary", getDimensionPrefix(dim), TIME_FORMATTER.format(worldTickTime), TIME_FORMATTER.format(worldTPS))); - } + ); } - private static String getDimensionPrefix(int dimId) + private static long[] getTimes(int dim) { - DimensionType providerType = DimensionManager.getProviderType(dimId); - if (providerType == null) - { - return String.format("Dim %2d", dimId); - } + //TODO: Implement, needs patch. + return null; + } + + private static int sendTime(CommandSource cs, int dim) throws CommandSyntaxException + { + long[] times = getTimes(dim); + + if (times == null) + throw INVALID_DIMENSION.create(dim); + + double worldTickTime = mean(times) * 1.0E-6D; + double worldTPS = Math.min(1000.0 / worldTickTime, 20); + DimensionType type = DimensionManager.getProviderType(dim); + if (type == null) + cs.func_197030_a(new TextComponentTranslation("commands.forge.tps.summary.basic", dim, TIME_FORMATTER.format(worldTickTime), TIME_FORMATTER.format(worldTPS)), true); else - { - return String.format("Dim %2d (%s)", dimId, providerType.getName()); - } + cs.func_197030_a(new TextComponentTranslation("commands.forge.tps.summary.named", dim, type.getName(), TIME_FORMATTER.format(worldTickTime), TIME_FORMATTER.format(worldTPS)), true); + + return 1; } private static long mean(long[] values) { long sum = 0L; for (long v : values) - { sum += v; - } return sum / values.length; } } diff --git a/src/main/java/net/minecraftforge/server/command/CommandTrack.java b/src/main/java/net/minecraftforge/server/command/CommandTrack.java index ff055711e3..466381730e 100644 --- a/src/main/java/net/minecraftforge/server/command/CommandTrack.java +++ b/src/main/java/net/minecraftforge/server/command/CommandTrack.java @@ -20,187 +20,114 @@ package net.minecraftforge.server.command; import javax.annotation.Nullable; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.function.Function; -import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.WrongUsageException; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.command.ISuggestionProvider; import net.minecraft.entity.Entity; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; -import net.minecraft.world.DimensionType; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.server.timings.ForgeTimings; import net.minecraftforge.server.timings.TimeTracker; -class CommandTrack extends CommandTreeBase +class CommandTrack { - private static final DecimalFormat TIME_FORMAT = new DecimalFormat("#####0.00"); - public CommandTrack() + static ArgumentBuilder register() { - addSubcommand(new StartTrackingCommand()); - addSubcommand(new ResetTrackingCommand()); - addSubcommand(new TrackResultsTileEntity()); - addSubcommand(new TrackResultsEntity()); - addSubcommand(new CommandTreeHelp(this)); + return Commands.func_197057_a("track") + .then(StartTrackingCommand.register()) + .then(ResetTrackingCommand.register()) + .then(TrackResultsEntity.register()) + .then(TrackResultsTileEntity.register()) + .then(StartTrackingCommand.register()); } - @Override - public String getName() + private static class StartTrackingCommand { - return "track"; - } - - @Override - public int getRequiredPermissionLevel() - { - return 2; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tracking.usage"; - } - - private static class StartTrackingCommand extends CommandBase - { - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException + static ArgumentBuilder register() { - if (args.length != 2) - { - throw new WrongUsageException(getUsage(sender)); - } - String type = args[0]; - int duration = parseInt(args[1], 1, 60); - if ("te".equals(type)) - { - TimeTracker.TILE_ENTITY_UPDATE.reset(); - TimeTracker.TILE_ENTITY_UPDATE.enable(duration); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.te.enabled", duration)); - } - else if ("entity".equals(type)) - { - TimeTracker.ENTITY_UPDATE.reset(); - TimeTracker.ENTITY_UPDATE.enable(duration); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.entity.enabled", duration)); - } - else - { - throw new WrongUsageException(getUsage(sender)); - } - } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) - { - return Arrays.asList("te", "entity"); - } - - @Override - public String getName() - { - return "start"; - } - - @Override - public int getRequiredPermissionLevel() - { - return 2; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tracking.start.usage"; + return Commands.func_197057_a("start") + .requires(cs->cs.func_197034_c(2)) //permission + .then(Commands.func_197057_a("te") + .then(Commands.func_197056_a("duration", IntegerArgumentType.integer(1)) + .executes(ctx -> { + int duration = IntegerArgumentType.getInteger(ctx, "duration"); + TimeTracker.TILE_ENTITY_UPDATE.reset(); + TimeTracker.TILE_ENTITY_UPDATE.enable(duration); + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.tracking.te.enabled", duration), true); + return 0; + }) + ) + ) + .then(Commands.func_197057_a("entity") + .then(Commands.func_197056_a("duration", IntegerArgumentType.integer(1)) + .executes(ctx -> { + int duration = IntegerArgumentType.getInteger(ctx, "duration"); + TimeTracker.ENTITY_UPDATE.reset(); + TimeTracker.ENTITY_UPDATE.enable(duration); + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.tracking.entity.enabled", duration), true); + return 0; + }) + ) + ); } } - private static class ResetTrackingCommand extends CommandBase + private static class ResetTrackingCommand { - @Override - public String getName() + static ArgumentBuilder register() { - return "reset"; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tracking.reset.usage"; - } - - @Override - public int getRequiredPermissionLevel() - { - return 2; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - if (args.length != 1) - { - throw new WrongUsageException(getUsage(sender)); - } - String type = args[0]; - if ("te".equals(type)) - { - TimeTracker.TILE_ENTITY_UPDATE.reset(); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.reset")); - } - else if ("entity".equals(type)) - { - TimeTracker.ENTITY_UPDATE.reset(); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.reset")); - } - else - { - throw new WrongUsageException(getUsage(sender)); - } - } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) - { - return Arrays.asList("te", "entity"); + return Commands.func_197057_a("reset") + .requires(cs->cs.func_197034_c(2)) //permission + .then(Commands.func_197057_a("te") + .executes(ctx -> { + TimeTracker.TILE_ENTITY_UPDATE.reset(); + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.tracking.te.reset"), true); + return 0; + }) + ) + .then(Commands.func_197057_a("entity") + .executes(ctx -> { + TimeTracker.ENTITY_UPDATE.reset(); + ctx.getSource().func_197030_a(new TextComponentTranslation("commands.forge.tracking.entity.reset"), true); + return 0; + }) + ); } } - /** - * A base command for all the tracking results commands - * - * @param - */ - private static abstract class TrackResultsBaseCommand extends CommandBase + private static class TrackResults { - - private TimeTracker tracker; - - protected TrackResultsBaseCommand(TimeTracker tracker) - { - this.tracker = tracker; - } - /** * Returns the time objects recorded by the time tracker sorted by average time * * @return A list of time objects */ - protected List> getSortedTimings() + private static List> getSortedTimings(TimeTracker tracker) { ArrayList> list = new ArrayList<>(); @@ -211,42 +138,21 @@ class CommandTrack extends CommandTreeBase return list; } - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException + private static int execute(CommandSource source, TimeTracker tracker, Function, ITextComponent> toString) throws CommandException { - List> timingsList = getSortedTimings(); + List> timingsList = getSortedTimings(tracker); if (timingsList.isEmpty()) { - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.noData")); + source.func_197030_a(new TextComponentTranslation("commands.forge.tracking.no_data"), true); } else { timingsList.stream() .filter(timings -> timings.getObject().get() != null) .limit(10) - .forEach(timings -> sender.sendMessage(buildTrackString(sender, timings)) - ); - } - } - - protected abstract ITextComponent buildTrackString(ICommandSender sender, ForgeTimings data); - - /** - * Gets the time suffix for the provided time in nanoseconds - * - * @param time The time in nanoseconds - * @return The time suffix - */ - protected String getTimeSuffix(double time) - { - if (time < 1000) - { - return "µs"; - } - else - { - return "ms"; + .forEach(timings -> source.func_197030_a(toString.apply(timings), true)); } + return 0; } /** @@ -255,105 +161,53 @@ class CommandTrack extends CommandTreeBase * @param dimId The dimension ID * @return The name of the dimension */ - protected String getWorldName(int dimId) + protected static String getWorldName(int dimId) { DimensionType type = DimensionManager.getProviderType(dimId); if (type == null) - { return "Dim " + dimId; - } else - { return type.getName(); - } } } - private static class TrackResultsEntity extends TrackResultsBaseCommand + private static class TrackResultsEntity { - public TrackResultsEntity() + static ArgumentBuilder register() { - super(TimeTracker.ENTITY_UPDATE); - } + return Commands.func_197057_a("entity").executes(ctx -> TrackResults.execute(ctx.getSource(), TimeTracker.ENTITY_UPDATE, data -> + { + Entity entity = data.getObject().get(); + if (entity == null) + return new TextComponentTranslation("commands.forge.tracking.invalid"); - @Override - public String getName() - { - return "entity"; - } + BlockPos pos = entity.getPosition(); + double averageTimings = data.getAverageTimings(); + String tickTime = (averageTimings > 1000 ? TIME_FORMAT.format(averageTimings / 1000) : TIME_FORMAT.format(averageTimings)) + (averageTimings < 1000 ? "µs" : "ms"); - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tracking.entity.usage"; - } - - @Override - protected ITextComponent buildTrackString(ICommandSender sender, ForgeTimings data) - { - Entity entity = data.getObject().get(); - if (entity == null) - return TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.invalid"); - - BlockPos currentPos = entity.getPosition(); - String world = getWorldName(entity.world.provider.getDimension()); - double averageTimings = data.getAverageTimings(); - String tickTime = (averageTimings > 1000 ? TIME_FORMAT.format(averageTimings / 1000) : TIME_FORMAT.format(averageTimings)) + getTimeSuffix( - averageTimings); - - return TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.timingEntry", entity.getName(), - world, currentPos.getX(), currentPos.getY(), currentPos.getZ(), tickTime); + return new TextComponentTranslation("commands.forge.tracking.timing_entry", entity.func_200600_R().getRegistryName(), TrackResults.getWorldName(entity.world.provider.getDimension()), pos.getX(), pos.getY(), pos.getZ(), tickTime); + }) + ); } } - private static class TrackResultsTileEntity extends TrackResultsBaseCommand + private static class TrackResultsTileEntity { - - public TrackResultsTileEntity() + static ArgumentBuilder register() { - super(TimeTracker.TILE_ENTITY_UPDATE); - } + return Commands.func_197057_a("te").executes(ctx -> TrackResults.execute(ctx.getSource(), TimeTracker.TILE_ENTITY_UPDATE, data -> + { + TileEntity te = data.getObject().get(); + if (te == null) + return new TextComponentTranslation("commands.forge.tracking.invalid"); - @Override - public String getName() - { - return "te"; - } + BlockPos pos = te.getPos(); - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.tracking.te.usage"; - } - - @Override - protected ITextComponent buildTrackString(ICommandSender sender, ForgeTimings data) - { - TileEntity te = data.getObject().get(); - if (te == null) - return TextComponentHelper.createComponentTranslation(sender, "commands.forge.tracking.invalid"); - - String name = getTileEntityName(te); - BlockPos pos = te.getPos(); - - double averageTimings = data.getAverageTimings(); - String tickTime = (averageTimings > 1000 ? TIME_FORMAT.format(averageTimings / 1000) : TIME_FORMAT.format(averageTimings)) + getTimeSuffix( - averageTimings); - return TextComponentHelper - .createComponentTranslation(sender, "commands.forge.tracking.timingEntry", name, - getWorldName(te.getWorld().provider.getDimension()), - pos.getX(), pos.getY(), pos.getZ(), tickTime); - } - - private String getTileEntityName(TileEntity tileEntity) - { - ResourceLocation registryId = TileEntity.getKey(tileEntity.getClass()); - if (registryId == null) - return tileEntity.getClass().getSimpleName(); - else - { - return registryId.toString(); - } + double averageTimings = data.getAverageTimings(); + String tickTime = (averageTimings > 1000 ? TIME_FORMAT.format(averageTimings / 1000) : TIME_FORMAT.format(averageTimings)) + (averageTimings < 1000 ? "µs" : "ms"); + return new TextComponentTranslation("commands.forge.tracking.timing_entry", te.func_200662_C().getRegistryName(), TrackResults.getWorldName(te.getWorld().provider.getDimension()), pos.getX(), pos.getY(), pos.getZ(), tickTime); + }) + ); } } } diff --git a/src/main/java/net/minecraftforge/server/command/CommandTreeBase.java b/src/main/java/net/minecraftforge/server/command/CommandTreeBase.java deleted file mode 100644 index c460ba42be..0000000000 --- a/src/main/java/net/minecraftforge/server/command/CommandTreeBase.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.server.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommand; -import net.minecraft.command.ICommandSender; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.math.BlockPos; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Base class for commands that has subcommands. - *

- * E.g. /team settings set [value] - * settings is subcommand of team and set is subcommand of settings - */ -public abstract class CommandTreeBase extends CommandBase -{ - private final Map commandMap = new HashMap<>(); - private final Map commandAliasMap = new HashMap<>(); - - public void addSubcommand(ICommand command) - { - commandMap.put(command.getName(), command); - for (String alias : command.getAliases()) - { - commandAliasMap.put(alias, command); - } - } - - public Collection getSubCommands() - { - return commandMap.values(); - } - - @Nullable - public ICommand getSubCommand(String command) - { - ICommand cmd = commandMap.get(command); - if (cmd != null) - { - return cmd; - } - return commandAliasMap.get(command); - } - - public Map getCommandMap() - { - return Collections.unmodifiableMap(commandMap); - } - - public List getSortedCommandList() - { - List list = new ArrayList<>(getSubCommands()); - Collections.sort(list); - return list; - } - - private static String[] shiftArgs(@Nullable String[] s) - { - if(s == null || s.length == 0) - { - return new String[0]; - } - - String[] s1 = new String[s.length - 1]; - System.arraycopy(s, 1, s1, 0, s1.length); - return s1; - } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos pos) - { - if(args.length == 1) - { - List keys = new ArrayList<>(); - - for (ICommand c : getSubCommands()) - { - if(c.checkPermission(server, sender)) - { - keys.add(c.getName()); - } - } - - keys.sort(null); - return getListOfStringsMatchingLastWord(args, keys); - } - - ICommand cmd = getSubCommand(args[0]); - - if(cmd != null) - { - return cmd.getTabCompletions(server, sender, shiftArgs(args), pos); - } - - return super.getTabCompletions(server, sender, args, pos); - } - - @Override - public boolean isUsernameIndex(String[] args, int index) - { - if (index > 0 && args.length > 1) - { - ICommand cmd = getSubCommand(args[0]); - if (cmd != null) - { - return cmd.isUsernameIndex(shiftArgs(args), index - 1); - } - } - - return false; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - if (args.length < 1) - { - String subCommandsString = getAvailableSubCommandsString(server, sender); - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, "commands.tree_base.available_subcommands", subCommandsString)); - } - else - { - ICommand cmd = getSubCommand(args[0]); - - if(cmd == null) - { - String subCommandsString = getAvailableSubCommandsString(server, sender); - throw new CommandException("commands.tree_base.invalid_cmd.list_subcommands", args[0], subCommandsString); - } - else if(!cmd.checkPermission(server, sender)) - { - throw new CommandException("commands.generic.permission"); - } - else - { - cmd.execute(server, sender, shiftArgs(args)); - } - } - } - - private String getAvailableSubCommandsString(MinecraftServer server, ICommandSender sender) - { - Collection availableCommands = new ArrayList<>(); - for (ICommand command : getSubCommands()) - { - if (command.checkPermission(server, sender)) - { - availableCommands.add(command.getName()); - } - } - return CommandBase.joinNiceStringFromCollection(availableCommands); - } -} diff --git a/src/main/java/net/minecraftforge/server/command/CommandTreeHelp.java b/src/main/java/net/minecraftforge/server/command/CommandTreeHelp.java deleted file mode 100644 index d66c296836..0000000000 --- a/src/main/java/net/minecraftforge/server/command/CommandTreeHelp.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.server.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommand; -import net.minecraft.command.ICommandSender; -import net.minecraft.server.MinecraftServer; - -/** - * Add help for parent and all its children. - * Must be added to parent after all other commands. - */ -public class CommandTreeHelp extends CommandTreeBase -{ - private final ICommand parent; - - public CommandTreeHelp(CommandTreeBase parent) - { - this.parent = parent; - for (ICommand command : parent.getSubCommands()) - { - addSubcommand(new HelpSubCommand(this, command)); - } - } - - @Override - public int getRequiredPermissionLevel() - { - return 0; - } - - @Override - public String getName() - { - return "help"; - } - - @Override - public String getUsage(ICommandSender sender) - { - return "commands.forge.usage.help"; - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - if (args.length == 0) - { - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, parent.getUsage(sender))); - for (ICommand subCommand : getSubCommands()) - { - if (subCommand instanceof HelpSubCommand && subCommand.checkPermission(server, sender)) - { - subCommand.execute(server, sender, args); - } - } - return; - } - super.execute(server, sender, args); - } - - public static class HelpSubCommand extends CommandBase - { - private final CommandTreeHelp parent; - private final ICommand command; - - public HelpSubCommand(CommandTreeHelp parent, ICommand command) - { - this.parent = parent; - this.command = command; - } - - @Override - public int getRequiredPermissionLevel() - { - return 0; - } - - @Override - public String getName() - { - return command.getName(); - } - - @Override - public String getUsage(ICommandSender sender) - { - return command.getUsage(sender); - } - - @Override - public boolean checkPermission(MinecraftServer server, ICommandSender sender) - { - return command.checkPermission(server, sender); - } - - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException - { - sender.sendMessage(TextComponentHelper.createComponentTranslation(sender, command.getUsage(sender))); - } - } -} diff --git a/src/main/java/net/minecraftforge/server/command/ForgeCommand.java b/src/main/java/net/minecraftforge/server/command/ForgeCommand.java index bcae494538..8b4e6aee3c 100644 --- a/src/main/java/net/minecraftforge/server/command/ForgeCommand.java +++ b/src/main/java/net/minecraftforge/server/command/ForgeCommand.java @@ -22,24 +22,19 @@ package net.minecraftforge.server.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.command.CommandSource; -import net.minecraft.util.text.TextComponentString; public class ForgeCommand { public ForgeCommand(CommandDispatcher dispatcher) { - dispatcher.register(LiteralArgumentBuilder.literal("forge"). - requires(cs->cs.func_197034_c(2)). - then(LiteralArgumentBuilder.literal("tps")). - executes(c->{c.getSource().func_197021_a(new TextComponentString("command.forge.tps.summary")); return 1;})); -/* - super.addSubcommand(new CommandTps()); - super.addSubcommand(new CommandTrack()); - super.addSubcommand(new CommandGenerate()); - super.addSubcommand(new CommandEntity()); - super.addSubcommand(new CommandSetDimension()); - super.addSubcommand(new CommandDimensions()); - super.addSubcommand(new CommandTreeHelp(this)); -*/ + dispatcher.register( + LiteralArgumentBuilder.literal("forge") + .then(CommandTps.register()) + .then(CommandTrack.register()) + .then(CommandEntity.register()) + .then(CommandGenerate.register()) + .then(CommandDimensions.register()) + .then(CommandSetDimension.register()) + ); } } diff --git a/src/main/resources/assets/forge/lang/en_us.json b/src/main/resources/assets/forge/lang/en_us.json index 74fd7464c2..f9ff6cc80d 100644 --- a/src/main/resources/assets/forge/lang/en_us.json +++ b/src/main/resources/assets/forge/lang/en_us.json @@ -6,5 +6,31 @@ "fml.menu.mods.z_to_a": "Z-A", "fml.menu.mods.config": "Config", "fml.menu.modoptions": "Mod Options...", - "fml.menu.loadingmods": "{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded" + "fml.menu.loadingmods": "{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded", + + "commands.forge.dimensions.list": "Currently registered dimensions by type:", + "commands.forge.entity.list.invalid": "Invalid filter, does not match any entities. Use /forge entity list for a proper list", + "commands.forge.entity.list.invalidworld": "Could not load world for dimension {0}. Please select a valid dimension.", + "commands.forge.entity.list.none": "No entities found.", + "commands.forge.entity.list.single.header": "Entity: {0} Total: {1}", + "commands.forge.entity.list.multiple.header": "Total: {0}", + "commands.forge.gen.usage": "Use /forge gen [dimension] [interval]", + "commands.forge.gen.dim_fail": "Failed to load world for dimension {0}, Task terminated.", + "commands.forge.gen.progress": "Generation Progress: {0}/{1}", + "commands.forge.gen.complete": "Finished generating {0} new chunks (out of {2}) for dimension {3}.", + "commands.forge.gen.start": "Starting to generate {0} chunks in a spiral around {1}, {2} in dimension {3}.", + "commands.forge.setdim.invalid.entity": "The entity selected ({0}) is not valid.", + "commands.forge.setdim.invalid.dim": "The dimension ID specified ({0}) is not valid.", + "commands.forge.setdim.invalid.nochange": "The entity selected ({0}) is already in the dimension specified ({1}).", + "commands.forge.tps.invalid": "Invalid dimension {0} Possible values: {1}", + "commands.forge.tps.summary.all": "Overall: Mean tick time: {1} ms. Mean TPS: {2}", + "commands.forge.tps.summary.basic": "Dim {0}: Mean tick time: {1} ms. Mean TPS: {2}", + "commands.forge.tps.summary.named": "Dim {0} ({1}): Mean tick time: {2} ms. Mean TPS: {3}", + "commands.forge.tracking.entity.enabled": "Entity tracking enabled for %d seconds.", + "commands.forge.tracking.entity.reset": "Entity timings data has been cleared!", + "commands.forge.tracking.invalid": "Invalid tracking data.", + "commands.forge.tracking.te.enabled": "Tile Entity tracking enabled for %d seconds.", + "commands.forge.tracking.te.reset": "Tile entity timings data has been cleared!", + "commands.forge.tracking.timing_entry": "{0} - {1} [{2}, {3}, {4}]: {5}", + "commands.forge.tracking.no_data": "No data has been recorded yet." }