Merge fixes

This commit is contained in:
Sebastian Hartte
2020-08-11 00:09:08 +02:00
121 changed files with 1684 additions and 1995 deletions
@@ -26,6 +26,8 @@ package appeng.api.config;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import java.util.Locale;
/**
* Represent the security systems basic permissions, these are not for
* anti-griefing, they are part of the mod as a gameplay feature.
@@ -61,7 +63,7 @@ public enum SecurityPermissions {
*/
SECURITY;
private final String translationKey = "gui.appliedenergistics2.security." + this.name().toLowerCase();
private final String translationKey = "gui.appliedenergistics2.security." + this.name().toLowerCase(Locale.ROOT);
public String getTranslatedName() {
return this.translationKey + ".name";
@@ -1,38 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2013 AlgorithmX2
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package appeng.api.implementations;
/**
* Defines the result of performing a transition from the world into a storage
* cell, if its possible, and what the energy usage is.
*/
public class TransitionResult {
public final boolean success;
public final double energyUsage;
public TransitionResult(final boolean success, final double power) {
this.success = success;
this.energyUsage = power;
}
}
@@ -30,7 +30,6 @@ import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import appeng.api.implementations.TransitionResult;
import appeng.api.util.WorldCoord;
/**
@@ -53,13 +52,13 @@ public interface ISpatialStorageCell {
int getMaxStoredDim(ItemStack is);
/**
* get the currently stored Dimension id.
* get the currently stored spatial storage plot id.
*
* @param is spatial storage cell
*
* @return dimension id or -1
* @return plot id or -1
*/
RegistryKey<World> getStoredDimension(ItemStack is);
int getAllocatedPlotId(ItemStack is);
/**
* Perform a spatial swap with the contents of the cell, and the world.
@@ -70,7 +69,7 @@ public interface ISpatialStorageCell {
* @param max max coord
* @param playerId owner of current grid or -1
*
* @return result of transition
* @return success of transition
*/
TransitionResult doSpatialTransition(ItemStack is, ServerWorld w, WorldCoord min, WorldCoord max, int playerId);
boolean doSpatialTransition(ItemStack is, ServerWorld w, WorldCoord min, WorldCoord max, int playerId);
}
@@ -1,52 +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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.api.storage;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
public interface ISpatialDimension {
ServerWorld getWorld(RegistryKey<World> cellDim);
@Nullable
RegistryKey<World> createNewCellDimension(BlockPos capacity);
void deleteCellDimension(RegistryKey<World> cellDim);
boolean isCellDimension(RegistryKey<World> cellDim);
BlockPos getCellDimensionOrigin(RegistryKey<World> cellDim);
BlockPos getCellDimensionSize(RegistryKey<World> cellDim);
/**
* Adds a user-facing tooltip that describes this dimension so that a player can
* keep storage cells apart.
*/
void addCellDimensionTooltip(RegistryKey<World> cellDim, List<Text> lines);
}
@@ -18,6 +18,8 @@
package appeng.block.networking;
import java.util.Locale;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
@@ -52,7 +54,7 @@ public class WirelessBlock extends AEBaseTileBlock<WirelessBlockEntity> {
@Override
public String asString() {
return this.name().toLowerCase();
return this.name().toLowerCase(Locale.ROOT);
}
}
+3 -1
View File
@@ -1,6 +1,8 @@
package appeng.client;
import java.util.Locale;
import org.lwjgl.glfw.GLFW;
public enum ActionKey {
@@ -13,7 +15,7 @@ public enum ActionKey {
}
public String getTranslationKey() {
return "key." + this.name().toLowerCase() + ".desc";
return "key." + this.name().toLowerCase(Locale.ROOT) + ".desc";
}
public int getDefaultKey() {
@@ -1,5 +1,7 @@
package appeng.client.gui.implementations;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.LongConsumer;
@@ -7,13 +9,13 @@ import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.NumberEntryType;
import appeng.client.gui.widgets.ITickingWidget;
import appeng.client.gui.widgets.NumberBox;
import appeng.core.AEConfig;
import net.minecraft.text.Text;
/**
* A utility widget that consists of a text-field to enter a number with
@@ -21,6 +23,9 @@ import appeng.core.AEConfig;
*/
public class NumberEntryWidget implements ITickingWidget {
private static final Text PLUS = Text.method_30163("+");
private static final Text MINUS = Text.method_30163("+");
private final AEBaseScreen<?> parent;
private final int x;
@@ -28,14 +33,7 @@ public class NumberEntryWidget implements ITickingWidget {
private final NumberBox level;
private final NumberEntryType type;
private ButtonWidget plus1;
private ButtonWidget plus10;
private ButtonWidget plus100;
private ButtonWidget plus1000;
private ButtonWidget minus1;
private ButtonWidget minus10;
private ButtonWidget minus100;
private ButtonWidget minus1000;
private List<ButtonWidget> buttons;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
LongConsumer changeListener) {
@@ -57,14 +55,7 @@ public class NumberEntryWidget implements ITickingWidget {
public void setActive(boolean active) {
this.level.active = active;
this.plus1.active = active;
this.plus10.active = active;
this.plus100.active = active;
this.plus1000.active = active;
this.minus1.active = active;
this.minus10.active = active;
this.minus100.active = active;
this.minus1000.active = active;
this.buttons.forEach(b -> b.active = active);
}
public void setTextFieldBounds(int x, int y, int width) {
@@ -87,25 +78,23 @@ public class NumberEntryWidget implements ITickingWidget {
int left = parent.getX() + x;
int top = parent.getY() + y;
addButton.accept(this.plus1 = new ButtonWidget(left, top, 22, 20, new LiteralText("+" + a), btn -> addQty(a)));
addButton.accept(
this.plus10 = new ButtonWidget(left + 28, top, 28, 20, new LiteralText("+" + b), btn -> addQty(b)));
addButton.accept(
this.plus100 = new ButtonWidget(left + 62, top, 32, 20, new LiteralText("+" + c), btn -> addQty(c)));
addButton.accept(
this.plus1000 = new ButtonWidget(left + 100, top, 38, 20, new LiteralText("+" + d), btn -> addQty(d)));
List<ButtonWidget> buttons = new ArrayList<>(8);
buttons.add(new ButtonWidget(left, top, 22, 20, makeLabel(PLUS, a), btn -> addQty(a)));
buttons.add(new ButtonWidget(left + 28, top, 28, 20, makeLabel(PLUS, b), btn -> addQty(b)));
buttons.add(new ButtonWidget(left + 62, top, 32, 20, makeLabel(PLUS, c), btn -> addQty(c)));
buttons.add(new ButtonWidget(left + 100, top, 38, 20, makeLabel(PLUS, d), btn -> addQty(d)));
// Placing this here will give a sensible tab order
addChildren.accept(this.level);
addButton.accept(
this.minus1 = new ButtonWidget(left, top + 42, 22, 20, new LiteralText("-" + a), btn -> addQty(-a)));
addButton.accept(this.minus10 = new ButtonWidget(left + 28, top + 42, 28, 20, new LiteralText("-" + b),
btn -> addQty(-b)));
addButton.accept(this.minus100 = new ButtonWidget(left + 62, top + 42, 32, 20, new LiteralText("-" + c),
btn -> addQty(-c)));
addButton.accept(this.minus1000 = new ButtonWidget(left + 100, top + 42, 38, 20, new LiteralText("-" + d),
btn -> addQty(-d)));
buttons.add(new ButtonWidget(left, top + 42, 22, 20, makeLabel(MINUS, a), btn -> addQty(-a)));
buttons.add(new ButtonWidget(left + 28, top + 42, 28, 20, makeLabel(MINUS, b), btn -> addQty(-b)));
buttons.add(new ButtonWidget(left + 62, top + 42, 32, 20, makeLabel(MINUS, c), btn -> addQty(-c)));
buttons.add(new ButtonWidget(left + 100, top + 42, 38, 20, makeLabel(MINUS, d), btn -> addQty(-d)));
this.buttons = buttons;
this.buttons.forEach(addButton);
}
private void addQty(final long i) {
@@ -135,4 +124,8 @@ public class NumberEntryWidget implements ITickingWidget {
this.level.tick();
}
private Text makeLabel(Text prefix, int amount) {
return prefix.copy().append(String.valueOf(amount));
}
}
@@ -18,6 +18,8 @@
package appeng.client.render;
import java.util.Locale;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.util.math.Vector4f;
@@ -112,6 +114,6 @@ public enum FacingToRotation implements StringIdentifiable {
@Override
public String asString() {
return name().toLowerCase();
return name().toLowerCase(Locale.ROOT);
}
}
@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import net.fabricmc.api.EnvType;
@@ -104,7 +105,7 @@ class CableBuilder {
}
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, textureFolder + color.name().toLowerCase()));
new Identifier(AppEng.MOD_ID, textureFolder + color.name().toLowerCase(Locale.ROOT)));
}
/**
@@ -19,6 +19,7 @@
package appeng.client.render.cablebus;
import java.util.EnumMap;
import java.util.Locale;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
@@ -74,7 +75,7 @@ public enum CableCoreType {
public SpriteIdentifier getTexture(AEColor color) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase()));
new Identifier(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase(Locale.ROOT)));
}
}
@@ -49,7 +49,7 @@ public class EnergyParticleData implements ParticleEffect {
reader.expect(' ');
boolean forItem = reader.readBoolean();
reader.expect(' ');
AEPartLocation direction = AEPartLocation.valueOf(reader.readString().toUpperCase());
AEPartLocation direction = AEPartLocation.valueOf(reader.readString().toUpperCase(Locale.ROOT));
return new EnergyParticleData(forItem, direction);
}
@@ -74,7 +74,8 @@ public class EnergyParticleData implements ParticleEffect {
@Override
public String asString() {
return String.format(Locale.ROOT, "%s %s", forItem ? "true" : "false", direction.name().toLowerCase());
return String.format(Locale.ROOT, "%s %s", forItem ? "true" : "false",
direction.name().toLowerCase(Locale.ROOT));
}
}
@@ -20,6 +20,7 @@ package appeng.client.render.spatial;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -59,7 +60,7 @@ public class SpatialPylonModel implements BasicUnbakedModel {
private static SpriteIdentifier getTexturePath(SpatialPylonTextureType type) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/spatial_pylon/" + type.name().toLowerCase()));
new Identifier(AppEng.MOD_ID, "block/spatial_pylon/" + type.name().toLowerCase(Locale.ROOT)));
}
}
+52 -65
View File
@@ -1,56 +1,5 @@
package appeng.core;
import java.util.OptionalLong;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.earthcomputer.libstructure.LibStructure;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BannerBlockEntity;
import net.minecraft.block.entity.BeaconBlockEntity;
import net.minecraft.block.entity.BrewingStandBlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.ComparatorBlockEntity;
import net.minecraft.block.entity.DaylightDetectorBlockEntity;
import net.minecraft.block.entity.DispenserBlockEntity;
import net.minecraft.block.entity.DropperBlockEntity;
import net.minecraft.block.entity.EnchantingTableBlockEntity;
import net.minecraft.block.entity.EndPortalBlockEntity;
import net.minecraft.block.entity.EnderChestBlockEntity;
import net.minecraft.block.entity.FurnaceBlockEntity;
import net.minecraft.block.entity.HopperBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.PistonBlockEntity;
import net.minecraft.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
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;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.decorator.RangeDecoratorConfig;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import appeng.api.config.Upgrades;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IItems;
@@ -124,7 +73,6 @@ import appeng.fluids.container.FluidLevelEmitterContainer;
import appeng.fluids.container.FluidStorageBusContainer;
import appeng.fluids.container.FluidTerminalContainer;
import appeng.fluids.registries.BasicFluidCellGuiHandler;
import appeng.hooks.RegisterDimensionTypeCallback;
import appeng.hooks.ToolItemHook;
import appeng.items.parts.FacadeItem;
import appeng.items.tools.NetworkToolItem;
@@ -145,14 +93,61 @@ import appeng.recipes.handlers.InscriberRecipe;
import appeng.recipes.handlers.InscriberRecipeSerializer;
import appeng.recipes.handlers.QuartzKnifeRecipeSerializer;
import appeng.server.AECommand;
import appeng.spatial.SpatialDimensionManager;
import appeng.spatial.StorageCellBiome;
import appeng.spatial.StorageChunkGenerator;
import appeng.spatial.SpatialStorageBiome;
import appeng.spatial.SpatialStorageChunkGenerator;
import appeng.spatial.SpatialStorageDimensionIds;
import appeng.tile.AEBaseBlockEntity;
import appeng.worldgen.BiomeModifier;
import appeng.worldgen.ChargedQuartzOreConfig;
import appeng.worldgen.ChargedQuartzOreFeature;
import appeng.worldgen.meteorite.MeteoriteStructure;
import net.earthcomputer.libstructure.LibStructure;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BannerBlockEntity;
import net.minecraft.block.entity.BeaconBlockEntity;
import net.minecraft.block.entity.BrewingStandBlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.ComparatorBlockEntity;
import net.minecraft.block.entity.DaylightDetectorBlockEntity;
import net.minecraft.block.entity.DispenserBlockEntity;
import net.minecraft.block.entity.DropperBlockEntity;
import net.minecraft.block.entity.EnchantingTableBlockEntity;
import net.minecraft.block.entity.EndPortalBlockEntity;
import net.minecraft.block.entity.EnderChestBlockEntity;
import net.minecraft.block.entity.FurnaceBlockEntity;
import net.minecraft.block.entity.HopperBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.PistonBlockEntity;
import net.minecraft.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
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;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.decorator.RangeDecoratorConfig;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import javax.annotation.Nullable;
import java.util.function.Consumer;
public abstract class AppEngBase implements AppEng {
@@ -614,16 +609,8 @@ public abstract class AppEngBase implements AppEng {
}
private void registerDimension() {
Registry.register(BuiltinRegistries.BIOME, AppEng.makeId("storage"), StorageCellBiome.INSTANCE);
Registry.register(Registry.CHUNK_GENERATOR, AppEng.makeId("storage"), StorageChunkGenerator.CODEC);
RegisterDimensionTypeCallback.EVENT.register(registryTracker -> {
DimensionType dimensionType = new DimensionType(OptionalLong.of(12000), false, false, false, false, false,
false, true, false, false, 256, BlockTags.INFINIBURN_OVERWORLD.getId(), 1.0f);
Registry.register(registryTracker.getDimensionTypes(),
SpatialDimensionManager.STORAGE_DIMENSION_TYPE.getValue(), dimensionType);
});
Registry.register(BuiltinRegistries.BIOME, SpatialStorageDimensionIds.BIOME_ID, SpatialStorageBiome.INSTANCE);
Registry.register(Registry.CHUNK_GENERATOR, SpatialStorageDimensionIds.CHUNK_GENERATOR_ID, SpatialStorageChunkGenerator.CODEC);
}
}
@@ -19,6 +19,7 @@
package appeng.entity;
import java.util.List;
import java.util.Random;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
@@ -42,6 +43,8 @@ import appeng.util.Platform;
public final class ChargedQuartzEntity extends AEBaseItemEntity {
private static final Random RANDOM = new Random();
public static EntityType<ChargedQuartzEntity> TYPE;
private int delay = 0;
@@ -135,8 +138,15 @@ public final class ChargedQuartzEntity extends AEBaseItemEntity {
}
materials.fluixCrystal().maybeStack(2).ifPresent(is -> {
final ItemEntity entity = new ItemEntity(this.world, this.getX(), this.getY(), this.getZ(), is);
final double x = Math.floor(this.getX()) + .25d + RANDOM.nextDouble() * .5;
final double y = Math.floor(this.getY()) + .25d + RANDOM.nextDouble() * .5;
final double z = Math.floor(this.getZ()) + .25d + RANDOM.nextDouble() * .5;
final double xSpeed = RANDOM.nextDouble() * .25 - 0.125;
final double ySpeed = RANDOM.nextDouble() * .25 - 0.125;
final double zSpeed = RANDOM.nextDouble() * .25 - 0.125;
final ItemEntity entity = new ItemEntity(this.world, x, y, z, is);
entity.setVelocity(xSpeed, ySpeed, zSpeed);
this.world.spawnEntity(entity);
});
@@ -1,14 +0,0 @@
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<World> worldId, RegistryKey<DimensionType> dimensionTypeId,
ChunkGenerator chunkGenerator);
}
@@ -1,18 +0,0 @@
package appeng.hooks;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.util.registry.DynamicRegistryManager;
public interface RegisterDimensionTypeCallback {
Event<RegisterDimensionTypeCallback> EVENT = EventFactory.createArrayBacked(RegisterDimensionTypeCallback.class,
(listeners) -> (registryTracker) -> {
for (RegisterDimensionTypeCallback listener : listeners) {
listener.addDimensionTypes(registryTracker);
}
});
void addDimensionTypes(DynamicRegistryManager registryTracker);
}
@@ -0,0 +1,130 @@
package appeng.hooks;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import appeng.core.AppEng;
import appeng.mixins.unlitquad.BakedQuadAccessor;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelElementFace;
import net.minecraft.client.render.model.json.ModelElementTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.math.Direction;
/**
* Implementation details of allowing quads to be defined as "unlit" in JSON
* models by specifying an "unlit" boolean property on the face.
*/
public class UnlitQuadHooks {
/**
* Vertex format used for blocks.
*/
private static final VertexFormat VERTEX_FORMAT = VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL;
/**
* Offset into the vertex data (which is represented as integers).
*/
private static final int LIGHT_OFFSET = getLightOffset();
// Lightmap texture coordinate with full intensity light leading to no drop in
// brightness
private static final int UNLIT_LIGHT_UV = LightmapTextureManager.pack(15, 15);
/**
* Thread-Local flag to indicate that an enhanced Applied Energistics model is
* currently being deserialized.
*/
private static final ThreadLocal<Boolean> ENABLE_UNLIT_EXTENSIONS = new ThreadLocal<>();
/**
* Notify the unlit model system that a specific model is about to be
* deserialized by {@link net.minecraft.client.render.model.ModelLoader}.
*/
public static void beginDeserializingModel(Identifier location) {
String namespace = location.getNamespace();
if (namespace.equals(AppEng.MOD_ID)) {
ENABLE_UNLIT_EXTENSIONS.set(true);
}
}
/**
* Notify the unlit model system that deserialization of a model has ended.
*/
public static void endDeserializingModel() {
ENABLE_UNLIT_EXTENSIONS.set(false);
}
public static boolean isUnlitExtensionEnabled() {
Boolean b = ENABLE_UNLIT_EXTENSIONS.get();
return b != null && b;
}
public static ModelElementFace enhanceModelElementFace(ModelElementFace modelElement, JsonElement jsonElement) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (JsonHelper.getBoolean(jsonObject, "unlit", false)) {
return new UnlitModelElementFace(modelElement.cullFace, modelElement.tintIndex, modelElement.textureId,
modelElement.textureData);
}
return modelElement;
}
/**
* Creates a new quad from the given quad and pre-bakes it to not be affected by
* lighting (neither diffuse lighting nor the prebaked lightmap). This works on
* the assumption that Vanilla will not modify a quad's lightmap data if it's
* not zero.
*/
public static BakedQuad makeUnlit(BakedQuad quad) {
int[] vertexData = quad.getVertexData().clone();
int stride = VERTEX_FORMAT.getVertexSizeInteger();
// Set the pre-baked texture coords for the lightmap.
// Vanilla will not overwrite them if they are non-zero
for (int i = 0; i < 4; i++) {
vertexData[stride * i + LIGHT_OFFSET] = UNLIT_LIGHT_UV;
}
Sprite sprite = ((BakedQuadAccessor) quad).getSprite();
// Copy the quad to disable diffuse lighting
return new BakedQuad(vertexData, quad.getColorIndex(), quad.getFace(), sprite, false /* diffuse lighting */);
}
/**
* This subclass is used as a marker to indicate this face deserialized from
* JSON is supposed to be unlit, which translates to processing by
* {@link #makeUnlit(BakedQuad)}.
*/
public static class UnlitModelElementFace extends ModelElementFace {
public UnlitModelElementFace(Direction cullFaceIn, int tintIndexIn, String textureIn, ModelElementTexture blockFaceUVIn) {
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
}
}
/**
* Find the index in the BakedQuad vertex data (for vertex 0) where the lightmap
* coordinates are. Assumes the BLOCK vertex format.
*/
private static int getLightOffset() {
int offset = 0;
for (VertexFormatElement element : VERTEX_FORMAT.getElements()) {
// LIGHT_ELEMENT is the lightmap vertex element
if (element == VertexFormats.LIGHT_ELEMENT) {
if (element.getFormat() != VertexFormatElement.Format.SHORT) {
throw new UnsupportedOperationException("Expected light map format to be of type SHORT");
}
if (offset % 4 != 0) {
throw new UnsupportedOperationException("Expected light map offset to be 4-byte aligned");
}
return offset / 4;
}
offset += element.getSize();
}
throw new UnsupportedOperationException("Failed to find the lightmap index in the block vertex format");
}
}
@@ -47,7 +47,7 @@ public abstract class BaseWailaDataProvider implements IComponentProvider, IServ
}
@Override
public void appendServerData(CompoundTag compoundNBT, ServerPlayerEntity serverPlayerEntity, World world,
public void appendServerData(CompoundTag CompoundTag, ServerPlayerEntity serverPlayerEntity, World world,
BlockEntity tileEntity) {
}
@@ -18,35 +18,39 @@
package appeng.items.storage;
import java.time.Instant;
import java.util.List;
import java.util.Locale;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
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 appeng.api.implementations.TransitionResult;
import appeng.api.implementations.items.ISpatialStorageCell;
import appeng.api.storage.ISpatialDimension;
import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.core.localization.GuiText;
import appeng.items.AEBaseItem;
import appeng.spatial.SpatialDimensionManager;
import appeng.spatial.StorageHelper;
import appeng.spatial.SpatialStorageHelper;
import appeng.spatial.SpatialStoragePlot;
import appeng.spatial.SpatialStoragePlotManager;
import appeng.spatial.TransitionInfo;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorageCell {
private static final String TAG_DIMENSION_ID = "dimension_id";
private static final String TAG_PLOT_ID = "plot_id";
/**
* This is only stored in the itemstack to display in the tooltip on the
* client-side.
*/
private static final String TAG_PLOT_SIZE = "plot_size";
private final int maxRegion;
@@ -58,19 +62,23 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag
@Environment(EnvType.CLIENT)
@Override
public void appendTooltip(final ItemStack stack, final World world, final List<Text> lines,
final TooltipContext advancedTooltips) {
final RegistryKey<World> worldId = this.getStoredDimension(stack);
if (worldId == null) {
final TooltipContext advancedTooltips) {
int plotId = this.getAllocatedPlotId(stack);
if (plotId == -1) {
lines.add(GuiText.Unformatted.text().copy().formatted(Formatting.ITALIC));
lines.add(GuiText.SpatialCapacity.text(maxRegion, maxRegion, maxRegion));
} else {
SpatialDimensionManager.INSTANCE.addCellDimensionTooltip(worldId, lines);
return;
}
if (advancedTooltips.isAdvanced()) {
if (worldId != null && worldId.getValue() != null) {
lines.add(new LiteralText("Dimension: " + worldId.getValue()));
}
// Add a serial number to allows players to keep different cells apart
// Try to make this a little more flavorful.
String serialNumber = String.format(Locale.ROOT, "SP-%04d", plotId);
lines.add(GuiText.SerialNumber.text(serialNumber));
CompoundTag tag = stack.getTag();
if (tag != null && tag.contains(TAG_PLOT_SIZE, NbtType.LONG)) {
BlockPos size = BlockPos.fromLong(tag.getLong(TAG_PLOT_SIZE));
lines.add(GuiText.StoredSize.text(size.getX(), size.getY(), size.getZ()));
}
}
@@ -85,70 +93,80 @@ public class SpatialStorageCellItem extends AEBaseItem implements ISpatialStorag
}
@Override
public RegistryKey<World> getStoredDimension(final ItemStack is) {
public int getAllocatedPlotId(final ItemStack is) {
final CompoundTag c = is.getTag();
if (c != null && c.contains(TAG_DIMENSION_ID)) {
if (c != null && c.contains(TAG_PLOT_ID)) {
try {
Identifier worldId = new Identifier(c.getString(TAG_DIMENSION_ID));
return RegistryKey.of(Registry.DIMENSION, worldId);
int plotId = c.getInt(TAG_PLOT_ID);
if (SpatialStoragePlotManager.INSTANCE.getPlot(plotId) == null) {
return -1;
}
return plotId;
} catch (Exception e) {
AELog.warn("Failed to retrieve storage cell dimension.", e);
AELog.warn("Failed to retrieve spatial storage dimension: %s", e);
}
}
return null;
return -1;
}
@Override
public TransitionResult doSpatialTransition(final ItemStack is, final ServerWorld w, final WorldCoord min,
final WorldCoord max, int playerId) {
public boolean doSpatialTransition(final ItemStack is, final ServerWorld w, final WorldCoord min,
final WorldCoord max, int playerId) {
final int targetX = max.x - min.x - 1;
final int targetY = max.y - min.y - 1;
final int targetZ = max.z - min.z - 1;
final int maxSize = this.getMaxStoredDim(is);
if (targetX > maxSize && targetY > maxSize && targetZ > maxSize) {
AELog.info(
"Failing spatial transition because the transfer area (%dx%dx%d) exceeds the cell capacity (%s).",
targetX, targetY, targetZ, maxSize);
return false;
}
final BlockPos targetSize = new BlockPos(targetX, targetY, targetZ);
ISpatialDimension manager = SpatialDimensionManager.INSTANCE;
SpatialStoragePlotManager manager = SpatialStoragePlotManager.INSTANCE;
RegistryKey<World> worldId = this.getStoredDimension(is);
if (worldId == null || manager.getWorld(worldId) == null) {
worldId = manager.createNewCellDimension(targetSize);
SpatialStoragePlot plot = SpatialStoragePlotManager.INSTANCE.getPlot(this.getAllocatedPlotId(is));
if (plot != null) {
// Check that the existing plot has the right size
if (!plot.getSize().equals(targetSize)) {
AELog.info(
"Failing spatial transition because the transfer area (%dx%dx%d) does not match the spatial storage plot's size (%s).",
targetX, targetY, targetZ, plot.getSize());
return false;
}
} else {
// Otherwise allocate a new one
plot = manager.allocatePlot(targetSize, playerId);
}
if (worldId == null) {
// Failed to create the dimension
return new TransitionResult(false, 0);
}
// Store some information about this transition in the plot
TransitionInfo info = new TransitionInfo(w.getRegistryKey().getValue(), min.getBlockPos(),
max.getBlockPos(), Instant.now());
manager.setLastTransition(plot.getId(), info);
try {
if (manager.isCellDimension(worldId)) {
ServerWorld cellWorld = manager.getWorld(worldId);
ServerWorld cellWorld = manager.getWorld();
BlockPos scale = manager.getCellDimensionSize(worldId);
BlockPos offset = plot.getOrigin();
if (scale.equals(targetSize)) {
if (targetX <= maxSize && targetY <= maxSize && targetZ <= maxSize) {
BlockPos offset = manager.getCellDimensionOrigin(worldId);
this.setStoredDimension(is, plot.getId(), plot.getSize());
SpatialStorageHelper.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);
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);
return new TransitionResult(true, 0);
}
}
}
return new TransitionResult(false, 0);
return true;
} finally {
// clean up newly created dimensions that failed transfer
if (manager.isCellDimension(worldId) && this.getStoredDimension(is) == null) {
manager.deleteCellDimension(worldId);
if (this.getAllocatedPlotId(is) == -1) {
manager.freePlot(plot.getId(), true);
}
}
}
private void setStoredDimension(final ItemStack is, RegistryKey<World> worldId) {
public void setStoredDimension(final ItemStack is, int plotId, BlockPos size) {
final CompoundTag c = is.getOrCreateTag();
c.putString(TAG_DIMENSION_ID, worldId.getValue().toString());
c.putInt(TAG_PLOT_ID, plotId);
c.putLong(TAG_PLOT_SIZE, size.asLong());
}
}
@@ -1,22 +0,0 @@
package appeng.mixins;
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;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.world.dimension.DimensionType;
import appeng.hooks.RegisterDimensionTypeCallback;
@Mixin(DimensionType.class)
public class DimensionTypeMixin {
@Inject(method = "addRegistryDefaults", at = @At("TAIL"))
private static void addRegistryDefaults(DynamicRegistryManager.Impl registryTracker,
CallbackInfoReturnable<?> cir) {
RegisterDimensionTypeCallback.EVENT.invoker().addDimensionTypes(registryTracker);
}
}
@@ -1,106 +0,0 @@
package appeng.mixins;
import java.util.Map;
import java.util.concurrent.Executor;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
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 appeng.hooks.DynamicDimensions;
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin implements DynamicDimensions {
@Shadow
private DynamicRegistryManager.Impl registryManager;
@Shadow
private Map<RegistryKey<World>, ServerWorld> worlds;
@Shadow
private SaveProperties saveProperties;
@Shadow
private Executor workerExecutor;
@Shadow
private LevelStorage.Session session;
public ServerWorld addWorld(RegistryKey<World> worldId, RegistryKey<DimensionType> 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 = registryManager.getDimensionTypes().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(
() -> registryManager.getDimensionTypes().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<DimensionOptions> dimOptKey = RegistryKey.of(Registry.DIMENSION_OPTIONS, worldId.getValue());
generatorOptions.getDimensionMap().add(dimOptKey, dimensionOptions);
// FIXME FABRIC: might not be needed anymore if dimensions will save regardless
// FIXME FABRIC 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.registryManager, this.saveProperties, self.getPlayerManager().getUserData());
return world;
}
}
@@ -0,0 +1,37 @@
package appeng.mixins.spatial;
import java.util.List;
import java.util.Map;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.dimension.DimensionOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import appeng.spatial.SpatialStorageDimensionIds;
/**
* This Mixin tries to hide the screen that warns users about experimental
* features being used, but only if AE2's dimension is the only added dimension.
*/
@Mixin(DimensionOptions.class)
public class DimensionOptionMixin {
/**
* This injects right after the method makes a local copy of all present
* dimensions, and modifies the list by removing our mod-provided dimension from
* it.
* <p>
* This means Vanilla will perform it's check whether it should display an
* experimental warning without considering our dimension.
*/
@ModifyVariable(method = "method_29567", at = @At(value = "INVOKE_ASSIGN", ordinal = 0, target = "Lcom/google/common/collect/Lists;newArrayList(Ljava/lang/Iterable;)Ljava/util/ArrayList;", remap = false), allow = 1)
private static List<Map.Entry<RegistryKey<DimensionOptions>, DimensionOptions>> overrideExperimentalCheck(
List<Map.Entry<RegistryKey<DimensionOptions>, DimensionOptions>> dimensions) {
// this only removes our dimension from the check
dimensions.removeIf(e -> e.getKey() == SpatialStorageDimensionIds.DIMENSION_ID);
return dimensions;
}
}
@@ -0,0 +1,32 @@
package appeng.mixins.spatial;
import appeng.spatial.SpatialStorageDimensionIds;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
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;
import java.util.OptionalLong;
/**
* Adds the storage cell world dimension type as a built-in dimension type. This
* can be registered as a JSON file as well, but doing so will trigger an
* experimental feature warning when the world is being loaded.
*/
@Mixin(DimensionType.class)
public class DimensionTypeMixin {
@Inject(method = "addRegistryDefaults", at = @At("TAIL"))
private static void addRegistryDefaults(DynamicRegistryManager.Impl registryTracker, CallbackInfoReturnable<?> cir) {
DimensionType dimensionType = new DimensionType(OptionalLong.of(12000), false, false, false, false, false,
false, true, false, false, 256, BlockTags.INFINIBURN_OVERWORLD.getId(), 1.0f);
Registry.register(registryTracker.getDimensionTypes(),
SpatialStorageDimensionIds.DIMENSION_TYPE_ID.getValue(), dimensionType);
}
}
@@ -1,4 +1,4 @@
package appeng.mixins;
package appeng.mixins.spatial;
import java.util.Optional;
@@ -11,8 +11,8 @@ import net.minecraft.client.render.SkyProperties;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.dimension.DimensionType;
import appeng.spatial.SpatialDimensionManager;
import appeng.spatial.StorageSkyProperties;
import appeng.spatial.SpatialStorageDimensionIds;
import appeng.spatial.SpatialStorageSkyProperties;
@Mixin(SkyProperties.class)
public class SkyPropertiesMixin {
@@ -20,8 +20,8 @@ public class SkyPropertiesMixin {
@Inject(method = "byDimensionType", at = @At("HEAD"), cancellable = true)
private static void byDimensionType(Optional<RegistryKey<DimensionType>> optional,
CallbackInfoReturnable<SkyProperties> ci) {
if (optional.orElse(null) == SpatialDimensionManager.STORAGE_DIMENSION_TYPE) {
ci.setReturnValue(StorageSkyProperties.INSTANCE);
if (optional.orElse(null) == SpatialStorageDimensionIds.DIMENSION_TYPE_ID) {
ci.setReturnValue(SpatialStorageSkyProperties.INSTANCE);
}
}
@@ -1,4 +1,4 @@
package appeng.mixins;
package appeng.mixins.spatial;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -11,7 +11,7 @@ import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack;
import appeng.client.render.SpatialSkyRender;
import appeng.spatial.SpatialDimensionManager;
import appeng.spatial.SpatialStorageDimensionIds;
@Mixin(WorldRenderer.class)
public class SkyRenderMixin {
@@ -22,7 +22,7 @@ public class SkyRenderMixin {
@SuppressWarnings("ConstantConditions")
@Inject(method = "renderSky", at = @At("HEAD"), cancellable = true)
public void renderSky(MatrixStack matrices, float tickDelta, CallbackInfo ci) {
if (client.world.getDimensionRegistryKey() == SpatialDimensionManager.STORAGE_DIMENSION_TYPE) {
if (client.world.getRegistryKey() == SpatialStorageDimensionIds.WORLD_ID) {
SpatialSkyRender.getInstance().render(matrices);
ci.cancel();
}
@@ -0,0 +1,14 @@
package appeng.mixins.unlitquad;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(BakedQuad.class)
public interface BakedQuadAccessor {
@Accessor
Sprite getSprite();
}
@@ -0,0 +1,34 @@
package appeng.mixins.unlitquad;
import appeng.hooks.UnlitQuadHooks;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.client.render.model.json.ModelElement;
import net.minecraft.client.render.model.json.ModelElementFace;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
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;
/**
* This mixin hooks into conversion from {@link ModelElementFace} to
* {@link BakedQuad} to apply our unlit extensions if the block part face is an
* instance of our marker class
* {@link appeng.hooks.UnlitQuadHooks.UnlitModelElementFace}.
*/
@Mixin(JsonUnbakedModel.class)
public class JsonUnbakedModelMixin {
@Inject(method = "createQuad", at = @At("RETURN"), cancellable = true, require = 1, allow = 1)
private static void onBakeFace(ModelElement element, ModelElementFace elementFace, Sprite sprite, Direction side,
ModelBakeSettings settings, Identifier id, CallbackInfoReturnable<BakedQuad> cri) {
if (elementFace instanceof UnlitQuadHooks.UnlitModelElementFace) {
cri.setReturnValue(UnlitQuadHooks.makeUnlit(cri.getReturnValue()));
}
}
}
@@ -0,0 +1,32 @@
package appeng.mixins.unlitquad;
import appeng.hooks.UnlitQuadHooks;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import net.minecraft.client.render.model.json.ModelElementFace;
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;
import java.lang.reflect.Type;
/**
* This mixin will call the hook to deserialize the unlit property, but only if
* we are currently deserializing an AE2 model.
*/
@Mixin(ModelElementFace.Deserializer.class)
public class ModelElementFaceDeserializerMixin {
@Inject(method = "deserialize", at = @At("RETURN"), cancellable = true, allow = 1, remap = false)
public void onDeserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext,
CallbackInfoReturnable<ModelElementFace> cri) {
if (!UnlitQuadHooks.isUnlitExtensionEnabled()) {
return; // Not in a model that activated the deserializer
}
ModelElementFace modelElement = cri.getReturnValue();
cri.setReturnValue(UnlitQuadHooks.enhanceModelElementFace(modelElement, jsonElement));
}
}
@@ -0,0 +1,32 @@
package appeng.mixins.unlitquad;
import appeng.hooks.UnlitQuadHooks;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.util.Identifier;
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;
import java.io.IOException;
/**
* The only job of this mixin is to only enable the unlit extensions if the
* model is whitelisted for it, which is decided in {@link UnlitQuadHooks}.
*/
@Mixin(ModelLoader.class)
public class ModelLoaderMixin {
@Inject(method = "loadModelFromJson", at = @At("HEAD"), allow = 1)
protected void onBeginLoadModel(Identifier location, CallbackInfoReturnable<JsonUnbakedModel> cri)
throws IOException {
UnlitQuadHooks.beginDeserializingModel(location);
}
@Inject(method = "loadModelFromJson", at = @At("RETURN"))
protected void onEndLoadModel(Identifier location, CallbackInfoReturnable<JsonUnbakedModel> cri) {
UnlitQuadHooks.endDeserializingModel();
}
}
@@ -32,10 +32,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.util.AEPartLocation;
import appeng.items.parts.PartModels;
public class IdentityAnnihilationPlanePart extends AnnihilationPlanePart {
@@ -60,7 +60,8 @@ public class FluidP2PTunnelPart extends P2PTunnelPart<FluidP2PTunnelPart> {
return MODELS.getModels();
}
public float getPowerDrainPerTick() {
@Override
protected float getPowerDrainPerTick() {
return 2.0f;
}
@@ -66,6 +66,11 @@ public class ItemP2PTunnelPart extends P2PTunnelPart<ItemP2PTunnelPart> implemen
super(is);
}
@Override
protected float getPowerDrainPerTick() {
return POWER_DRAIN;
}
@Override
public void onNeighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
this.cachedInv = null;
@@ -199,10 +204,6 @@ public class ItemP2PTunnelPart extends P2PTunnelPart<ItemP2PTunnelPart> implemen
to.offer(getDestination(), CacheInfo.NOT_CACHABLE);
}
public float getPowerDrainPerTick() {
return POWER_DRAIN;
}
@Override
public IPartModel getStaticModels() {
return MODELS.getModel(this.isPowered(), this.isActive());
@@ -56,6 +56,10 @@ public class LightP2PTunnelPart extends P2PTunnelPart<LightP2PTunnelPart> implem
super(is);
}
protected float getPowerDrainPerTick() {
return 0.5f;
}
@Override
public void chanRender(final MENetworkChannelsChanged c) {
this.onTunnelNetworkChange();
@@ -186,10 +190,6 @@ public class LightP2PTunnelPart extends P2PTunnelPart<LightP2PTunnelPart> implem
return this.doWork() ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
}
public float getPowerDrainPerTick() {
return 0.5f;
}
@Override
public IPartModel getStaticModels() {
return MODELS.getModel(this.isPowered(), this.isActive());
@@ -67,6 +67,11 @@ public class MEP2PTunnelPart extends P2PTunnelPart<MEP2PTunnelPart> implements I
this.outerProxy.setFlags(GridFlags.DENSE_CAPACITY, GridFlags.CANNOT_CARRY_COMPRESSED);
}
@Override
protected float getPowerDrainPerTick() {
return 2.0f;
}
@Override
public void readFromNBT(final CompoundTag extra) {
super.readFromNBT(extra);
@@ -59,6 +59,11 @@ public abstract class P2PTunnelPart<T extends P2PTunnelPart> extends BasicStateP
public P2PTunnelPart(final ItemStack is) {
super(is);
this.getProxy().setIdlePowerUsage(this.getPowerDrainPerTick());
}
protected float getPowerDrainPerTick() {
return 1.0f;
}
public TunnelCollection<T> getCollection(final Collection<P2PTunnelPart> collection,
@@ -55,6 +55,11 @@ public class RedstoneP2PTunnelPart extends P2PTunnelPart<RedstoneP2PTunnelPart>
super(is);
}
@Override
protected float getPowerDrainPerTick() {
return 0.5f;
}
@MENetworkEventSubscribe
public void changeStateA(final MENetworkBootingStatusChange bs) {
this.setNetworkReady();
@@ -123,10 +128,6 @@ public class RedstoneP2PTunnelPart extends P2PTunnelPart<RedstoneP2PTunnelPart>
this.setNetworkReady();
}
public float getPowerDrainPerTick() {
return 0.5f;
}
@Override
public void onNeighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
if (!this.isOutput()) {
+3 -1
View File
@@ -20,6 +20,8 @@ package appeng.server;
import static net.minecraft.server.command.CommandManager.literal;
import java.util.Locale;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
@@ -47,7 +49,7 @@ public final class AECommand {
private void add(LiteralArgumentBuilder<ServerCommandSource> builder, Commands subCommand) {
LiteralArgumentBuilder<ServerCommandSource> subCommandBuilder = literal(subCommand.name().toLowerCase())
LiteralArgumentBuilder<ServerCommandSource> subCommandBuilder = literal(subCommand.name().toLowerCase(Locale.ROOT))
.requires(src -> src.hasPermissionLevel(subCommand.level));
subCommand.command.addArguments(subCommandBuilder);
subCommandBuilder.executes(ctx -> {
+3 -1
View File
@@ -19,13 +19,15 @@
package appeng.server;
import appeng.server.subcommands.ChunkLogger;
import appeng.server.subcommands.SpatialStorageCommand;
import appeng.server.subcommands.Supporters;
import appeng.server.subcommands.TestMeteoritesCommand;
import appeng.server.subcommands.TestOreGenCommand;
public enum Commands {
Chunklogger(4, new ChunkLogger(), false), Supporters(0, new Supporters(), false),
TestOreGen(4, new TestOreGenCommand(), true), TestMeteorites(4, new TestMeteoritesCommand(), true);
TestOreGen(4, new TestOreGenCommand(), true), TestMeteorites(4, new TestMeteoritesCommand(), true),
Spatial(4, new SpatialStorageCommand(), false);
public final int level;
public final ISubCommand command;
@@ -0,0 +1,327 @@
package appeng.server.subcommands;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.function.UnaryOperator;
import appeng.core.AppEng;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.CommandException;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.HoverEvent;
import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import appeng.core.Api;
import appeng.core.worlddata.WorldData;
import appeng.items.storage.SpatialStorageCellItem;
import appeng.server.ISubCommand;
import appeng.spatial.SpatialStorageDimensionIds;
import appeng.spatial.SpatialStoragePlot;
import appeng.spatial.SpatialStoragePlotManager;
import appeng.spatial.TransitionInfo;
import net.minecraft.server.command.CommandManager;
import static net.minecraft.server.command.CommandManager.literal;
/**
* This admin command allows management of spatial storage plots.
*/
public class SpatialStorageCommand implements ISubCommand {
@Override
public void addArguments(LiteralArgumentBuilder<ServerCommandSource> builder) {
// Shows info about a given plot or about the plot the player is currently in
builder.then(literal("info").executes(ctx -> {
showPlotInfo(ctx.getSource(), getCurrentPlot(ctx.getSource()));
return 1;
}).then(CommandManager.argument("plotId", IntegerArgumentType.integer(1)).executes(ctx -> {
int plotId = IntegerArgumentType.getInteger(ctx, "plotId");
showPlotInfo(ctx.getSource(), getPlot(plotId));
return 1;
})));
// Teleport into the plot
builder.then(literal("tp").then(CommandManager.argument("plotId", IntegerArgumentType.integer(1)).executes(ctx -> {
int plotId = IntegerArgumentType.getInteger(ctx, "plotId");
teleportToPlot(ctx.getSource(), plotId);
return 1;
})));
// Teleport from the current plot back to the source of its content, or do the
// same for a given plot id
builder.then(literal("tpback").executes(ctx -> {
teleportBack(ctx.getSource());
return 1;
}).then(CommandManager.argument("plotId", IntegerArgumentType.integer(1)).executes(ctx -> {
int plotId = IntegerArgumentType.getInteger(ctx, "plotId");
teleportBack(ctx.getSource(), getPlot(plotId));
return 1;
})));
// Creates a storage cell for the given plot id and gives it to the player
builder.then(
literal("givecell").then(CommandManager.argument("plotId", IntegerArgumentType.integer(1)).executes(ctx -> {
int plotId = IntegerArgumentType.getInteger(ctx, "plotId");
giveCell(ctx.getSource(), plotId);
return 1;
})));
}
/**
* If the player is currently within a spatial storage plot, teleports them back
* to the last source of transition.
*/
private void teleportBack(ServerCommandSource source) {
if (source.getWorld().getRegistryKey() != SpatialStorageDimensionIds.WORLD_ID) {
throw new CommandException(Text.method_30163("Must be within the spatial storage world."));
}
BlockPos playerPos = new BlockPos(source.getPosition());
int x = playerPos.getX();
int z = playerPos.getZ();
// This is slow, but for an admin-command it's acceptable
for (SpatialStoragePlot plot : SpatialStoragePlotManager.INSTANCE.getPlots()) {
BlockPos origin = plot.getOrigin();
BlockPos size = plot.getSize();
if (x >= origin.getX() && x <= origin.getX() + size.getX() && z >= origin.getZ()
&& z <= origin.getZ() + size.getZ()) {
teleportBack(source, plot);
return;
}
}
throw new CommandException(Text.method_30163("Couldn't find a plot for the current position."));
}
/**
* Teleports back from the given plot.
*/
private void teleportBack(ServerCommandSource source, SpatialStoragePlot plot) {
TransitionInfo lastTransition = plot.getLastTransition();
if (lastTransition == null) {
throw new CommandException(
Text.method_30163("This plot doesn't have a last known transition."));
}
String command = getTeleportCommand(lastTransition.getWorldId(), lastTransition.getMin().add(0, 1, 0));
runCommandFor(source, command);
}
/**
* Shows detailed information about a spatial storage plot.
*/
private static void showPlotInfo(ServerCommandSource source, SpatialStoragePlot plot) {
sendKeyValuePair(source, "Plot ID", String.valueOf(plot.getId()));
// Show the owner of the spatial storage plot
int playerId = plot.getOwner();
if (playerId != -1) {
UUID profileId = WorldData.instance().playerData().getProfileId(playerId);
if (profileId == null) {
sendKeyValuePair(source, "Owner", "Unknown AE2 player (" + playerId + ")");
} else {
MinecraftServer server = AppEng.instance().getServer();
ServerPlayerEntity player = server.getPlayerManager().getPlayer(profileId);
if (player == null) {
sendKeyValuePair(source, "Owner", "Unknown Minecraft profile (" + profileId + ")");
} else {
sendKeyValuePair(source, "Owner", player.getDisplayName());
}
}
} else {
sendKeyValuePair(source, "Owner", "Unknown");
}
sendKeyValuePair(source, "Size", formatBlockPos(plot.getSize(), "x"));
// Show the plot's origin and make it clickable to teleport directly to it
String teleportToPlotCommand = getTeleportCommand(SpatialStorageDimensionIds.WORLD_ID.getValue(),
plot.getOrigin());
sendKeyValuePair(source, "Origin", new LiteralText(formatBlockPos(plot.getOrigin(), ","))
.styled(makeCommandLink(teleportToPlotCommand, "Teleport into plot")));
sendKeyValuePair(source, "Region file:", plot.getRegionFilename());
// Show information about what was last transfered into the plot (with a
// clickable link to the source)
TransitionInfo lastTransition = plot.getLastTransition();
if (lastTransition != null) {
source.sendFeedback(new LiteralText("Last Transition:").formatted(Formatting.UNDERLINE,
Formatting.BOLD), true);
String sourceWorldId = lastTransition.getWorldId().toString();
MutableText sourceLink = new LiteralText(
sourceWorldId + " - " + formatBlockPos(lastTransition.getMin(), ",") + " to "
+ formatBlockPos(lastTransition.getMax(), ","));
String tpCommand = getTeleportCommand(lastTransition.getWorldId(), lastTransition.getMin().add(0, 1, 0));
sourceLink.styled(makeCommandLink(tpCommand, "Click to teleport"));
sendKeyValuePair(source, "Source", sourceLink);
sendKeyValuePair(source, "When", lastTransition.getTimestamp().toString());
} else {
source.sendFeedback(Text.method_30163("Last Transition unknown"), true);
}
}
private static void teleportToPlot(ServerCommandSource source, int plotId) {
SpatialStoragePlot plot = getPlot(plotId);
String teleportCommand = getTeleportCommand(SpatialStorageDimensionIds.WORLD_ID.getValue(),
plot.getOrigin());
runCommandFor(source, teleportCommand);
}
private void giveCell(ServerCommandSource source, int plotId) throws CommandSyntaxException {
ServerPlayerEntity player = source.getPlayer();
SpatialStoragePlot plot = getPlot(plotId);
ItemStack cell;
int longestSide = getLongestSide(plot.getSize());
if (longestSide <= 2) {
cell = Api.instance().definitions().items().spatialCell2().stack(1);
} else if (longestSide <= 16) {
cell = Api.instance().definitions().items().spatialCell16().stack(1);
} else {
cell = Api.instance().definitions().items().spatialCell128().stack(1);
}
if (!(cell.getItem() instanceof SpatialStorageCellItem)) {
throw new CommandException(
Text.method_30163("Storage cell items don't implement the storage cell interface!"));
}
SpatialStorageCellItem spatialCellItem = (SpatialStorageCellItem) cell.getItem();
spatialCellItem.setStoredDimension(cell, plotId, plot.getSize());
player.giveItemStack(cell);
}
private static int getLongestSide(BlockPos size) {
return Math.max(size.getX(), Math.max(size.getY(), size.getZ()));
}
@Override
public void call(MinecraftServer srv, CommandContext<ServerCommandSource> ctx, ServerCommandSource sender) {
List<SpatialStoragePlot> plots = new ArrayList<>(SpatialStoragePlotManager.INSTANCE.getPlots());
// Prints the least recently used plots
plots.sort(Comparator.comparing((SpatialStoragePlot plot) -> {
TransitionInfo lastTransition = plot.getLastTransition();
if (lastTransition != null) {
return lastTransition.getTimestamp();
} else {
return Instant.MIN;
}
}).reversed());
for (int i = 0; i < Math.min(5, plots.size()); i++) {
SpatialStoragePlot plot = plots.get(i);
String size = formatBlockPos(plot.getSize(), "x");
BlockPos originPos = plot.getOrigin();
String origin = formatBlockPos(originPos, ",");
Text infoLink = new LiteralText("Plot #" + plot.getId())
.styled(makeCommandLink("/ae2 spatial info " + plot.getId(), "Click to show details"));
Text tpLink = new LiteralText("Origin: " + origin)
.styled(makeCommandLink("/ae2 spatial tp " + plot.getId(), "Click to teleport into plot"));
Text message = new LiteralText("").append(infoLink)
.append(" Size: " + size + " ").append(tpLink);
sender.sendFeedback(message, true);
}
}
private static String formatBlockPos(BlockPos size, String separator) {
return size.getX() + separator + size.getY() + separator + size.getZ();
}
private static UnaryOperator<Style> makeCommandLink(String command, String tooltip) {
return style -> style.withFormatting(Formatting.UNDERLINE)
.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command) )
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.method_30163(tooltip)));
}
private static void runCommandFor(ServerCommandSource source, String command) {
CommandManager commandManager = AppEng.instance().getServer().getCommandManager();
commandManager.execute(source, command);
}
private static String getTeleportCommand(Identifier worldId, BlockPos pos) {
return "/execute in " + worldId + " run tp @s " + pos.getX() + " " + (pos.getY() + 1) + " " + pos.getZ();
}
private static SpatialStoragePlot getPlot(int plotId) {
SpatialStoragePlot plot = SpatialStoragePlotManager.INSTANCE.getPlot(plotId);
if (plot == null) {
throw new CommandException(Text.method_30163("Plot not found: " + plotId));
}
return plot;
}
private static void sendKeyValuePair(ServerCommandSource source, String label, Text value) {
source.sendFeedback(
new LiteralText("")
.append(new LiteralText(label + ": ").formatted(Formatting.BOLD)).append(value),
true);
}
private static void sendKeyValuePair(ServerCommandSource source, String label, String value) {
sendKeyValuePair(source, label, Text.method_30163(value));
}
/**
* Gets the spatial storage plot that the command source is currently in.
*/
private static SpatialStoragePlot getCurrentPlot(ServerCommandSource source) {
if (source.getWorld().getRegistryKey() != SpatialStorageDimensionIds.WORLD_ID) {
throw new CommandException(Text.method_30163("Must be within the spatial storage world."));
}
BlockPos playerPos = new BlockPos(source.getPosition());
int x = playerPos.getX();
int z = playerPos.getZ();
// This is slow, but for an admin-command it's acceptable
for (SpatialStoragePlot plot : SpatialStoragePlotManager.INSTANCE.getPlots()) {
BlockPos origin = plot.getOrigin();
BlockPos size = plot.getSize();
if (x >= origin.getX() && x <= origin.getX() + size.getX() && z >= origin.getZ()
&& z <= origin.getZ() + size.getZ()) {
return plot;
}
}
throw new CommandException(Text.method_30163("Couldn't find a plot for the current position."));
}
}
+15 -13
View File
@@ -28,6 +28,7 @@ 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.ServerLightingProvider;
import net.minecraft.server.world.ServerTickScheduler;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Tickable;
@@ -46,6 +47,7 @@ import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.worlddata.WorldData;
import net.minecraft.world.chunk.light.LightingProvider;
public class CachedPlane {
private final int x_size;
@@ -60,13 +62,13 @@ public class CachedPlane {
private final Column[][] myColumns;
private final List<BlockEntity> tiles = new ArrayList<>();
private final List<ScheduledTick<Block>> ticks = new ArrayList<>();
private final World world;
private final ServerWorld world;
private final IMovableRegistry reg = Api.instance().registries().movable();
private final List<WorldCoord> updates = new ArrayList<>();
private int verticalBits;
private final BlockState matrixBlockState;
public CachedPlane(final World w, final int minX, final int minY, final int minZ, final int maxX, final int maxY,
public CachedPlane(final ServerWorld w, final int minX, final int minY, final int minZ, final int maxX, final int maxY,
final int maxZ) {
Block matrixFrameBlock = Api.instance().definitions().blocks().matrixFrame().maybeBlock().orElse(null);
@@ -301,12 +303,17 @@ public class CachedPlane {
private void updateChunks() {
LightingProvider lightManager = world.getLightingProvider();
// update shit..
for (int x = 0; x < this.cx_size; x++) {
for (int z = 0; z < this.cz_size; z++) {
final WorldChunk c = this.myChunks[x][z];
// FIXME: Light shit
c.markDirty();
if (lightManager instanceof ServerLightingProvider) {
ServerLightingProvider serverLightManager = (ServerLightingProvider) lightManager;
for (int x = 0; x < this.cx_size; x++) {
for (int z = 0; z < this.cz_size; z++) {
final WorldChunk c = this.myChunks[x][z];
serverLightManager.light(c, false);
c.markDirty();
}
}
}
@@ -320,7 +327,7 @@ public class CachedPlane {
// FIXME this was sending chunks to players...
ChunkDataS2CPacket cdp = new ChunkDataS2CPacket(c, verticalBits, false);
((ServerChunkManager) world.getChunkManager()).threadedAnvilChunkStorage
world.getChunkManager().threadedAnvilChunkStorage
.getPlayersWatchingChunk(c.getPos(), false).forEach(spe -> spe.networkHandler.sendPacket(cdp));
}
@@ -341,7 +348,6 @@ public class CachedPlane {
private static class BlockStorageData {
public BlockState state;
public int light;
}
private class Column {
@@ -374,8 +380,6 @@ public class CachedPlane {
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
// );
}
private void fillData(final int y, BlockStorageData data) {
@@ -383,8 +387,6 @@ public class CachedPlane {
final ChunkSection extendedblockstorage = storage[y >> 4];
data.state = extendedblockstorage.getBlockState(this.x, y & 15, this.z);
// FIXME data.light = extendedblockstorage.getBlockLight( this.x, y & 15, this.z
// );
}
private boolean doNotSkip(final int y) {
@@ -1,70 +0,0 @@
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;
}
}
@@ -1,200 +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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.spatial;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nullable;
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 appeng.api.storage.ISpatialDimension;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.localization.GuiText;
import appeng.hooks.DynamicDimensions;
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<DimensionType> 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_";
private SpatialDimensionManager() {
}
@Override
public ServerWorld getWorld(RegistryKey<World> cellDim) {
MinecraftServer server = getServer();
return server.getWorld(cellDim);
}
@Override
public RegistryKey<World> createNewCellDimension(BlockPos size) {
Identifier dimKey = findFreeDimensionId();
AELog.info("Allocating storage cell dimension '%s'", dimKey);
DynamicDimensions dynamicDimensions = (DynamicDimensions) getServer();
RegistryKey<World> 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;
}
/**
* Tries finding the next free storage cell dimension ID based on the currently
* registered storage cell dimensions.
*/
private Identifier findFreeDimensionId() {
int maxId = 0;
for (RegistryKey<World> worldId : getServer().getWorldRegistryKeys()) {
Identifier regName = worldId.getValue();
if (regName == null || !AppEng.MOD_ID.equals(regName.getNamespace())) {
continue;
}
String path = regName.getPath();
if (!path.startsWith(DIM_ID_PREFIX)) {
continue;
}
try {
String numericIdPart = path.substring(DIM_ID_PREFIX.length());
maxId = Math.max(Integer.parseUnsignedInt(numericIdPart), maxId);
} catch (NumberFormatException e) {
AELog.warn("Unparsable storage cell dimension id '%s'", path, e);
}
}
++maxId;
return new Identifier(AppEng.MOD_ID, DIM_ID_PREFIX + maxId);
}
@Override
public void deleteCellDimension(RegistryKey<World> worldId) {
AELog.info("Unregistering storage cell dimension %s", worldId.getValue());
MinecraftServer server = getServer();
// 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(RegistryKey<World> 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;
}
// 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(RegistryKey<World> worldId) {
return REGION_CENTER;
}
@Override
public BlockPos getCellDimensionSize(RegistryKey<World> worldId) {
SpatialDimensionExtraData extraData = getExtraData(worldId);
return extraData != null ? extraData.getSize() : BlockPos.ORIGIN;
}
@Override
public void addCellDimensionTooltip(RegistryKey<World> worldId, List<Text> lines) {
// Check if the cell dimension type is even registered
Identifier registryName = worldId.getValue();
if (registryName == null || !AppEng.MOD_ID.equals(registryName.getNamespace())) {
return;
}
if (!registryName.getPath().startsWith(DIM_ID_PREFIX)) {
return;
}
// Add the actual stored size
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
int dimId;
try {
String numericIdPart = registryName.getPath().substring(DIM_ID_PREFIX.length());
dimId = Integer.parseUnsignedInt(numericIdPart);
} catch (NumberFormatException ignored) {
return;
}
// Try to make this a little more flavorful.
String serialNumber = String.format(Locale.ROOT, "SP-%04d", dimId);
lines.add(GuiText.SerialNumber.text(serialNumber));
}
@Nullable
private SpatialDimensionExtraData getExtraData(RegistryKey<World> worldId) {
ServerWorld world = getWorld(worldId);
if (world == null) {
return null;
}
return world.getPersistentStateManager().get(SpatialDimensionExtraData::new, SpatialDimensionExtraData.ID);
}
private static MinecraftServer getServer() {
return AppEng.instance().getServer();
}
}
@@ -25,7 +25,10 @@ import net.minecraft.world.biome.SpawnSettings;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder;
public class StorageCellBiome {
/**
* The single biome used within the spatial storage world.
*/
public class SpatialStorageBiome {
public static final Biome INSTANCE = new Biome.Settings()
.generationSettings(new GenerationSettings.Builder()
@@ -43,18 +43,21 @@ import net.minecraft.world.gen.chunk.VerticalBlockSample;
import appeng.core.Api;
public class StorageChunkGenerator extends ChunkGenerator {
/**
* Chunk generator the spatial storage world.
*/
public class SpatialStorageChunkGenerator extends ChunkGenerator {
private final VerticalBlockSample columnSample;
public static final StorageChunkGenerator INSTANCE = new StorageChunkGenerator();
public static final SpatialStorageChunkGenerator INSTANCE = new SpatialStorageChunkGenerator();
public static final Codec<StorageChunkGenerator> CODEC = RecordCodecBuilder
public static final Codec<SpatialStorageChunkGenerator> CODEC = RecordCodecBuilder
.create((instance) -> instance.stable(INSTANCE));
private final BlockState defaultBlockState;
private StorageChunkGenerator() {
private SpatialStorageChunkGenerator() {
super(createBiomeProvider(), createSettings());
this.defaultBlockState = Api.instance().definitions().blocks().matrixFrame().block().getDefaultState();
@@ -71,7 +74,7 @@ public class StorageChunkGenerator extends ChunkGenerator {
}
private static BiomeSource createBiomeProvider() {
return new FixedBiomeSource(StorageCellBiome.INSTANCE);
return new FixedBiomeSource(SpatialStorageBiome.INSTANCE);
}
private static StructuresConfig createSettings() {
@@ -0,0 +1,55 @@
package appeng.spatial;
import appeng.core.AppEng;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionOptions;
import net.minecraft.world.dimension.DimensionType;
/**
* IDs for the spatial storage world related dimension objects.
*/
public final class SpatialStorageDimensionIds {
/**
* ID of the {@link DimensionType} used for the spatial storage world.
* <p>
* This is defined in {@link appeng.mixins.spatial.DimensionTypeMixin}.
*/
public static final RegistryKey<DimensionType> DIMENSION_TYPE_ID = RegistryKey
.of(Registry.DIMENSION_TYPE_KEY, AppEng.makeId("spatial_storage"));
/**
* ID of the {@link net.minecraft.world.gen.chunk.ChunkGenerator} used for the spatial
* storage world.
*/
public static final Identifier CHUNK_GENERATOR_ID = AppEng.makeId("spatial_storage");
/**
* ID of the {@link net.minecraft.world.biome.Biome} used for the spatial
* storage world.
*/
public static final Identifier BIOME_ID = AppEng.makeId("spatial_storage");
/**
* ID of the {@link DimensionOptions} used for the spatial storage dimension.
* <p>
* This is defined in
* <code>data/minecraft/dimension/appliedenergistics2/spatial_storage.json</code>
*/
public static final RegistryKey<DimensionOptions> DIMENSION_ID = RegistryKey.of(Registry.DIMENSION_OPTIONS,
AppEng.makeId("spatial_storage"));
/**
* ID of the {@link World} that is instantiated from the dimension/dimension
* type.
*/
public static final RegistryKey<World> WORLD_ID = RegistryKey.of(Registry.DIMENSION,
AppEng.makeId("spatial_storage"));
private SpatialStorageDimensionIds() {
}
}
@@ -40,13 +40,13 @@ import appeng.api.util.WorldCoord;
import appeng.core.Api;
import appeng.core.AppEng;
public class StorageHelper {
public class SpatialStorageHelper {
private static StorageHelper instance;
private static SpatialStorageHelper instance;
public static StorageHelper getInstance() {
public static SpatialStorageHelper getInstance() {
if (instance == null) {
instance = new StorageHelper();
instance = new SpatialStorageHelper();
}
return instance;
}
@@ -99,7 +99,7 @@ public class StorageHelper {
ChunkStatus.FULL, true);
if (entity instanceof ServerPlayerEntity
&& link.dim.getDimensionRegistryKey() == SpatialDimensionManager.STORAGE_DIMENSION_TYPE) {
&& link.dim.getDimensionRegistryKey() == SpatialStorageDimensionIds.DIMENSION_TYPE_ID) {
AppEng.instance().getAdvancementTriggers().getSpatialExplorer().trigger((ServerPlayerEntity) entity);
}
@@ -0,0 +1,189 @@
package appeng.spatial;
import java.util.Locale;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
/**
* A plot inside the storage cell world that is assigned to a specific storage
* cell.
*/
public class SpatialStoragePlot {
private static final String TAG_ID = "id";
private static final String TAG_SIZE = "size";
private static final String TAG_OWNER = "owner";
private static final String TAG_LAST_TRANSITION = "last_transition";
private static final int REGION_SIZE = 512;
public static final int MAX_SIZE = 128;
/**
* Id of the plot.
*/
private final int id;
/**
* The storage size of this dimension. This is dictated 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;
/**
* AE2 player id of who primarily owned the network when the storage plot was
* allocated.
*/
private final int owner;
/**
* Information about the last transition into this plot.
*/
@Nullable
private TransitionInfo lastTransition;
public SpatialStoragePlot(int id, BlockPos size, int owner) {
this.id = id;
this.size = size;
this.owner = owner;
if (size.getX() < 1 || size.getY() < 1 || size.getZ() < 1) {
throw new IllegalArgumentException("Plot size " + size + " is smaller than minimum size.");
}
if (size.getX() > MAX_SIZE || size.getY() > MAX_SIZE || size.getZ() > MAX_SIZE) {
throw new IllegalArgumentException("Plot size " + size + " exceeds maximum size of " + MAX_SIZE);
}
}
public int getId() {
return id;
}
/**
* The size in blocks of the plot in the storage dimension.
*
* @see #getOrigin()
*/
public BlockPos getSize() {
return size;
}
/**
* Returns the AE player id of the owner of this plot, or -1 if unknown.
*
* @see appeng.core.worlddata.IWorldPlayerData
*/
public int getOwner() {
return owner;
}
/**
* Returns information about the last transition into this plot (if any).
*/
@Nullable
public TransitionInfo getLastTransition() {
return lastTransition;
}
void setLastTransition(TransitionInfo info) {
this.lastTransition = info;
}
/**
* The origin of this plot within the spatial storage dimension.
* <p>
* To map an integer to a specific position, it uses the following algorithm.
*
* The 2 least significant bits determine the sign for the x and z axis. Every
* other pack of 2 bits locate the plot within a quadrant of a increasing area
* by the bit position.
*
* The first 2 bits after the sign address a quadrant within 1024x1024 blocks
* (or 4 region files)
*
* Every further will continue to double both x and z values. E.g. 2048x2048 for
* the 3rd pack and 4096x4096 for the 4th.
*
* @see #getSize()
*/
public BlockPos getOrigin() {
int signBits = id & 0b11;
int offsetBits = id >> 2;
int offsetScale = 1;
int posx = REGION_SIZE / 2;
int posz = REGION_SIZE / 2;
// find quadrant
while (offsetBits != 0) {
posx += REGION_SIZE * offsetScale * (offsetBits & 0b01);
posz += REGION_SIZE * offsetScale * (offsetBits >> 1 & 0b01);
offsetBits >>= 2;
offsetScale <<= 1;
}
// mirror in one of 4 directions
// First flip the z axis on every increment and then every two the x axis
if ((signBits & 0b01) != 0) {
posz *= -1;
}
if ((signBits & 0b10) != 0) {
posx *= -1;
}
// offset from cell center
//
// This is to ensure a 128x128x128 block plot (or 8x8 chunks) is centered within
// the region.
// This provides 12 chunks around it, so the default chunk loading radius on
// servers of 10 will prevent adjacent regions to be generated. As well as a 24
// chunks to the next plot.
posx -= 64;
posz -= 64;
return new BlockPos(posx, 64, posz);
}
/**
* Returns the filename of the region in the world save containing this plot.
*/
public String getRegionFilename() {
BlockPos origin = this.getOrigin();
ChunkPos originChunk = new ChunkPos(origin);
return String.format(Locale.ROOT, "r.%d.%d.mca", originChunk.getRegionX(), originChunk.getRegionZ());
}
public CompoundTag toTag() {
CompoundTag tag = new CompoundTag();
tag.putInt(TAG_ID, id);
tag.put(TAG_SIZE, NbtHelper.fromBlockPos(size));
tag.putInt(TAG_OWNER, owner);
if (lastTransition != null) {
tag.put(TAG_LAST_TRANSITION, lastTransition.toTag());
}
return tag;
}
public static SpatialStoragePlot fromTag(CompoundTag tag) {
int id = tag.getInt(TAG_ID);
BlockPos size = NbtHelper.toBlockPos(tag.getCompound(TAG_SIZE));
int ownerId = tag.getInt(TAG_OWNER);
SpatialStoragePlot plot = new SpatialStoragePlot(id, size, ownerId);
if (tag.contains(TAG_LAST_TRANSITION, NbtType.COMPOUND)) {
plot.lastTransition = TransitionInfo.fromTag(tag.getCompound(TAG_LAST_TRANSITION));
}
return plot;
}
}
@@ -0,0 +1,118 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.spatial;
import java.util.List;
import javax.annotation.Nullable;
import appeng.core.AppEng;
import net.minecraft.block.BlockState;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import appeng.core.AELog;
import appeng.core.Api;
/**
* Allocates and manages plots for spatial storage in the spatial storage world.
*/
public final class SpatialStoragePlotManager {
public static final SpatialStoragePlotManager INSTANCE = new SpatialStoragePlotManager();
private SpatialStoragePlotManager() {
}
/**
* Gets the world used to store spatial storage cell's content.
*/
public ServerWorld getWorld() {
MinecraftServer server = getServer();
ServerWorld world = server.getWorld(SpatialStorageDimensionIds.WORLD_ID);
if (world == null) {
throw new IllegalStateException("The storage cell world is missing.");
}
return world;
}
private SpatialStorageWorldData getWorldData() {
return getWorld().getChunkManager().getPersistentStateManager().getOrCreate(SpatialStorageWorldData::new,
SpatialStorageWorldData.ID);
}
@Nullable
public SpatialStoragePlot getPlot(int plotId) {
if (plotId == -1) {
return null;
}
return getWorldData().getPlotById(plotId);
}
public SpatialStoragePlot allocatePlot(BlockPos size, int ownerId) {
SpatialStoragePlot plot = getWorldData().allocatePlot(size, ownerId);
AELog.info("Allocating storage cell plot %d with size %s for %d", plot.getId(), size, ownerId);
return plot;
}
/**
* Sets the last source for a spatial storage transition into the given plot.
* This is used to allow the server-admin commands to know where the content of
* a given plot came from.
*/
public void setLastTransition(int plotId, TransitionInfo info) {
getWorldData().setLastTransition(plotId, info);
}
/**
* Returns an immutable list of all plots.
*/
public List<SpatialStoragePlot> getPlots() {
return getWorldData().getPlots();
}
public void freePlot(int plotId, boolean resetBlocks) {
SpatialStoragePlot plot = getPlot(plotId);
if (plot == null) {
return; // Already removed apparently
}
if (resetBlocks) {
BlockPos from = plot.getOrigin();
BlockPos to = from.add(plot.getSize()).add(-1, -1, -1);
AELog.info("Clearing spatial storage plot %s (%s -> %s)", plotId, from, to);
// This is slow, but it should usually be just an admin-command
ServerWorld world = getWorld();
BlockState matrixFrame = Api.instance().definitions().blocks().matrixFrame().block().getDefaultState();
for (BlockPos blockPos : BlockPos.iterate(from, to)) {
world.setBlockState(blockPos, matrixFrame);
}
}
getWorldData().removePlot(plotId);
}
private static MinecraftServer getServer() {
return AppEng.instance().getServer();
}
}
@@ -7,8 +7,11 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.render.SkyProperties;
import net.minecraft.util.math.Vec3d;
/**
* Defines properties for how the sky in the spatial storage world is rendered.
*/
@Environment(EnvType.CLIENT)
public class StorageSkyProperties {
public class SpatialStorageSkyProperties {
// See the fabric version of this to get any idea what its doing
public static final SkyProperties INSTANCE = new SkyProperties(Float.NaN /* disables clouds */, false,
@@ -0,0 +1,110 @@
package appeng.spatial;
import java.util.List;
import com.google.common.collect.ImmutableList;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.PersistentState;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import appeng.core.AELog;
/**
* Extra data attached to the spatial storage world.
*/
public class SpatialStorageWorldData extends PersistentState {
/**
* ID of this data when it is attached to a world.
*/
public static final String ID = "ae2_spatial_storage";
// Used to allow forward compatibility
private static final int CURRENT_FORMAT = 2;
private static final String TAG_FORMAT = "format";
private static final String TAG_PLOTS = "plots";
private final Int2ObjectOpenHashMap<SpatialStoragePlot> plots = new Int2ObjectOpenHashMap<>();
public SpatialStorageWorldData() {
super(ID);
}
public SpatialStoragePlot getPlotById(int id) {
return plots.get(id);
}
public List<SpatialStoragePlot> getPlots() {
return ImmutableList.copyOf(plots.values());
}
public SpatialStoragePlot allocatePlot(BlockPos size, int owner) {
int nextId = 1;
for (int id : plots.keySet()) {
if (id >= nextId) {
nextId = id + 1;
}
}
SpatialStoragePlot plot = new SpatialStoragePlot(nextId, size, owner);
plots.put(nextId, plot);
markDirty();
return plot;
}
public void removePlot(int plotId) {
plots.remove(plotId);
markDirty();
}
public void setLastTransition(int plotId, TransitionInfo info) {
SpatialStoragePlot plot = plots.get(plotId);
if (plot != null) {
plot.setLastTransition(info);
}
markDirty();
}
@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);
}
ListTag plotsTag = tag.getList(TAG_PLOTS, NbtType.COMPOUND);
for (Tag plotTag : plotsTag) {
SpatialStoragePlot plot = SpatialStoragePlot.fromTag((CompoundTag) plotTag);
if (plots.containsKey(plot.getId())) {
AELog.warn("Overwriting duplicate plot id %s", plot.getId());
}
plots.put(plot.getId(), plot);
}
}
@Override
public CompoundTag toTag(CompoundTag tag) {
tag.putInt(TAG_FORMAT, CURRENT_FORMAT);
ListTag plotTags = new ListTag();
for (SpatialStoragePlot plot : plots.values()) {
plotTags.add(plot.toTag());
}
tag.put(TAG_PLOTS, plotTags);
return tag;
}
}
@@ -0,0 +1,69 @@
package appeng.spatial;
import java.time.Instant;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
/**
* Defines the source world and area of a transition into the spatial storage
* plot.
*/
public final class TransitionInfo {
public static final String TAG_WORLD_ID = "world_id";
public static final String TAG_MIN = "min";
public static final String TAG_MAX = "max";
public static final String TAG_TIMESTAMP = "timestamp";
private final Identifier worldId;
private final BlockPos min;
private final BlockPos max;
private final Instant timestamp;
public TransitionInfo(Identifier worldId, BlockPos min, BlockPos max, Instant timestamp) {
this.worldId = worldId;
this.min = min.toImmutable();
this.max = max.toImmutable();
this.timestamp = timestamp;
}
public Identifier getWorldId() {
return worldId;
}
public BlockPos getMin() {
return min;
}
public BlockPos getMax() {
return max;
}
public Instant getTimestamp() {
return timestamp;
}
public CompoundTag toTag() {
CompoundTag tag = new CompoundTag();
tag.putString(TAG_WORLD_ID, worldId.toString());
tag.put(TAG_MIN, NbtHelper.fromBlockPos(min));
tag.put(TAG_MAX, NbtHelper.fromBlockPos(max));
tag.putLong(TAG_TIMESTAMP, timestamp.toEpochMilli());
return tag;
}
public static TransitionInfo fromTag(CompoundTag tag) {
Identifier worldId = new Identifier(tag.getString(TAG_WORLD_ID));
BlockPos min = NbtHelper.toBlockPos(tag.getCompound(TAG_MIN));
BlockPos max = NbtHelper.toBlockPos(tag.getCompound(TAG_MAX));
Instant timestamp = Instant.ofEpochMilli(tag.getLong(TAG_TIMESTAMP));
return new TransitionInfo(worldId, min, max, timestamp);
}
}
@@ -34,7 +34,6 @@ import alexiil.mc.lib.attributes.item.FixedItemInv;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.YesNo;
import appeng.api.implementations.TransitionResult;
import appeng.api.implementations.items.ISpatialStorageCell;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGrid;
@@ -137,14 +136,18 @@ public class SpatialIOPortBlockEntity extends AENetworkInvBlockEntity implements
if (Math.abs(pr - req) < req * 0.001) {
final MENetworkEvent res = gi.postEvent(new MENetworkSpatialEvent(this, req));
if (!res.isCanceled()) {
int playerId = -1;
// Prefer player id from security system, but if unavailable, use the
// player who placed the grid node (if any)
int playerId;
if (this.getProxy().getSecurity().isAvailable()) {
playerId = this.getProxy().getSecurity().getOwner();
} else {
playerId = this.getProxy().getNode().getPlayerID();
}
final TransitionResult tr = sc.doSpatialTransition(cell, serverWorld, spc.getMin(),
spc.getMax(), playerId);
if (tr.success) {
boolean success = sc.doSpatialTransition(cell, serverWorld, spc.getMin(), spc.getMax(),
playerId);
if (success) {
energy.extractAEPower(req, Actionable.MODULATE, PowerMultiplier.CONFIG);
this.inv.setInvStack(0, ItemStack.EMPTY, Simulation.ACTION);
this.inv.setInvStack(1, cell, Simulation.ACTION);
@@ -37,6 +37,12 @@ public class MeteoriteStructurePiece extends StructurePiece {
public static final StructurePieceType TYPE = StructurePieceType.register(MeteoriteStructurePiece::new, "ae2mtrt");
public static void register() {
// THIS MUST BE CALLED otherwise the static initializer above will not run,
// unless world generation is actually invoked, which means that chunks may
// be loaded without this being registered as a structure piece!
}
private final PlacedMeteoriteSettings settings;
protected MeteoriteStructurePiece(BlockPos center, float coreRadius, CraterType craterType, FalloutMode fallout,
@@ -4,14 +4,14 @@
"package": "appeng.mixins",
"compatibilityLevel": "JAVA_8",
"mixins": [
"spatial.DimensionTypeMixin",
"spatial.DimensionOptionMixin",
"CriteriaRegisterMixin",
"RemainderSetter",
"ScreenHandlerListeners",
"ShapelessRecipeMixin",
"SlotMixin",
"TntAccessor",
"DimensionTypeMixin",
"MinecraftServerMixin",
"ThreadedAnvilChunkStorageAccessor",
"GenerationSettingsAccessor",
"BiomeAccessor",
@@ -19,13 +19,17 @@
"HopperMixin"
],
"client": [
"spatial.SkyRenderMixin",
"spatial.SkyPropertiesMixin",
"unlitquad.ModelLoaderMixin",
"unlitquad.JsonUnbakedModelMixin",
"unlitquad.ModelElementFaceDeserializerMixin",
"unlitquad.BakedQuadAccessor",
"ModelsReloadMixin",
"RenderPhaseMixin",
"BakedModelManagerAccessor",
"RenderEncodedPatternMixin",
"ItemRendererAccessor",
"SkyRenderMixin",
"SkyPropertiesMixin",
"MinecraftClientAccessor"
],
"server": [],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"block": "block/stone",
@@ -42,50 +41,32 @@
"down": {
"texture": "#quartz",
"cullface": "down",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"east": {
"texture": "#quartz",
"cullface": "east",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"north": {
"texture": "#quartz",
"cullface": "north",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"south": {
"texture": "#quartz",
"cullface": "south",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"up": {
"texture": "#quartz",
"cullface": "up",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"west": {
"texture": "#quartz",
"cullface": "west",
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
},
"from": [0, 0, 0],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lights_bright": "appliedenergistics2:block/chest/lights_on_bright",
"lights_medium": "appliedenergistics2:block/chest/lights_on_medium",
@@ -13,10 +12,7 @@
"up": {
"texture": "#lights_bright",
"tintindex": 3,
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"up": {
"texture": "#lights_medium",
"tintindex": 2,
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"up": {
"texture": "#lights_dark",
"tintindex": 1,
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"block": "appliedenergistics2:block/controller_powered",
@@ -12,50 +11,32 @@
"down": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"east": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"north": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"south": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"up": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"west": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
},
"from": [0, 0, 0],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"block": "appliedenergistics2:block/controller_powered",
@@ -12,50 +11,32 @@
"down": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"east": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"north": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"south": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"up": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"west": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
},
"from": [0, 0, 0],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"block": "appliedenergistics2:block/controller_column_powered",
@@ -12,50 +11,32 @@
"down": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"east": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"north": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"south": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"up": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"west": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
},
"from": [0, 0, 0],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"block": "appliedenergistics2:block/controller_column_powered",
@@ -12,50 +11,32 @@
"down": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"east": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"north": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"south": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"up": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
},
"west": {
"texture": "#lights",
"uv": [0, 0, 16, 16],
"uvlightmap": {
"block": 0.007,
"sky": 0.007
}
"unlit": true
}
},
"from": [0, 0, 0],
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"all": "appliedenergistics2:block/molecular_assembler_lights"
@@ -13,55 +12,37 @@
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "down",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "up",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"north": {
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "north",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"south": {
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "south",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "west",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#all",
"uv": [2.6, 2.6, 13.4, 13.4],
"cullface": "east",
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"parent": "block/block",
"textures": {
"particle": "appliedenergistics2:block/security_station_side",
@@ -42,10 +41,7 @@
"up": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -56,10 +52,7 @@
"up": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -70,10 +63,7 @@
"up": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"ambientocclusion": false,
"textures": {
"torch": "appliedenergistics2:block/wireless_access_point_on"
@@ -39,10 +38,7 @@
"texture": "#torch",
"uv": [7, 7, 9, 9],
"rotation": 270,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -55,19 +51,13 @@
"texture": "#torch",
"uv": [6, 6, 10, 10],
"rotation": 90,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"down": {
"texture": "#torch",
"uv": [6, 6, 10, 10],
"rotation": 270,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -79,19 +69,13 @@
"west": {
"texture": "#torch",
"uv": [6, 6, 10, 10],
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#torch",
"uv": [6, 6, 10, 10],
"rotation": 180,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -10,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -10,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/conversion_monitor_bright",
"lightsMedium": "appliedenergistics2:part/conversion_monitor_medium_locked",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/conversion_monitor_bright",
"lightsMedium": "appliedenergistics2:part/conversion_monitor_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/crafting_terminal_bright",
"lightsMedium": "appliedenergistics2:part/crafting_terminal_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/fluid_terminal_bright",
"lightsMedium": "appliedenergistics2:part/fluid_terminal_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/interface_terminal_bright",
"lightsMedium": "appliedenergistics2:part/interface_terminal_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"ambientocclusion": false,
"textures": {
"emitter": "appliedenergistics2:part/level_emitter_on",
@@ -40,10 +39,7 @@
"texture": "#emitter",
"uv": [6, 7, 8, 9],
"rotation": 270,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -56,19 +52,13 @@
"texture": "#emitter",
"uv": [5, 6, 9, 10],
"rotation": 90,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"down": {
"texture": "#emitter",
"uv": [5, 6, 9, 10],
"rotation": 270,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -80,19 +70,13 @@
"west": {
"texture": "#emitter",
"uv": [5, 6, 9, 10],
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#emitter",
"uv": [5, 6, 9, 10],
"rotation": 180,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"sides": "appliedenergistics2:part/monitor_sides",
"back": "appliedenergistics2:part/monitor_back",
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"ambientocclusion": false,
"textures": {
"lights": "appliedenergistics2:part/monitor_light"
@@ -13,10 +12,7 @@
"north": {
"texture": "#lights",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lights": "appliedenergistics2:part/monitor_light"
},
@@ -11,10 +10,7 @@
"north": {
"texture": "#lights",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lights": "appliedenergistics2:part/monitor_light"
},
@@ -11,10 +10,7 @@
"north": {
"texture": "#lights",
"tintindex": 4,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/pattern_terminal_bright",
"lightsMedium": "appliedenergistics2:part/pattern_terminal_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_has_channel"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"indicator": "appliedenergistics2:part/monitor_sides_status_on"
},
@@ -11,34 +10,22 @@
"down": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"up": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"east": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
},
"west": {
"texture": "#indicator",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/storage_monitor_bright",
"lightsMedium": "appliedenergistics2:part/storage_monitor_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}
@@ -1,5 +1,4 @@
{
"loader": "appliedenergistics2:uvlightmap",
"textures": {
"lightsBright": "appliedenergistics2:part/storage_monitor_bright",
"lightsMedium": "appliedenergistics2:part/storage_monitor_medium",
@@ -13,10 +12,7 @@
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -27,10 +23,7 @@
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
},
@@ -41,10 +34,7 @@
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
"unlit": true
}
}
}

Some files were not shown because too many files have changed in this diff Show More