diff --git a/src/api/java/appeng/api/implementations/items/ISpatialStorageCell.java b/src/api/java/appeng/api/implementations/items/ISpatialStorageCell.java index 803833e11..caf9d5128 100644 --- a/src/api/java/appeng/api/implementations/items/ISpatialStorageCell.java +++ b/src/api/java/appeng/api/implementations/items/ISpatialStorageCell.java @@ -26,6 +26,7 @@ package appeng.api.implementations.items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; @@ -58,7 +59,7 @@ public interface ISpatialStorageCell { * * @return dimension id or -1 */ - DimensionType getStoredDimension(ItemStack is); + RegistryKey getStoredDimension(ItemStack is); /** * Perform a spatial swap with the contents of the cell, and the world. diff --git a/src/api/java/appeng/api/storage/ISpatialDimension.java b/src/api/java/appeng/api/storage/ISpatialDimension.java index 25231a28e..e7e50e628 100644 --- a/src/api/java/appeng/api/storage/ISpatialDimension.java +++ b/src/api/java/appeng/api/storage/ISpatialDimension.java @@ -24,27 +24,29 @@ import javax.annotation.Nullable; import net.minecraft.util.math.BlockPos; import net.minecraft.text.Text; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; import net.minecraft.server.world.ServerWorld; public interface ISpatialDimension { - ServerWorld getWorld(DimensionType cellDim); + ServerWorld getWorld(RegistryKey cellDim); @Nullable - DimensionType createNewCellDimension(BlockPos capacity); + RegistryKey createNewCellDimension(BlockPos capacity); - void deleteCellDimension(DimensionType cellDim); + void deleteCellDimension(RegistryKey cellDim); - boolean isCellDimension(DimensionType cellDim); + boolean isCellDimension(RegistryKey cellDim); - BlockPos getCellDimensionOrigin(DimensionType cellDim); + BlockPos getCellDimensionOrigin(RegistryKey cellDim); - BlockPos getCellDimensionSize(DimensionType cellDim); + BlockPos getCellDimensionSize(RegistryKey cellDim); /** * Adds a user-facing tooltip that describes this dimension so that a player can * keep storage cells apart. */ - void addCellDimensionTooltip(DimensionType cellDim, List lines); + void addCellDimensionTooltip(RegistryKey cellDim, List lines); } diff --git a/src/main/java/appeng/client/AppEngClient.java b/src/main/java/appeng/client/AppEngClient.java index 3520d2b44..549b15b3b 100644 --- a/src/main/java/appeng/client/AppEngClient.java +++ b/src/main/java/appeng/client/AppEngClient.java @@ -10,6 +10,7 @@ import appeng.client.render.SimpleModelLoader; import appeng.client.render.cablebus.CableBusModelLoader; import appeng.client.render.effects.*; import appeng.client.render.model.SkyCompassModel; +import appeng.client.render.spatial.SpatialPylonModel; import appeng.client.render.tesr.InscriberTESR; import appeng.client.render.tesr.SkyChestTESR; import appeng.container.implementations.*; @@ -245,7 +246,7 @@ public final class AppEngClient extends AppEngBase { // FIXME FABRIC addBuiltInModel("biometric_card", BiometricCardModel::new); // FIXME FABRIC addBuiltInModel("drive", DriveModel::new); // FIXME FABRIC addBuiltInModel("color_applicator", ColorApplicatorModel::new); -// FIXME FABRIC addBuiltInModel("spatial_pylon", SpatialPylonModel::new); + addBuiltInModel("block/spatial_pylon", SpatialPylonModel::new); // FIXME FABRIC addBuiltInModel("paint_splotches", PaintSplotchesModel::new); // FIXME FABRIC addBuiltInModel("quantum_bridge_formed", QnbFormedModel::new); // FIXME FABRIC addBuiltInModel("p2p_tunnel_frequency", P2PTunnelFrequencyModel::new); diff --git a/src/main/java/appeng/client/gui/implementations/SpatialIOPortScreen.java b/src/main/java/appeng/client/gui/implementations/SpatialIOPortScreen.java index 8a078f425..553d908f2 100644 --- a/src/main/java/appeng/client/gui/implementations/SpatialIOPortScreen.java +++ b/src/main/java/appeng/client/gui/implementations/SpatialIOPortScreen.java @@ -45,26 +45,26 @@ public class SpatialIOPortScreen extends AEBaseScreen { @Override public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - this.textRenderer.draw(matrices, GuiText.StoredPower.text() + ": " - + Platform.formatPowerLong(this.handler.getCurrentPower(), false), 13, 21, 4210752); + this.textRenderer.draw(matrices, GuiText.StoredPower.withSuffix(": " + + Platform.formatPowerLong(this.handler.getCurrentPower(), false)), 13, 21, 4210752); this.textRenderer.draw(matrices, - GuiText.MaxPower.text() + ": " + Platform.formatPowerLong(this.handler.getMaxPower(), false), 13, + GuiText.MaxPower.withSuffix(": " + Platform.formatPowerLong(this.handler.getMaxPower(), false)), 13, 31, 4210752); - this.textRenderer.draw(matrices, GuiText.RequiredPower.text() + ": " - + Platform.formatPowerLong(this.handler.getRequiredPower(), false), 13, 73, 4210752); + this.textRenderer.draw(matrices, GuiText.RequiredPower.withSuffix(": " + + Platform.formatPowerLong(this.handler.getRequiredPower(), false)), 13, 73, 4210752); this.textRenderer.draw(matrices, - GuiText.Efficiency.text() + ": " + (((float) this.handler.getEfficency()) / 100) + '%', 13, 83, + GuiText.Efficiency.withSuffix(": " + (((float) this.handler.getEfficency()) / 100) + '%'), 13, 83, 4210752); this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.SpatialIOPort.text()), 8, 6, 4210752); this.textRenderer.draw(matrices, GuiText.inventory.text(), 8, this.backgroundHeight - 96, 4210752); if (this.handler.xSize != 0 && this.handler.ySize != 0 && this.handler.zSize != 0) { - final String text = GuiText.SCSSize.text() + ": " + this.handler.xSize + "x" + this.handler.ySize - + "x" + this.handler.zSize; + final Text text = GuiText.SCSSize.withSuffix(": " + this.handler.xSize + "x" + this.handler.ySize + + "x" + this.handler.zSize); this.textRenderer.draw(matrices, text, 13, 93, 4210752); } else { - this.textRenderer.draw(matrices, GuiText.SCSSize.text() + ": " + GuiText.SCSInvalid.text(), 13, 93, 4210752); + this.textRenderer.draw(matrices, GuiText.SCSSize.withSuffix(": ").append(GuiText.SCSInvalid.text()), 13, 93, 4210752); } } diff --git a/src/main/java/appeng/client/render/BasicUnbakedModel.java b/src/main/java/appeng/client/render/BasicUnbakedModel.java index d3e4e58ee..d5f42f562 100644 --- a/src/main/java/appeng/client/render/BasicUnbakedModel.java +++ b/src/main/java/appeng/client/render/BasicUnbakedModel.java @@ -6,6 +6,7 @@ import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.util.Identifier; import java.util.Collection; +import java.util.Collections; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -17,6 +18,11 @@ import java.util.stream.Stream; */ public interface BasicUnbakedModel extends UnbakedModel { + @Override + default Collection getModelDependencies() { + return Collections.emptyList(); + } + default Stream getAdditionalTextures() { return Stream.empty(); } diff --git a/src/unported/java/appeng/client/render/spatial/SpatialPylonBakedModel.java b/src/main/java/appeng/client/render/spatial/SpatialPylonBakedModel.java similarity index 82% rename from src/unported/java/appeng/client/render/spatial/SpatialPylonBakedModel.java rename to src/main/java/appeng/client/render/spatial/SpatialPylonBakedModel.java index 0de14891b..065ff7bea 100644 --- a/src/unported/java/appeng/client/render/spatial/SpatialPylonBakedModel.java +++ b/src/main/java/appeng/client/render/spatial/SpatialPylonBakedModel.java @@ -18,21 +18,30 @@ package appeng.client.render.spatial; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.function.Supplier; import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.google.common.collect.ImmutableMap; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.json.ModelOverrideList; +import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.texture.Sprite; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraftforge.client.model.data.IDynamicBakedModel; +import net.minecraft.world.BlockRenderView; import appeng.client.render.cablebus.CubeBuilder; @@ -41,7 +50,7 @@ import appeng.tile.spatial.SpatialPylonBlockEntity; /** * The baked model that will be used for rendering the spatial pylon. */ -class SpatialPylonBakedModel implements IDynamicBakedModel { +class SpatialPylonBakedModel implements BakedModel, FabricBakedModel { private final Map textures; @@ -49,13 +58,16 @@ class SpatialPylonBakedModel implements IDynamicBakedModel { this.textures = ImmutableMap.copyOf(textures); } - @Nonnull @Override - public List getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, - @Nonnull IModelData extraData) { - int flags = this.getFlags(extraData); + public boolean isVanillaAdapter() { + return false; + } - CubeBuilder builder = new CubeBuilder(); + @Override + public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + int flags = getFlags(blockView, pos); + + CubeBuilder builder = new CubeBuilder(context.getEmitter()); if (flags != 0) { Direction ori = null; @@ -134,13 +146,31 @@ class SpatialPylonBakedModel implements IDynamicBakedModel { builder.setTexture(this.textures.get(SpatialPylonTextureType.DIM)); builder.addCube(0, 0, 0, 16, 16, 16); } - - return builder.getOutput(); } - private int getFlags(IModelData modelData) { - Integer flags = modelData.getData(SpatialPylonBlockEntity.STATE); - return flags != null ? flags : 0; + @Override + public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + // Not intended to be used as an item model. + } + + @Nonnull + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand) { + // Can only sensibly render using the new API + return Collections.emptyList(); + } + + private int getFlags(BlockRenderView blockRenderView, BlockPos pos) { + if (!(blockRenderView instanceof RenderAttachedBlockView)) { + return 0; + } + + Object attachment = ((RenderAttachedBlockView) blockRenderView).getBlockEntityRenderAttachment(pos); + if (!(attachment instanceof Integer)) { + return 0; + } + + return (Integer) attachment; } private static SpatialPylonTextureType getTextureTypeFromSideOutside(int flags, Direction ori, Direction dir) { @@ -202,6 +232,11 @@ class SpatialPylonBakedModel implements IDynamicBakedModel { return this.textures.get(SpatialPylonTextureType.DIM); } + @Override + public ModelTransformation getTransformation() { + return ModelTransformation.NONE; + } + @Override public ModelOverrideList getOverrides() { return ModelOverrideList.EMPTY; diff --git a/src/unported/java/appeng/client/render/spatial/SpatialPylonModel.java b/src/main/java/appeng/client/render/spatial/SpatialPylonModel.java similarity index 62% rename from src/unported/java/appeng/client/render/spatial/SpatialPylonModel.java rename to src/main/java/appeng/client/render/spatial/SpatialPylonModel.java index febbd41d4..975b5d666 100644 --- a/src/unported/java/appeng/client/render/spatial/SpatialPylonModel.java +++ b/src/main/java/appeng/client/render/spatial/SpatialPylonModel.java @@ -18,50 +18,40 @@ package appeng.client.render.spatial; +import appeng.client.render.BasicUnbakedModel; +import appeng.core.AppEng; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.util.Identifier; + +import javax.annotation.Nullable; import java.util.Arrays; -import java.util.Collection; import java.util.EnumMap; import java.util.Map; -import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.stream.Stream; -import com.mojang.datafixers.util.Pair; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.IModelTransform; -import net.minecraft.client.render.model.IUnbakedModel; -import net.minecraft.client.render.model.json.ModelOverrideList; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.client.texture.Sprite; -import net.minecraft.util.Identifier; -import net.minecraftforge.client.model.IModelConfiguration; -import net.minecraftforge.client.model.geometry.IModelGeometry; - -import appeng.core.AppEng; - -public class SpatialPylonModel implements IModelGeometry { +public class SpatialPylonModel implements BasicUnbakedModel { + @Nullable @Override - public BakedModel bake(IModelConfiguration owner, ModelLoader bakery, - Function spriteGetter, IModelTransform modelTransform, - ModelOverrideList overrides, Identifier modelLocation) { + public BakedModel bake(ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { Map textures = new EnumMap<>(SpatialPylonTextureType.class); for (SpatialPylonTextureType type : SpatialPylonTextureType.values()) { - textures.put(type, spriteGetter.apply(getTexturePath(type))); + textures.put(type, textureGetter.apply(getTexturePath(type))); } return new SpatialPylonBakedModel(textures); } @Override - public Collection getTextures(IModelConfiguration owner, - Function modelGetter, Set> missingTextureErrors) { - return Arrays.stream(SpatialPylonTextureType.values()).map(SpatialPylonModel::getTexturePath) - .collect(Collectors.toList()); + public Stream getAdditionalTextures() { + return Arrays.stream(SpatialPylonTextureType.values()).map(SpatialPylonModel::getTexturePath); } private static SpriteIdentifier getTexturePath(SpatialPylonTextureType type) { diff --git a/src/unported/java/appeng/client/render/spatial/SpatialPylonTextureType.java b/src/main/java/appeng/client/render/spatial/SpatialPylonTextureType.java similarity index 100% rename from src/unported/java/appeng/client/render/spatial/SpatialPylonTextureType.java rename to src/main/java/appeng/client/render/spatial/SpatialPylonTextureType.java diff --git a/src/main/java/appeng/core/AppEngBase.java b/src/main/java/appeng/core/AppEngBase.java index e705042a3..c15c6f36b 100644 --- a/src/main/java/appeng/core/AppEngBase.java +++ b/src/main/java/appeng/core/AppEngBase.java @@ -33,8 +33,12 @@ import appeng.hooks.ToolItemHook; import appeng.items.tools.NetworkToolItem; import appeng.me.cache.*; import appeng.mixins.CriteriaRegisterMixin; +import appeng.hooks.RegisterDimensionTypeCallback; import appeng.recipes.handlers.*; import appeng.server.AECommand; +import appeng.spatial.SpatialDimensionManager; +import appeng.spatial.StorageCellBiome; +import appeng.spatial.StorageChunkGenerator; import appeng.worldgen.ChargedQuartzOreConfig; import appeng.worldgen.ChargedQuartzOreFeature; import appeng.worldgen.meteorite.MeteoriteStructure; @@ -50,10 +54,12 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeType; import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.tag.BlockTags; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.chunk.StructureConfig; import net.minecraft.world.gen.decorator.Decorator; @@ -64,6 +70,7 @@ import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.feature.FeatureConfig; import net.minecraft.world.gen.feature.OreFeatureConfig; +import java.util.OptionalLong; import java.util.function.Consumer; public abstract class AppEngBase implements AppEng { @@ -97,6 +104,7 @@ public abstract class AppEngBase implements AppEng { registerRecipeSerializers(); registerWorldGen(); registerServerCommands(); + registerDimension(); setupInternalRegistries(); @@ -368,4 +376,31 @@ public abstract class AppEngBase implements AppEng { }); } + private void registerDimension() { + Registry.register(Registry.BIOME, AppEng.makeId("storage"), StorageCellBiome.INSTANCE); + Registry.register(Registry.CHUNK_GENERATOR, AppEng.makeId("storage"), StorageChunkGenerator.CODEC); + + RegisterDimensionTypeCallback.EVENT.register(registryTracker -> { + + registryTracker.addDimensionType( + SpatialDimensionManager.STORAGE_DIMENSION_TYPE, + new DimensionType( + OptionalLong.of(12000), + false, + false, + false, + false, + false, + false, + true, + true, + false, + 256, + BlockTags.INFINIBURN_OVERWORLD.getId(), + 0.5f + ) + ); + }); + } + } diff --git a/src/main/java/appeng/core/api/definitions/ApiBlocks.java b/src/main/java/appeng/core/api/definitions/ApiBlocks.java index 445f40593..29d455518 100644 --- a/src/main/java/appeng/core/api/definitions/ApiBlocks.java +++ b/src/main/java/appeng/core/api/definitions/ApiBlocks.java @@ -83,76 +83,76 @@ import static appeng.block.AEBaseBlock.defaultProps; * Internal implementation for the API blocks */ public final class ApiBlocks implements IBlocks { - private IBlockDefinition quartzOre; - private IBlockDefinition quartzOreCharged; - private IBlockDefinition matrixFrame; - private IBlockDefinition quartzBlock; - private IBlockDefinition quartzPillar; - private IBlockDefinition chiseledQuartzBlock; - private IBlockDefinition quartzGlass; - private IBlockDefinition quartzVibrantGlass; - private IBlockDefinition quartzFixture; - private IBlockDefinition fluixBlock; - private IBlockDefinition skyStoneBlock; - private IBlockDefinition smoothSkyStoneBlock; - private IBlockDefinition skyStoneBrick; - private IBlockDefinition skyStoneSmallBrick; - private IBlockDefinition skyStoneChest; - private IBlockDefinition smoothSkyStoneChest; - private IBlockDefinition skyCompass; - private ITileDefinition grindstone; - private ITileDefinition crank; - private ITileDefinition inscriber; - private ITileDefinition wirelessAccessPoint; - private ITileDefinition charger; - private IBlockDefinition tinyTNT; - private ITileDefinition securityStation; - private ITileDefinition quantumRing; - private ITileDefinition quantumLink; - private ITileDefinition spatialPylon; - private ITileDefinition spatialIOPort; - private ITileDefinition multiPart; - private ITileDefinition controller; - private ITileDefinition drive; - private ITileDefinition chest; - private ITileDefinition iface; - private ITileDefinition fluidIface; - private ITileDefinition cellWorkbench; - private ITileDefinition iOPort; - private ITileDefinition condenser; - private ITileDefinition energyAcceptor; - private ITileDefinition vibrationChamber; - private ITileDefinition quartzGrowthAccelerator; - private ITileDefinition energyCell; - private ITileDefinition energyCellDense; - private ITileDefinition energyCellCreative; - private ITileDefinition craftingUnit; - private ITileDefinition craftingAccelerator; - private ITileDefinition craftingStorage1k; - private ITileDefinition craftingStorage4k; - private ITileDefinition craftingStorage16k; - private ITileDefinition craftingStorage64k; - private ITileDefinition craftingMonitor; - private ITileDefinition molecularAssembler; - private ITileDefinition lightDetector; - private ITileDefinition paint; - private IBlockDefinition skyStoneStairs; - private IBlockDefinition smoothSkyStoneStairs; - private IBlockDefinition skyStoneBrickStairs; - private IBlockDefinition skyStoneSmallBrickStairs; - private IBlockDefinition fluixStairs; - private IBlockDefinition quartzStairs; - private IBlockDefinition chiseledQuartzStairs; - private IBlockDefinition quartzPillarStairs; + private final IBlockDefinition quartzOre; + private final IBlockDefinition quartzOreCharged; + private final IBlockDefinition matrixFrame; + private final IBlockDefinition quartzBlock; + private final IBlockDefinition quartzPillar; + private final IBlockDefinition chiseledQuartzBlock; + private final IBlockDefinition quartzGlass; + private final IBlockDefinition quartzVibrantGlass; + private final IBlockDefinition quartzFixture; + private final IBlockDefinition fluixBlock; + private final IBlockDefinition skyStoneBlock; + private final IBlockDefinition smoothSkyStoneBlock; + private final IBlockDefinition skyStoneBrick; + private final IBlockDefinition skyStoneSmallBrick; + private final IBlockDefinition skyStoneChest; + private final IBlockDefinition smoothSkyStoneChest; + private final IBlockDefinition skyCompass; + private final ITileDefinition grindstone; + private final ITileDefinition crank; + private final ITileDefinition inscriber; + private final ITileDefinition wirelessAccessPoint; + private final ITileDefinition charger; + private final IBlockDefinition tinyTNT; + private final ITileDefinition securityStation; + private final ITileDefinition quantumRing; + private final ITileDefinition quantumLink; + private final ITileDefinition spatialPylon; + private final ITileDefinition spatialIOPort; + private final ITileDefinition multiPart; + private final ITileDefinition controller; + private final ITileDefinition drive; + private final ITileDefinition chest; + private final ITileDefinition iface; + private final ITileDefinition fluidIface; + private final ITileDefinition cellWorkbench; + private final ITileDefinition iOPort; + private final ITileDefinition condenser; + private final ITileDefinition energyAcceptor; + private final ITileDefinition vibrationChamber; + private final ITileDefinition quartzGrowthAccelerator; + private final ITileDefinition energyCell; + private final ITileDefinition energyCellDense; + private final ITileDefinition energyCellCreative; + private final ITileDefinition craftingUnit; + private final ITileDefinition craftingAccelerator; + private final ITileDefinition craftingStorage1k; + private final ITileDefinition craftingStorage4k; + private final ITileDefinition craftingStorage16k; + private final ITileDefinition craftingStorage64k; + private final ITileDefinition craftingMonitor; + private final ITileDefinition molecularAssembler; + private final ITileDefinition lightDetector; + private final ITileDefinition paint; + private final IBlockDefinition skyStoneStairs; + private final IBlockDefinition smoothSkyStoneStairs; + private final IBlockDefinition skyStoneBrickStairs; + private final IBlockDefinition skyStoneSmallBrickStairs; + private final IBlockDefinition fluixStairs; + private final IBlockDefinition quartzStairs; + private final IBlockDefinition chiseledQuartzStairs; + private final IBlockDefinition quartzPillarStairs; - private IBlockDefinition skyStoneSlab; - private IBlockDefinition smoothSkyStoneSlab; - private IBlockDefinition skyStoneBrickSlab; - private IBlockDefinition skyStoneSmallBrickSlab; - private IBlockDefinition fluixSlab; - private IBlockDefinition quartzSlab; - private IBlockDefinition chiseledQuartzSlab; - private IBlockDefinition quartzPillarSlab; + private final IBlockDefinition skyStoneSlab; + private final IBlockDefinition smoothSkyStoneSlab; + private final IBlockDefinition skyStoneBrickSlab; + private final IBlockDefinition skyStoneSmallBrickSlab; + private final IBlockDefinition fluixSlab; + private final IBlockDefinition quartzSlab; + private final IBlockDefinition chiseledQuartzSlab; + private final IBlockDefinition quartzPillarSlab; private IBlockDefinition itemGen; private IBlockDefinition chunkLoader; diff --git a/src/main/java/appeng/core/api/definitions/ApiItems.java b/src/main/java/appeng/core/api/definitions/ApiItems.java index 968497448..db8d41d2c 100644 --- a/src/main/java/appeng/core/api/definitions/ApiItems.java +++ b/src/main/java/appeng/core/api/definitions/ApiItems.java @@ -47,6 +47,7 @@ import appeng.items.misc.PaintBallItemRendering; import appeng.items.parts.FacadeItem; import appeng.items.storage.BasicStorageCellItem; import appeng.items.storage.CreativeStorageCellItem; +import appeng.items.storage.SpatialStorageCellItem; import appeng.items.storage.ViewCellItem; import appeng.items.tools.BiometricCardItem; import appeng.items.tools.MemoryCardItem; @@ -55,7 +56,6 @@ import appeng.items.tools.powered.*; import appeng.items.tools.quartz.*; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.SpawnGroup; import net.minecraft.item.Item; @@ -67,59 +67,59 @@ import java.util.function.Consumer; * Internal implementation for the API items */ public final class ApiItems implements IItems { - private IItemDefinition certusQuartzAxe; - private IItemDefinition certusQuartzHoe; - private IItemDefinition certusQuartzShovel; - private IItemDefinition certusQuartzPick; - private IItemDefinition certusQuartzSword; - private IItemDefinition certusQuartzWrench; - private IItemDefinition certusQuartzKnife; + private final IItemDefinition certusQuartzAxe; + private final IItemDefinition certusQuartzHoe; + private final IItemDefinition certusQuartzShovel; + private final IItemDefinition certusQuartzPick; + private final IItemDefinition certusQuartzSword; + private final IItemDefinition certusQuartzWrench; + private final IItemDefinition certusQuartzKnife; - private IItemDefinition netherQuartzAxe; - private IItemDefinition netherQuartzHoe; - private IItemDefinition netherQuartzShovel; - private IItemDefinition netherQuartzPick; - private IItemDefinition netherQuartzSword; - private IItemDefinition netherQuartzWrench; - private IItemDefinition netherQuartzKnife; + private final IItemDefinition netherQuartzAxe; + private final IItemDefinition netherQuartzHoe; + private final IItemDefinition netherQuartzShovel; + private final IItemDefinition netherQuartzPick; + private final IItemDefinition netherQuartzSword; + private final IItemDefinition netherQuartzWrench; + private final IItemDefinition netherQuartzKnife; - private IItemDefinition entropyManipulator; - private IItemDefinition wirelessTerminal; - private IItemDefinition biometricCard; - private IItemDefinition chargedStaff; - private IItemDefinition massCannon; - private IItemDefinition memoryCard; - private IItemDefinition networkTool; - private IItemDefinition portableCell; + private final IItemDefinition entropyManipulator; + private final IItemDefinition wirelessTerminal; + private final IItemDefinition biometricCard; + private final IItemDefinition chargedStaff; + private final IItemDefinition massCannon; + private final IItemDefinition memoryCard; + private final IItemDefinition networkTool; + private final IItemDefinition portableCell; - private IItemDefinition cellCreative; - private IItemDefinition viewCell; + private final IItemDefinition cellCreative; + private final IItemDefinition viewCell; - private IItemDefinition cell1k; - private IItemDefinition cell4k; - private IItemDefinition cell16k; - private IItemDefinition cell64k; + private final IItemDefinition cell1k; + private final IItemDefinition cell4k; + private final IItemDefinition cell16k; + private final IItemDefinition cell64k; - private IItemDefinition fluidCell1k; - private IItemDefinition fluidCell4k; - private IItemDefinition fluidCell16k; - private IItemDefinition fluidCell64k; + private final IItemDefinition fluidCell1k; + private final IItemDefinition fluidCell4k; + private final IItemDefinition fluidCell16k; + private final IItemDefinition fluidCell64k; - private IItemDefinition spatialCell2; - private IItemDefinition spatialCell16; - private IItemDefinition spatialCell128; + private final IItemDefinition spatialCell2; + private final IItemDefinition spatialCell16; + private final IItemDefinition spatialCell128; - private IItemDefinition facade; - private IItemDefinition certusCrystalSeed; - private IItemDefinition fluixCrystalSeed; - private IItemDefinition netherQuartzSeed; + private final IItemDefinition facade; + private final IItemDefinition certusCrystalSeed; + private final IItemDefinition fluixCrystalSeed; + private final IItemDefinition netherQuartzSeed; // rv1 - private IItemDefinition encodedPattern; - private IItemDefinition colorApplicator; + private final IItemDefinition encodedPattern; + private final IItemDefinition colorApplicator; - private AEColoredItemDefinition coloredPaintBall; - private AEColoredItemDefinition coloredLumenPaintBall; + private final AEColoredItemDefinition coloredPaintBall; + private final AEColoredItemDefinition coloredLumenPaintBall; // unsupported dev tools private IItemDefinition toolEraser; @@ -249,15 +249,15 @@ public final class ApiItems implements IItems { .props(storageCellProps).build(); FeatureFactory spatialCells = registry.features(AEFeature.SPATIAL_IO); -// FIXME FABRIC this.spatialCell2 = spatialCells -// FIXME FABRIC .item("2_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 2)) -// FIXME FABRIC .props(storageCellProps).build(); -// FIXME FABRIC this.spatialCell16 = spatialCells -// FIXME FABRIC .item("16_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 16)) -// FIXME FABRIC .props(storageCellProps).build(); -// FIXME FABRIC this.spatialCell128 = spatialCells -// FIXME FABRIC .item("128_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 128)) -// FIXME FABRIC .props(storageCellProps).build(); + this.spatialCell2 = spatialCells + .item("2_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 2)) + .props(storageCellProps).build(); + this.spatialCell16 = spatialCells + .item("16_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 16)) + .props(storageCellProps).build(); + this.spatialCell128 = spatialCells + .item("128_cubed_spatial_storage_cell", props -> new SpatialStorageCellItem(props, 128)) + .props(storageCellProps).build(); this.facade = registry.item("facade", FacadeItem::new).features(AEFeature.FACADES).build(); diff --git a/src/main/java/appeng/hooks/DynamicDimensions.java b/src/main/java/appeng/hooks/DynamicDimensions.java new file mode 100644 index 000000000..a6f48b409 --- /dev/null +++ b/src/main/java/appeng/hooks/DynamicDimensions.java @@ -0,0 +1,13 @@ +package appeng.hooks; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.chunk.ChunkGenerator; + +public interface DynamicDimensions { + + ServerWorld addWorld(RegistryKey worldId, RegistryKey dimensionTypeId, ChunkGenerator chunkGenerator); + +} diff --git a/src/main/java/appeng/hooks/RegisterDimensionTypeCallback.java b/src/main/java/appeng/hooks/RegisterDimensionTypeCallback.java new file mode 100644 index 000000000..ca8f6e53f --- /dev/null +++ b/src/main/java/appeng/hooks/RegisterDimensionTypeCallback.java @@ -0,0 +1,17 @@ +package appeng.hooks; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.util.registry.RegistryTracker; + +public interface RegisterDimensionTypeCallback { + + Event EVENT = EventFactory.createArrayBacked(RegisterDimensionTypeCallback.class, (listeners) -> (registryTracker) -> { + for (RegisterDimensionTypeCallback listener : listeners) { + listener.addDimensionTypes(registryTracker); + } + }); + + void addDimensionTypes(RegistryTracker.Modifiable registryTracker); + +} diff --git a/src/unported/java/appeng/items/storage/SpatialStorageCellItem.java b/src/main/java/appeng/items/storage/SpatialStorageCellItem.java similarity index 74% rename from src/unported/java/appeng/items/storage/SpatialStorageCellItem.java rename to src/main/java/appeng/items/storage/SpatialStorageCellItem.java index ab9a06a7a..02cdb1867 100644 --- a/src/unported/java/appeng/items/storage/SpatialStorageCellItem.java +++ b/src/main/java/appeng/items/storage/SpatialStorageCellItem.java @@ -30,8 +30,9 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.text.Text; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; -import net.minecraft.world.dimension.DimensionType; import net.fabricmc.api.Environment; import appeng.api.implementations.TransitionResult; @@ -58,17 +59,17 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag @Override public void appendTooltip(final ItemStack stack, final World world, final List lines, final TooltipContext advancedTooltips) { - final DimensionType dimType = this.getStoredDimension(stack); - if (dimType == null) { - lines.add(GuiText.Unformatted.text().formatted(Formatting.ITALIC)); + final RegistryKey worldId = this.getStoredDimension(stack); + if (worldId == null) { + lines.add(GuiText.Unformatted.text().copy().formatted(Formatting.ITALIC)); lines.add(GuiText.SpatialCapacity.text(maxRegion, maxRegion, maxRegion)); } else { - SpatialDimensionManager.INSTANCE.addCellDimensionTooltip(dimType, lines); + SpatialDimensionManager.INSTANCE.addCellDimensionTooltip(worldId, lines); } if (advancedTooltips.isAdvanced()) { - if (dimType != null && dimType.getRegistryName() != null) { - lines.add(new LiteralText("Dimension: " + dimType.getRegistryName())); + if (worldId != null && worldId.getValue() != null) { + lines.add(new LiteralText("Dimension: " + worldId.getValue())); } } } @@ -84,12 +85,12 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag } @Override - public DimensionType getStoredDimension(final ItemStack is) { + public RegistryKey getStoredDimension(final ItemStack is) { final CompoundTag c = is.getTag(); if (c != null && c.contains(TAG_DIMENSION_ID)) { try { - Identifier dimTypeId = new Identifier(c.getString(TAG_DIMENSION_ID)); - return DimensionType.byName(dimTypeId); + Identifier worldId = new Identifier(c.getString(TAG_DIMENSION_ID)); + return RegistryKey.of(Registry.DIMENSION, worldId); } catch (Exception e) { AELog.warn("Failed to retrieve storage cell dimension.", e); } @@ -109,27 +110,27 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag ISpatialDimension manager = SpatialDimensionManager.INSTANCE; - DimensionType storedDim = this.getStoredDimension(is); - if (storedDim == null) { - storedDim = manager.createNewCellDimension(targetSize); + RegistryKey worldId = this.getStoredDimension(is); + if (worldId == null || manager.getWorld(worldId) == null) { + worldId = manager.createNewCellDimension(targetSize); } - if (storedDim == null) { + if (worldId == null) { // Failed to create the dimension return new TransitionResult(false, 0); } try { - if (manager.isCellDimension(storedDim)) { - ServerWorld cellWorld = manager.getWorld(storedDim); + if (manager.isCellDimension(worldId)) { + ServerWorld cellWorld = manager.getWorld(worldId); - BlockPos scale = manager.getCellDimensionSize(storedDim); + BlockPos scale = manager.getCellDimensionSize(worldId); if (scale.equals(targetSize)) { if (targetX <= maxSize && targetY <= maxSize && targetZ <= maxSize) { - BlockPos offset = manager.getCellDimensionOrigin(storedDim); + BlockPos offset = manager.getCellDimensionOrigin(worldId); - this.setStoredDimension(is, storedDim); + this.setStoredDimension(is, worldId); StorageHelper.getInstance().swapRegions(w, min.x + 1, min.y + 1, min.z + 1, cellWorld, offset.getX(), offset.getY(), offset.getZ(), targetX - 1, targetY - 1, targetZ - 1); @@ -140,14 +141,14 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag return new TransitionResult(false, 0); } finally { // clean up newly created dimensions that failed transfer - if (manager.isCellDimension(storedDim) && this.getStoredDimension(is) == null) { - manager.deleteCellDimension(storedDim); + if (manager.isCellDimension(worldId) && this.getStoredDimension(is) == null) { + manager.deleteCellDimension(worldId); } } } - private void setStoredDimension(final ItemStack is, DimensionType dim) { + private void setStoredDimension(final ItemStack is, RegistryKey worldId) { final CompoundTag c = is.getOrCreateTag(); - c.putString(TAG_DIMENSION_ID, dim.getRegistryName().toString()); + c.putString(TAG_DIMENSION_ID, worldId.getValue().toString()); } } diff --git a/src/main/java/appeng/mixins/DimensionTypeMixin.java b/src/main/java/appeng/mixins/DimensionTypeMixin.java new file mode 100644 index 000000000..a8369fbbd --- /dev/null +++ b/src/main/java/appeng/mixins/DimensionTypeMixin.java @@ -0,0 +1,19 @@ +package appeng.mixins; + +import appeng.hooks.RegisterDimensionTypeCallback; +import net.minecraft.util.registry.RegistryTracker; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(DimensionType.class) +public class DimensionTypeMixin { + + @Inject(method="addRegistryDefaults", at=@At("TAIL")) + private static void addRegistryDefaults(RegistryTracker.Modifiable registryTracker, CallbackInfoReturnable cir) { + RegisterDimensionTypeCallback.EVENT.invoker().addDimensionTypes(registryTracker); + } + +} diff --git a/src/main/java/appeng/mixins/MinecraftServerMixin.java b/src/main/java/appeng/mixins/MinecraftServerMixin.java new file mode 100644 index 000000000..70cb20ac3 --- /dev/null +++ b/src/main/java/appeng/mixins/MinecraftServerMixin.java @@ -0,0 +1,95 @@ +package appeng.mixins; + +import appeng.hooks.DynamicDimensions; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.WorldGenerationProgressListener; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.RegistryTracker; +import net.minecraft.world.SaveProperties; +import net.minecraft.world.World; +import net.minecraft.world.border.WorldBorder; +import net.minecraft.world.border.WorldBorderListener; +import net.minecraft.world.dimension.DimensionOptions; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.GeneratorOptions; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.level.ServerWorldProperties; +import net.minecraft.world.level.UnmodifiableLevelProperties; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.concurrent.Executor; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin implements DynamicDimensions { + + @Shadow + private RegistryTracker.Modifiable dimensionTracker; + + @Shadow + private Map, ServerWorld> worlds; + + @Shadow + private SaveProperties saveProperties; + + @Shadow + private Executor workerExecutor; + + @Shadow + private LevelStorage.Session session; + + public ServerWorld addWorld(RegistryKey worldId, RegistryKey dimensionTypeId, ChunkGenerator chunkGenerator) { + Preconditions.checkArgument(!worlds.containsKey(worldId), "World with id %s already exists.", worldId.getValue()); + + // Each worlds must have a corresponding dimension options, otherwise they will not be re-created on load + GeneratorOptions generatorOptions = this.saveProperties.getGeneratorOptions(); + Preconditions.checkArgument(!generatorOptions.getDimensionMap().containsId(worldId.getValue()), + "Dimension config with id %s already exists.", worldId.getValue()); + + DimensionType dimensionType = dimensionTracker.getDimensionTypeRegistry().get(dimensionTypeId); + Preconditions.checkArgument(dimensionType != null, "dimensionTypeId %s is not registered", dimensionTypeId); + + // Create dimension options with the given world-id and chunk generator + DimensionOptions dimensionOptions = new DimensionOptions( + () -> dimensionTracker.getDimensionTypeRegistry().get(dimensionTypeId), + chunkGenerator + ); + + ServerWorldProperties serverWorldProperties = this.saveProperties.getMainWorldProperties(); + + // This sucks a little, but during startup, the server will use the same listener for every world, + // but it is ultimately only stored in the chunk storage. So we retrieve it from the overworld to + // mirror the original code as much as possible + ServerWorld overworld = worlds.get(ServerWorld.OVERWORLD); + Preconditions.checkState(overworld != null, "Overworld does not exist!"); + WorldGenerationProgressListener worldGenerationProgressListener = ((ThreadedAnvilChunkStorageAccessor) overworld.getChunkManager().threadedAnvilChunkStorage).getWorldGenerationProgressListener(); + + // Inherit seed + WorldBorder from overworld + long seed = overworld.getSeed(); + WorldBorder worldBorder = overworld.getWorldBorder(); + + MinecraftServer self = (MinecraftServer) (Object) this; + UnmodifiableLevelProperties unmodifiableLevelProperties = new UnmodifiableLevelProperties(this.saveProperties, serverWorldProperties); + ServerWorld world = new ServerWorld( + self, this.workerExecutor, this.session, unmodifiableLevelProperties, worldId, dimensionTypeId, dimensionType, worldGenerationProgressListener, chunkGenerator, false, seed, ImmutableList.of(), false + ); + worldBorder.addListener(new WorldBorderListener.WorldBorderSyncer(world.getWorldBorder())); + this.worlds.put(worldId, world); + + // Adding it here will cause the world to be re-created on server restart + RegistryKey dimOptKey = RegistryKey.of(Registry.DIMENSION_OPTIONS, worldId.getValue()); + generatorOptions.getDimensionMap().add(dimOptKey, dimensionOptions); + generatorOptions.getDimensionMap().markLoaded(dimOptKey); // Otherwise it wont be saved + // Ensure the save properties are saved, or the world will potentially be lost on restart + this.session.method_27426(this.dimensionTracker, this.saveProperties, self.getPlayerManager().getUserData()); + + return world; + } + +} diff --git a/src/main/java/appeng/mixins/ThreadedAnvilChunkStorageAccessor.java b/src/main/java/appeng/mixins/ThreadedAnvilChunkStorageAccessor.java new file mode 100644 index 000000000..297394675 --- /dev/null +++ b/src/main/java/appeng/mixins/ThreadedAnvilChunkStorageAccessor.java @@ -0,0 +1,14 @@ +package appeng.mixins; + +import net.minecraft.server.WorldGenerationProgressListener; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ThreadedAnvilChunkStorage.class) +public interface ThreadedAnvilChunkStorageAccessor { + + @Accessor + WorldGenerationProgressListener getWorldGenerationProgressListener(); + +} diff --git a/src/unported/java/appeng/spatial/CachedPlane.java b/src/main/java/appeng/spatial/CachedPlane.java similarity index 80% rename from src/unported/java/appeng/spatial/CachedPlane.java rename to src/main/java/appeng/spatial/CachedPlane.java index e2cf0ef1c..74c9a3e2f 100644 --- a/src/unported/java/appeng/spatial/CachedPlane.java +++ b/src/main/java/appeng/spatial/CachedPlane.java @@ -18,26 +18,6 @@ package appeng.spatial; -import java.util.ArrayList; -import java.util.List; -import java.util.Map.Entry; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.network.play.server.SChunkDataPacket; -import net.minecraft.util.Tickable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.EmptyBlockView; -import net.minecraft.world.ITickList; -import net.minecraft.world.NextTickListEntry; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.ChunkSection; -import net.minecraft.world.server.ServerChunkProvider; -import net.minecraft.world.server.ServerTickList; - import appeng.api.AEApi; import appeng.api.movable.IMovableHandler; import appeng.api.movable.IMovableRegistry; @@ -45,6 +25,26 @@ import appeng.api.util.AEPartLocation; import appeng.api.util.WorldCoord; import appeng.core.AELog; import appeng.core.worlddata.WorldData; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; +import net.minecraft.server.world.ServerChunkManager; +import net.minecraft.server.world.ServerTickScheduler; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Tickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ScheduledTick; +import net.minecraft.world.TickScheduler; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.WorldChunk; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; public class CachedPlane { private final int x_size; @@ -55,10 +55,10 @@ public class CachedPlane { private final int y_offset; private final int z_offset; private final int y_size; - private final Chunk[][] myChunks; + private final WorldChunk[][] myChunks; private final Column[][] myColumns; private final List tiles = new ArrayList<>(); - private final List> ticks = new ArrayList<>(); + private final List> ticks = new ArrayList<>(); private final World world; private final IMovableRegistry reg = AEApi.instance().registries().movable(); private final List updates = new ArrayList<>(); @@ -96,7 +96,7 @@ public class CachedPlane { final int cy_size = maxCY - minCY + 1; this.cz_size = maxCZ - minCZ + 1; - this.myChunks = new Chunk[this.cx_size][this.cz_size]; + this.myChunks = new WorldChunk[this.cx_size][this.cz_size]; this.myColumns = new Column[this.x_size][this.z_size]; this.verticalBits = 0; @@ -117,26 +117,27 @@ public class CachedPlane { for (int cz = 0; cz < this.cz_size; cz++) { final List deadTiles = new ArrayList<>(); - final Chunk c = w.getChunk(minCX + cx, minCZ + cz); + final WorldChunk c = w.getChunk(minCX + cx, minCZ + cz); this.myChunks[cx][cz] = c; - final List> rawTiles = new ArrayList<>(c.getBlockEntityMap().entrySet()); - for (final Entry tx : rawTiles) { - final BlockPos cp = tx.getKey(); - final BlockEntity te = tx.getValue(); + Set blockEntityPositions = c.getBlockEntityPositions(); + for (BlockPos tePOS : blockEntityPositions) { + final BlockEntity te = c.getBlockEntity(tePOS); + if (te == null) { + continue; + } - final BlockPos tePOS = te.getPos(); if (tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS.getZ() <= maxZ) { if (mr.askToMove(te)) { this.tiles.add(te); - deadTiles.add(cp); + deadTiles.add(tePOS); } else { final BlockStorageData details = new BlockStorageData(); this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData(tePOS.getY(), details); // don't skip air, just let the code replace it... - if (details.state.isAir(EmptyBlockView.INSTANCE, tePOS)) { + if (details.state.isAir()) { w.removeBlock(tePOS, false); } else { this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].setSkip(tePOS.getY()); @@ -146,20 +147,20 @@ public class CachedPlane { } for (final BlockPos cp : deadTiles) { - c.getBlockEntityMap().remove(cp); + c.removeBlockEntity(cp); } final long gameTime = this.getWorld().getTime(); - final ITickList pendingBlockTicks = this.getWorld().getPendingBlockTicks(); - if (pendingBlockTicks instanceof ServerTickList) { - List> pending = ((ServerTickList) pendingBlockTicks) - .getPending(c.getPos(), false, true); - for (final NextTickListEntry entry : pending) { - final BlockPos tePOS = entry.position; + final TickScheduler pendingBlockTicks = this.getWorld().getBlockTickScheduler(); + if (pendingBlockTicks instanceof ServerTickScheduler) { + List> pending = ((ServerTickScheduler) pendingBlockTicks) + .getScheduledTicksInChunk(c.getPos(), false, true); + for (final ScheduledTick entry : pending) { + final BlockPos tePOS = entry.pos; if (tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS.getZ() <= maxZ) { - this.ticks.add(new NextTickListEntry<>(tePOS, entry.getTarget(), - entry.scheduledTime - gameTime, entry.priority)); + this.ticks.add(new ScheduledTick<>(tePOS, entry.getObject(), + entry.time - gameTime, entry.priority)); } } } @@ -168,9 +169,9 @@ public class CachedPlane { for (final BlockEntity te : this.tiles) { try { - this.getWorld().loadedTileEntityList.remove(te); + this.getWorld().blockEntities.remove(te); if (te instanceof Tickable) { - this.getWorld().tickableTileEntities.remove(te); + this.getWorld().tickingBlockEntities.remove(te); } } catch (final Exception e) { AELog.debug(e); @@ -232,14 +233,14 @@ public class CachedPlane { dst, mr); } - for (final NextTickListEntry entry : this.ticks) { - final BlockPos tePOS = entry.position; + for (final ScheduledTick entry : this.ticks) { + final BlockPos tePOS = entry.pos; dst.addTick(tePOS.getX() - this.x_offset, tePOS.getY() - this.y_offset, tePOS.getZ() - this.z_offset, entry); } - for (final NextTickListEntry entry : dst.ticks) { - final BlockPos tePOS = entry.position; + for (final ScheduledTick entry : dst.ticks) { + final BlockPos tePOS = entry.pos; this.addTick(tePOS.getX() - dst.x_offset, tePOS.getY() - dst.y_offset, tePOS.getZ() - dst.z_offset, entry); } @@ -261,9 +262,9 @@ public class CachedPlane { } } - private void addTick(final int x, final int y, final int z, final NextTickListEntry entry) { + private void addTick(final int x, final int y, final int z, final ScheduledTick entry) { BlockPos where = new BlockPos(x + this.x_offset, y + this.y_offset, z + this.z_offset); - this.world.getPendingBlockTicks().scheduleTick(where, entry.getTarget(), (int) entry.scheduledTime, + this.world.getBlockTickScheduler().schedule(where, entry.getObject(), (int) entry.time, entry.priority); } @@ -284,7 +285,7 @@ public class CachedPlane { final BlockPos pos = new BlockPos(x, y, z); // attempt recovery... - c.c.addBlockEntity(te); + c.c.setBlockEntity(pos, te); this.world.updateListeners(pos, this.world.getBlockState(pos), this.world.getBlockState(pos), z); } @@ -303,7 +304,7 @@ public class CachedPlane { // update shit.. for (int x = 0; x < this.cx_size; x++) { for (int z = 0; z < this.cz_size; z++) { - final Chunk c = this.myChunks[x][z]; + final WorldChunk c = this.myChunks[x][z]; // FIXME: Light shit c.markDirty(); } @@ -313,22 +314,20 @@ public class CachedPlane { for (int x = 0; x < this.cx_size; x++) { for (int z = 0; z < this.cz_size; z++) { - final Chunk c = this.myChunks[x][z]; + final WorldChunk c = this.myChunks[x][z]; - for (int y = 1; y < 255; y += 32) { - WorldData.instance().compassData().service().updateArea(this.getWorld(), c.getPos(), y); - } + WorldData.instance().compassData().service().updateArea((ServerWorld) this.getWorld(), c); // FIXME this was sending chunks to players... - SChunkDataPacket cdp = new SChunkDataPacket(c, verticalBits); - ((ServerChunkProvider) world.getChunkManager()).chunkManager.getTrackingPlayers(c.getPos(), false) - .forEach(spe -> spe.connection.sendPacket(cdp)); + ChunkDataS2CPacket cdp = new ChunkDataS2CPacket(c, verticalBits, false); + ((ServerChunkManager) world.getChunkManager()).threadedAnvilChunkStorage.getPlayersWatchingChunk(c.getPos(), false) + .forEach(spe -> spe.networkHandler.sendPacket(cdp)); } } // FIXME check if this makes any sense at all to send changes to players asap - ServerChunkProvider serverChunkProvider = (ServerChunkProvider) world.getChunkManager(); + ServerChunkManager serverChunkProvider = (ServerChunkManager) world.getChunkManager(); serverChunkProvider.tick(() -> false); } @@ -356,7 +355,7 @@ public class CachedPlane { this.z = z; this.c = chunk; - final ChunkSection[] storage = this.c.getSections(); + final ChunkSection[] storage = this.c.getSectionArray(); // make sure storage exists before hand... for (int ay = 0; ay < chunkHeight; ay++) { @@ -372,7 +371,7 @@ public class CachedPlane { if (data.state == CachedPlane.this.matrixBlockState) { data.state = Blocks.AIR.getDefaultState(); } - final ChunkSection[] storage = this.c.getSections(); + final ChunkSection[] storage = this.c.getSectionArray(); final ChunkSection extendedBlockStorage = storage[y >> 4]; extendedBlockStorage.setBlockState(this.x, y & 15, this.z, data.state); // FIXME extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light @@ -380,7 +379,7 @@ public class CachedPlane { } private void fillData(final int y, BlockStorageData data) { - final ChunkSection[] storage = this.c.getSections(); + final ChunkSection[] storage = this.c.getSectionArray(); final ChunkSection extendedblockstorage = storage[y >> 4]; data.state = extendedblockstorage.getBlockState(this.x, y & 15, this.z); @@ -389,7 +388,7 @@ public class CachedPlane { } private boolean doNotSkip(final int y) { - final ChunkSection[] storage = this.c.getSections(); + final ChunkSection[] storage = this.c.getSectionArray(); final ChunkSection extendedblockstorage = storage[y >> 4]; if (CachedPlane.this.reg .isBlacklisted(extendedblockstorage.getBlockState(this.x, y & 15, this.z).getBlock())) { diff --git a/src/unported/java/appeng/spatial/ISpatialVisitor.java b/src/main/java/appeng/spatial/ISpatialVisitor.java similarity index 100% rename from src/unported/java/appeng/spatial/ISpatialVisitor.java rename to src/main/java/appeng/spatial/ISpatialVisitor.java diff --git a/src/main/java/appeng/spatial/SpatialDimensionExtraData.java b/src/main/java/appeng/spatial/SpatialDimensionExtraData.java new file mode 100644 index 000000000..e4f8fc07b --- /dev/null +++ b/src/main/java/appeng/spatial/SpatialDimensionExtraData.java @@ -0,0 +1,70 @@ +package appeng.spatial; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtHelper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.PersistentState; + +/** + * Helps with encoding and decoding the extra data we attach to each created + * storage dimension world as persistent state. + */ +public final class SpatialDimensionExtraData extends PersistentState { + + /** + * ID of this data when it is attached to a world. + */ + public static final String ID = "ae2_spatial_info"; + + // Used to allow forward compatibility + private static final int CURRENT_FORMAT = 1; + + private static final String TAG_FORMAT = "format"; + + private static final String TAG_SIZE = "size"; + + /** + * The storage size of this dimension. This is dicateted by the pylon structure + * size used to perform the first transfer into this dimension. Once it's set, + * it cannot be changed anymore. + */ + private BlockPos size = BlockPos.ORIGIN; + + public SpatialDimensionExtraData() { + super(ID); + } + + public SpatialDimensionExtraData(BlockPos size) { + super(ID); + this.size = size; + } + + public BlockPos getSize() { + return size; + } + + public void setSize(BlockPos size) { + this.size = size; + setDirty(true); + } + + @Override + public void fromTag(CompoundTag tag) { + int version = tag.getInt(TAG_FORMAT); + if (version != CURRENT_FORMAT) { + // Currently no new format has been defined, as such anything but the current + // version is invalid + throw new IllegalStateException("Invalid AE2 spatial info version: " + version); + } + + size = NbtHelper.toBlockPos(tag.getCompound(TAG_SIZE)); + } + + @Override + public CompoundTag toTag(CompoundTag tag) { + tag.putInt(TAG_FORMAT, CURRENT_FORMAT); + tag.put(TAG_SIZE, NbtHelper.fromBlockPos(size)); + return tag; + } + +} diff --git a/src/unported/java/appeng/spatial/SpatialDimensionManager.java b/src/main/java/appeng/spatial/SpatialDimensionManager.java similarity index 55% rename from src/unported/java/appeng/spatial/SpatialDimensionManager.java rename to src/main/java/appeng/spatial/SpatialDimensionManager.java index 0e863927d..9a773bcfa 100644 --- a/src/unported/java/appeng/spatial/SpatialDimensionManager.java +++ b/src/main/java/appeng/spatial/SpatialDimensionManager.java @@ -18,28 +18,34 @@ package appeng.spatial; -import java.util.List; -import java.util.Locale; - -import javax.annotation.Nullable; - -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.text.Text; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.server.world.ServerWorld; -import net.minecraftforge.common.DimensionManager; -import net.minecraftforge.fml.server.ServerLifecycleHooks; - import appeng.api.storage.ISpatialDimension; import appeng.core.AELog; import appeng.core.AppEng; import appeng.core.localization.GuiText; +import appeng.hooks.DynamicDimensions; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Locale; public final class SpatialDimensionManager implements ISpatialDimension { + // A region file is 512x512 blocks (32x32 chunks), + // to avoid creating the 4 regions around 0,0,0, + // we move the origin to the middle of region 0,0 + public static final BlockPos REGION_CENTER = new BlockPos(512 / 2, 64, 512 / 2); + + public static final RegistryKey STORAGE_DIMENSION_TYPE = RegistryKey.of(Registry.DIMENSION_TYPE_KEY, AppEng.makeId("storage_cell")); + public static final ISpatialDimension INSTANCE = new SpatialDimensionManager(); private static final String DIM_ID_PREFIX = "spatial_"; @@ -48,18 +54,26 @@ public final class SpatialDimensionManager implements ISpatialDimension { } @Override - public ServerWorld getWorld(DimensionType cellDim) { - return DimensionManager.getWorld(getServer(), cellDim, true, true); + public ServerWorld getWorld(RegistryKey cellDim) { + MinecraftServer server = getServer(); + return server.getWorld(cellDim); } @Override - public DimensionType createNewCellDimension(BlockPos size) { + public RegistryKey createNewCellDimension(BlockPos size) { Identifier dimKey = findFreeDimensionId(); AELog.info("Allocating storage cell dimension '%s'", dimKey); - PacketByteBuf extraData = new SpatialDimensionExtraData(size).write(); + DynamicDimensions dynamicDimensions = (DynamicDimensions) getServer(); - return DimensionManager.registerDimension(dimKey, StorageCellModDimension.INSTANCE, extraData, true); + RegistryKey worldId = RegistryKey.of(Registry.DIMENSION, dimKey); + + ServerWorld world = dynamicDimensions.addWorld(worldId, STORAGE_DIMENSION_TYPE, StorageChunkGenerator.INSTANCE); + + SpatialDimensionExtraData spatialExtraData = world.getPersistentStateManager().getOrCreate(SpatialDimensionExtraData::new, SpatialDimensionExtraData.ID); + spatialExtraData.setSize(size); + + return worldId; } /** @@ -68,8 +82,8 @@ public final class SpatialDimensionManager implements ISpatialDimension { */ private Identifier findFreeDimensionId() { int maxId = 0; - for (DimensionType dimensionType : DimensionType.getAll()) { - Identifier regName = dimensionType.getRegistryName(); + for (RegistryKey worldId : getServer().getWorldRegistryKeys()) { + Identifier regName = worldId.getValue(); if (regName == null || !AppEng.MOD_ID.equals(regName.getNamespace())) { continue; } @@ -93,42 +107,52 @@ public final class SpatialDimensionManager implements ISpatialDimension { } @Override - public void deleteCellDimension(DimensionType cellDim) { - AELog.info("Unregistering storage cell dimension %s", cellDim.getRegistryName()); + public void deleteCellDimension(RegistryKey worldId) { + AELog.info("Unregistering storage cell dimension %s", worldId.getValue()); MinecraftServer server = getServer(); - ServerWorld world = DimensionManager.getWorld(server, cellDim, false, false); - if (world != null) { - DimensionManager.unloadWorld(world); - } - DimensionManager.unloadWorlds(server, true); - DimensionManager.unregisterDimension(cellDim.getId()); +// FIXME FABRIC ServerWorld world = DimensionManager.getWorld(server, worldId, false, false); +// FIXME FABRIC if (world != null) { +// FIXME FABRIC DimensionManager.unloadWorld(world); +// FIXME FABRIC } +// FIXME FABRIC DimensionManager.unloadWorlds(server, true); +// FIXME FABRIC DimensionManager.unregisterDimension(worldId.getId()); + throw new IllegalStateException(); } @Override - public boolean isCellDimension(DimensionType cellDim) { - // Check if the cell dimension type is even registered - if (cellDim.getRegistryName() == null || !cellDim.getRegistryName().equals(DimensionType.getKey(cellDim))) { + public boolean isCellDimension(RegistryKey worldId) { + Identifier id = worldId.getValue(); + if (!id.getNamespace().equals(AppEng.MOD_ID)) { + return false; // World belongs to a different mod + } + if (!id.getPath().startsWith(DIM_ID_PREFIX)) { return false; } - return cellDim.getModType() instanceof StorageCellModDimension; + // Check that the world has the right dimension type + ServerWorld world = getServer().getWorld(worldId); + if (world == null) { + return false; // Non-existent world + } + + return world.getDimensionRegistryKey().equals(STORAGE_DIMENSION_TYPE); } @Override - public BlockPos getCellDimensionOrigin(DimensionType cellDim) { - return StorageCellDimension.REGION_CENTER; + public BlockPos getCellDimensionOrigin(RegistryKey worldId) { + return REGION_CENTER; } @Override - public BlockPos getCellDimensionSize(DimensionType cellDim) { - SpatialDimensionExtraData extraData = getExtraData(cellDim); + public BlockPos getCellDimensionSize(RegistryKey worldId) { + SpatialDimensionExtraData extraData = getExtraData(worldId); return extraData != null ? extraData.getSize() : BlockPos.ORIGIN; } @Override - public void addCellDimensionTooltip(DimensionType cellDim, List lines) { + public void addCellDimensionTooltip(RegistryKey worldId, List lines) { // Check if the cell dimension type is even registered - Identifier registryName = cellDim.getRegistryName(); + Identifier registryName = worldId.getValue(); if (registryName == null || !AppEng.MOD_ID.equals(registryName.getNamespace())) { return; } @@ -138,7 +162,7 @@ public final class SpatialDimensionManager implements ISpatialDimension { } // Add the actual stored size - BlockPos size = SpatialDimensionManager.INSTANCE.getCellDimensionSize(cellDim); + BlockPos size = SpatialDimensionManager.INSTANCE.getCellDimensionSize(worldId); lines.add(GuiText.StoredSize.text(size.getX(), size.getY(), size.getZ())); // Add a serial number to allows players to keep different cells apart @@ -156,15 +180,17 @@ public final class SpatialDimensionManager implements ISpatialDimension { } @Nullable - private SpatialDimensionExtraData getExtraData(DimensionType cellDim) { - if (!(cellDim.getModType() instanceof StorageCellModDimension)) { + private SpatialDimensionExtraData getExtraData(RegistryKey worldId) { + ServerWorld world = getWorld(worldId); + if (world == null) { return null; } - return SpatialDimensionExtraData.read(cellDim.getData()); + + return world.getPersistentStateManager().get(SpatialDimensionExtraData::new, SpatialDimensionExtraData.ID); } private static MinecraftServer getServer() { - return ServerLifecycleHooks.getCurrentServer(); + return AppEng.instance().getServer(); } } diff --git a/src/main/java/appeng/spatial/StorageCellBiome.java b/src/main/java/appeng/spatial/StorageCellBiome.java new file mode 100644 index 000000000..3b1f9572b --- /dev/null +++ b/src/main/java/appeng/spatial/StorageCellBiome.java @@ -0,0 +1,51 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 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 Applied Energistics 2. If not, see . + */ + +package appeng.spatial; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder; +import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder; + +public class StorageCellBiome extends Biome { + + public static final StorageCellBiome INSTANCE = new StorageCellBiome(); + + public StorageCellBiome() { + super(new Biome.Settings().surfaceBuilder(new ConfiguredSurfaceBuilder<>(SurfaceBuilder.NOPE, SurfaceBuilder.STONE_CONFIG)) + .precipitation(Precipitation.NONE).category(Category.NONE).depth(0).scale(1) + // Copied from the vanilla void biome + .temperature(0.5F).downfall(0.5F) + .effects(new BiomeEffects.Builder() + .waterColor(4159204) + .waterFogColor(329011) + .fogColor(0) + .build()) + .parent(null)); + } + + @Override + @Environment(EnvType.CLIENT) + public int getSkyColor() { + return 0x111111; + } + +} diff --git a/src/main/java/appeng/spatial/StorageChunkGenerator.java b/src/main/java/appeng/spatial/StorageChunkGenerator.java new file mode 100644 index 000000000..f5912a816 --- /dev/null +++ b/src/main/java/appeng/spatial/StorageChunkGenerator.java @@ -0,0 +1,132 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 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 Applied Energistics 2. If not, see . + */ + +package appeng.spatial; + +import appeng.api.AEApi; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.Heightmap; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.biome.source.BiomeAccess; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.biome.source.FixedBiomeSource; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.StructuresConfig; +import net.minecraft.world.gen.chunk.VerticalBlockSample; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Optional; + +public class StorageChunkGenerator extends ChunkGenerator { + + private final VerticalBlockSample columnSample; + + public static final StorageChunkGenerator INSTANCE = new StorageChunkGenerator(); + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> + instance.stable(INSTANCE)); + + private final BlockState defaultBlockState; + + private StorageChunkGenerator() { + super(createBiomeProvider(), createSettings()); + this.defaultBlockState = AEApi.instance().definitions().blocks().matrixFrame().block().getDefaultState(); + + // Vertical sample is mostly used for Feature generation, for those purposes we're all filled with matrix blocks + BlockState[] columnSample = new BlockState[256]; + Arrays.fill(columnSample, this.defaultBlockState); + this.columnSample = new VerticalBlockSample(columnSample); + } + + @Override + protected Codec method_28506() { + return CODEC; + } + + private static BiomeSource createBiomeProvider() { + return new FixedBiomeSource(StorageCellBiome.INSTANCE); + } + + private static StructuresConfig createSettings() { + return new StructuresConfig(Optional.empty(), Collections.emptyMap()); + } + + @Override + public void buildSurface(ChunkRegion region, Chunk chunk) { + this.fillChunk(chunk); + chunk.setShouldSave(false); + } + + private void fillChunk(Chunk chunk) { + BlockPos.Mutable mutPos = new BlockPos.Mutable(); + for (int cx = 0; cx < 16; cx++) { + mutPos.setX(cx); + for (int cz = 0; cz < 16; cz++) { + // FIXME: It's likely a bad idea to fill Y in the inner-loop given the storage + // layout of chunks + mutPos.setZ(cz); + for (int cy = 0; cy < 256; cy++) { + mutPos.setY(cy); + chunk.setBlockState(mutPos, defaultBlockState, false); + } + } + } + } + + @Override + public int getSeaLevel() { + return 0; + } + + @Override + public ChunkGenerator withSeed(long seed) { + return this; + } + + @Override + public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) { + } + + @Override + public BlockView getColumnSample(int x, int z) { + return columnSample; + } + + @Override + public int getHeight(int p_222529_1_, int p_222529_2_, Heightmap.Type heightmapType) { + return 0; + } + + @Override + public void generateFeatures(ChunkRegion region, StructureAccessor accessor) { + } + + @Override + public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) { + } + +} diff --git a/src/unported/java/appeng/spatial/StorageHelper.java b/src/main/java/appeng/spatial/StorageHelper.java similarity index 97% rename from src/unported/java/appeng/spatial/StorageHelper.java rename to src/main/java/appeng/spatial/StorageHelper.java index 80a2ca83e..860903919 100644 --- a/src/unported/java/appeng/spatial/StorageHelper.java +++ b/src/main/java/appeng/spatial/StorageHelper.java @@ -18,24 +18,26 @@ package appeng.spatial; -import java.util.ArrayList; -import java.util.List; - +import appeng.api.AEApi; +import appeng.api.util.WorldCoord; +import appeng.core.AppEng; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.math.Box; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; import net.minecraft.world.chunk.ChunkStatus; -import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.dimension.DimensionType; -import appeng.api.AEApi; -import appeng.api.util.WorldCoord; -import appeng.core.AppEng; +import java.util.ArrayList; +import java.util.List; public class StorageHelper { @@ -95,7 +97,7 @@ public class StorageHelper { newWorld.getChunkManager().getChunk(MathHelper.floor(link.x) >> 4, MathHelper.floor(link.z) >> 4, ChunkStatus.FULL, true); - if (entity instanceof ServerPlayerEntity && link.dim.getDimension() instanceof StorageCellDimension) { + if (entity instanceof ServerPlayerEntity && link.dim.getDimensionRegistryKey().equals(SpatialDimensionManager.STORAGE_DIMENSION_TYPE)) { AppEng.instance().getAdvancementTriggers().getSpatialExplorer().trigger((ServerPlayerEntity) entity); } diff --git a/src/main/java/appeng/tile/spatial/SpatialIOPortBlockEntity.java b/src/main/java/appeng/tile/spatial/SpatialIOPortBlockEntity.java index 0f234d9a6..35cd7858f 100644 --- a/src/main/java/appeng/tile/spatial/SpatialIOPortBlockEntity.java +++ b/src/main/java/appeng/tile/spatial/SpatialIOPortBlockEntity.java @@ -117,10 +117,10 @@ public class SpatialIOPortBlockEntity extends AENetworkInvBlockEntity implements @Override public Void call(final World world) throws Exception { - if (!(world instanceof ServerWorld)) { + if (!(this.world instanceof ServerWorld)) { return null; } - ServerWorld serverWorld = (ServerWorld) world; + ServerWorld serverWorld = (ServerWorld) this.world; final ItemStack cell = this.inv.getInvStack(0); if (this.isSpatialCell(cell) && this.inv.getInvStack(1).isEmpty()) { diff --git a/src/main/resources/appliedenergistics2.accesswidener b/src/main/resources/appliedenergistics2.accesswidener index 64272da32..46f1851fc 100644 --- a/src/main/resources/appliedenergistics2.accesswidener +++ b/src/main/resources/appliedenergistics2.accesswidener @@ -16,3 +16,5 @@ accessible method net/minecraft/data/server/RecipesProvider saveRecipeAdvancemen accessible method net/minecraft/data/server/BlockLootTableGenerator dropsWithSilkTouch (Lnet/minecraft/block/Block;Lnet/minecraft/loot/entry/LootPoolEntry$Builder;)Lnet/minecraft/loot/LootTable$Builder; accessible method net/minecraft/data/server/BlockLootTableGenerator applyExplosionDecay (Lnet/minecraft/item/ItemConvertible;Lnet/minecraft/loot/function/LootFunctionConsumingBuilder;)Ljava/lang/Object; + +accessible method net/minecraft/world/dimension/DimensionType (Ljava/util/OptionalLong;ZZZZZZZZZILnet/minecraft/util/Identifier;F)V diff --git a/src/main/resources/appliedenergistics2.mixins.json b/src/main/resources/appliedenergistics2.mixins.json index 322230c56..2083755e3 100644 --- a/src/main/resources/appliedenergistics2.mixins.json +++ b/src/main/resources/appliedenergistics2.mixins.json @@ -9,7 +9,10 @@ "ScreenHandlerListeners", "ShapelessRecipeMixin", "SlotMixin", - "TntAccessor" + "TntAccessor", + "DimensionTypeMixin", + "MinecraftServerMixin", + "ThreadedAnvilChunkStorageAccessor" ], "client": [ "ModelsReloadMixin", diff --git a/src/main/resources/assets/appliedenergistics2/models/block/chest/base.json b/src/main/resources/assets/appliedenergistics2/models/block/chest/base.json index 88dc5b2a4..1d5df6cb3 100644 --- a/src/main/resources/assets/appliedenergistics2/models/block/chest/base.json +++ b/src/main/resources/assets/appliedenergistics2/models/block/chest/base.json @@ -1,12 +1,25 @@ { - "parent": "block/cube", - "textures": { - "particle": "appliedenergistics2:block/chest/side", - "up": "appliedenergistics2:block/chest/top", - "down": "appliedenergistics2:block/chest/bottom", - "north": "appliedenergistics2:block/chest/front", - "east": "appliedenergistics2:block/chest/side", - "south": "appliedenergistics2:block/chest/side", - "west": "appliedenergistics2:block/chest/side" - } -} + "credit": "Made with Blockbench", + "parent": "block/cube", + "textures": { + "up": "appliedenergistics2:block/chest/top", + "down": "appliedenergistics2:block/chest/bottom", + "north": "appliedenergistics2:block/chest/front", + "particle": "appliedenergistics2:block/chest/side", + "east": "appliedenergistics2:block/chest/side" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#north"}, + "east": {"uv": [0, 0, 16, 16], "texture": "#east"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#east"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#east"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#up"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#down"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/models/block/spatial_pylon.json b/src/main/resources/assets/appliedenergistics2/models/block/spatial_pylon.json deleted file mode 100644 index bb881bbfd..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/spatial_pylon.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "appliedenergistics2:spatial_pylon" -} diff --git a/src/test/java/appeng/core/worlddata/SpatialDimensionExtraDataTest.java b/src/test/java/appeng/core/worlddata/SpatialDimensionExtraDataTest.java deleted file mode 100644 index 0c68507b2..000000000 --- a/src/test/java/appeng/core/worlddata/SpatialDimensionExtraDataTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package appeng.core.worlddata; - -import static org.junit.Assert.*; - -import net.minecraft.network.PacketByteBuf; -import org.junit.Test; - -import io.netty.buffer.Unpooled; - -import net.minecraft.util.math.BlockPos; - -import appeng.spatial.SpatialDimensionExtraData; - -public class SpatialDimensionExtraDataTest { - - /** - * The returned buffer should have just the right capacity. - */ - @Test - public void testCreatedBufferSize() { - PacketByteBuf buffer = new SpatialDimensionExtraData(BlockPos.ORIGIN).write(); - assertEquals(1 + 8 + 8, buffer.array().length); - } - - @Test - public void testReadWriteSize() { - BlockPos capacity = new BlockPos(1, 2, 3); - PacketByteBuf buffer = new SpatialDimensionExtraData(capacity).write(); - - PacketByteBuf readBackBuf = new PacketByteBuf(Unpooled.wrappedBuffer(buffer.array())); - SpatialDimensionExtraData extraData = SpatialDimensionExtraData.read(readBackBuf); - assertNotNull(extraData); - assertEquals(capacity, extraData.getSize()); - } - - /** - * Gracefully handle format version errors. - */ - @Test - public void testHandleInvalidFormatVersion() { - PacketByteBuf buffer = new SpatialDimensionExtraData(BlockPos.ORIGIN).write(); - buffer.writerIndex(0); - buffer.writeByte(5); - - PacketByteBuf readBackBuf = new PacketByteBuf(Unpooled.wrappedBuffer(buffer.array())); - assertNull(SpatialDimensionExtraData.read(readBackBuf)); - } - -} \ No newline at end of file diff --git a/src/unported/java/appeng/attributes/NullSpatialDimension.java b/src/unported/java/appeng/attributes/NullSpatialDimension.java deleted file mode 100644 index 9432b4a69..000000000 --- a/src/unported/java/appeng/attributes/NullSpatialDimension.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved. - * - * Applied Energistics 2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Applied Energistics 2 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 Applied Energistics 2. If not, see . - */ - -package appeng.attributes; - -import java.util.List; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.text.Text; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.server.world.ServerWorld; - -import appeng.api.storage.ISpatialDimension; - -class NullSpatialDimension implements ISpatialDimension { - @Override - public DimensionType createNewCellDimension(BlockPos size) { - return null; - } - - @Override - public void deleteCellDimension(DimensionType cellStorageId) { - } - - @Override - public BlockPos getCellDimensionOrigin(DimensionType cellStorageId) { - return null; - } - - @Override - public BlockPos getCellDimensionSize(DimensionType cellDim) { - return BlockPos.ORIGIN; - } - - @Override - public void addCellDimensionTooltip(DimensionType cellDim, List tooltip) { - } - - @Override - public ServerWorld getWorld(DimensionType cellStorageId) { - return null; - } - - @Override - public boolean isCellDimension(DimensionType cellDimID) { - return false; - } -} diff --git a/src/unported/java/appeng/spatial/SpatialDimensionExtraData.java b/src/unported/java/appeng/spatial/SpatialDimensionExtraData.java deleted file mode 100644 index 388be4850..000000000 --- a/src/unported/java/appeng/spatial/SpatialDimensionExtraData.java +++ /dev/null @@ -1,70 +0,0 @@ -package appeng.spatial; - -import javax.annotation.Nullable; - -import io.netty.buffer.Unpooled; - -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.math.BlockPos; - -import appeng.core.AELog; - -/** - * Helps with encoding and decoding the extra data we attach to the spatial - * {@link net.minecraft.world.dimension.DimensionType} as "extra data". Keep in - * mind this data will also be sent to the client unless - * {@link net.minecraftforge.common.ModDimension#write(PacketByteBuf, boolean)} - * is overridden. - */ -public final class SpatialDimensionExtraData { - - // Used to allow forward compatibility - private static final int CURRENT_FORMAT = 1; - - /** - * The storage size of this dimension. This is dicateted by the pylon structure - * size used to perform the first transfer into this dimension. Once it's set, - * it cannot be changed anymore. - */ - private final BlockPos size; - - public SpatialDimensionExtraData(BlockPos size) { - this.size = size; - } - - public PacketByteBuf write() { - PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); - buf.writeByte(CURRENT_FORMAT); - buf.writeBlockPos(size); - buf.capacity(buf.writerIndex()); // This cuts the backing buffer to the required size - return buf; - } - - public BlockPos getSize() { - return size; - } - - @Nullable - public static SpatialDimensionExtraData read(@Nullable PacketByteBuf buf) { - if (buf == null) { - return null; - } - - try { - buf.readerIndex(0); - byte version = buf.readByte(); - if (version != CURRENT_FORMAT) { - // Currently no new format has been defined, as such anything but the current - // version is invalid - return null; - } - - BlockPos size = buf.readBlockPos(); - return new SpatialDimensionExtraData(size); - } catch (IndexOutOfBoundsException e) { - AELog.warn(e, "Failed to read spatial storage dimension data."); - return null; - } - } - -} diff --git a/src/unported/java/appeng/spatial/StorageCellBiome.java b/src/unported/java/appeng/spatial/StorageCellBiome.java deleted file mode 100644 index ac3cf0b01..000000000 --- a/src/unported/java/appeng/spatial/StorageCellBiome.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. - * - * Applied Energistics 2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Applied Energistics 2 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 Applied Energistics 2. If not, see . - */ - -package appeng.spatial; - -import net.minecraft.util.SharedSeedRandom; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; -import net.minecraft.world.WorldView; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.GenerationSettings; -import net.minecraft.world.gen.GenerationStep; -import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -public class StorageCellBiome extends Biome { - - public static final StorageCellBiome INSTANCE = new StorageCellBiome(); - - static { - INSTANCE.setRegistryName("appliedenergistics2:storage"); - } - - public StorageCellBiome() { - super(new Biome.Builder().surfaceBuilder(SurfaceBuilder.NOPE, SurfaceBuilder.STONE_STONE_GRAVEL_CONFIG) - .precipitation(RainType.NONE).category(Category.NONE).depth(0).scale(1) - // Copied from the vanilla void biome - .temperature(0.5F).downfall(0.5F).waterColor(4159204).waterFogColor(329011).parent(null)); - } - - @Override - @Environment(EnvType.CLIENT) - public int getSkyColor() { - return 0x111111; - } - - @Override - public boolean doesWaterFreeze(WorldView worldIn, BlockPos pos) { - return false; - } - - @Override - public boolean doesWaterFreeze(WorldView worldIn, BlockPos water, boolean mustBeAtEdge) { - return false; - } - - @Override - public boolean doesSnowGenerate(WorldView worldIn, BlockPos pos) { - return false; - } - - @Override - public void decorate(GenerationStep.Decoration stage, ChunkGenerator chunkGenerator, - WorldAccess worldIn, long seed, SharedSeedRandom random, BlockPos pos) { - // Nothing should ever generate here... - } -} diff --git a/src/unported/java/appeng/spatial/StorageCellDimension.java b/src/unported/java/appeng/spatial/StorageCellDimension.java index 0bb4b31a1..129a89473 100644 --- a/src/unported/java/appeng/spatial/StorageCellDimension.java +++ b/src/unported/java/appeng/spatial/StorageCellDimension.java @@ -35,11 +35,6 @@ import appeng.client.render.SpatialSkyRender; public class StorageCellDimension extends Dimension { - // A region file is 512x512 blocks (32x32 chunks), - // to avoid creating the 4 regions around 0,0,0, - // we move the origin to the middle of region 0,0 - public static final BlockPos REGION_CENTER = new BlockPos(512 / 2, 64, 512 / 2); - public StorageCellDimension(World world, DimensionType dimensionType) { // FIXME: check light value super(world, dimensionType, 1.0f); diff --git a/src/unported/java/appeng/spatial/StorageChunkGenerator.java b/src/unported/java/appeng/spatial/StorageChunkGenerator.java deleted file mode 100644 index e7ca80638..000000000 --- a/src/unported/java/appeng/spatial/StorageChunkGenerator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. - * - * Applied Energistics 2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Applied Energistics 2 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 Applied Energistics 2. If not, see . - */ - -package appeng.spatial; - -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; -import net.minecraft.world.World; -import net.minecraft.world.biome.provider.BiomeProvider; -import net.minecraft.world.biome.provider.SingleBiomeProvider; -import net.minecraft.world.biome.provider.SingleBiomeProviderSettings; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.GenerationSettings; -import net.minecraft.world.Heightmap; -import net.minecraft.world.gen.WorldGenRegion; - -import appeng.api.AEApi; - -public class StorageChunkGenerator extends ChunkGenerator { - - private final BlockState defaultBlockState; - - public StorageChunkGenerator(final World world) { - super(world, createBiomeProvider(), createSettings()); - this.defaultBlockState = AEApi.instance().definitions().blocks().matrixFrame().block().getDefaultState(); - } - - private static BiomeProvider createBiomeProvider() { - SingleBiomeProviderSettings biomeSettings = new SingleBiomeProviderSettings(null); - biomeSettings.setBiome(StorageCellBiome.INSTANCE); - return new SingleBiomeProvider(biomeSettings); - } - - private static GenerationSettings createSettings() { - return new GenerationSettings(); - } - - @Override - public void generateSurface(WorldGenRegion region, Chunk chunk) { - this.fillChunk(chunk); - chunk.setModified(false); - } - - private void fillChunk(Chunk chunk) { - BlockPos.Mutable mutPos = new BlockPos.Mutable(); - for (int cx = 0; cx < 16; cx++) { - mutPos.setX(cx); - for (int cz = 0; cz < 16; cz++) { - // FIXME: It's likely a bad idea to fill Y in the inner-loop given the storage - // layout of chunks - mutPos.setZ(cz); - for (int cy = 0; cy < 256; cy++) { - mutPos.setY(cy); - chunk.setBlockState(mutPos, defaultBlockState, false); - } - } - } - } - - @Override - public int getGroundHeight() { - return 0; - } - - @Override - public void makeBase(WorldAccess worldIn, Chunk chunkIn) { - } - - @Override - public int getHeight(int p_222529_1_, int p_222529_2_, Heightmap.Type heightmapType) { - return 0; - } - - @Override - public void decorate(WorldGenRegion region) { - // Do not decorate chunks at all - } - -}