Lots of fixes

This commit is contained in:
Sebastian Hartte
2020-07-23 02:38:32 +02:00
parent 1933b4b10d
commit 9fcfbf31be
100 changed files with 1771 additions and 1866 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ dependencies {
modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}"
modImplementation "alexiil.mc.lib:libblockattributes-all:0.7.0" modImplementation "alexiil.mc.lib:libblockattributes-all:0.7.1-pre.4"
modImplementation "me.shedaniel:RoughlyEnoughItems:4.6.6" modImplementation "me.shedaniel:RoughlyEnoughItems:4.6.6"
modImplementation "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75" modImplementation "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75"
@@ -0,0 +1,48 @@
package appeng.api.parts;
import appeng.api.util.AEPartLocation;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
/**
* This interface can be implemented by baked models returned by {@link IPart#getStaticModels()} to indicate that
* they would like to use the model data returned by {@link IPart#getModelData()}.
*/
public interface IDynamicPartBakedModel extends BakedModel {
/**
* See {@link net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel#emitBlockQuads(BlockRenderView, BlockState, BlockPos, Supplier, RenderContext)}
* for context.
* <p>
* The given <code>context</code> will already have been transformed so that the model renders from the
* rotated location the part is attached to.
*
* @param partSide The side of the cable bus that the part is attached to.
* @param modelData The model data returned by {@link IPart#getModelData()}
*/
void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context,
Direction partSide, @Nullable Object modelData);
/**
* Unless you use your dynamic model for other purposes, this method will not be called.
*/
@Override
default List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return Collections.emptyList();
}
}
@@ -141,7 +141,7 @@ public class AEBaseBlockItem extends BlockItem {
} }
if (tile instanceof IGridProxyable) { if (tile instanceof IGridProxyable) {
// FIXME FABRIC ((IGridProxyable) tile).getProxy().setOwner(player); ((IGridProxyable) tile).getProxy().setOwner(player);
} }
tile.onPlacement(context); tile.onPlacement(context);
@@ -28,6 +28,8 @@ import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.AttributeList; import alexiil.mc.lib.attributes.AttributeList;
import alexiil.mc.lib.attributes.AttributeProvider; import alexiil.mc.lib.attributes.AttributeProvider;
import alexiil.mc.lib.attributes.item.FixedItemInv; import alexiil.mc.lib.attributes.item.FixedItemInv;
import appeng.block.networking.CableBusBlock;
import appeng.tile.networking.CableBusBlockEntity;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
@@ -206,7 +208,7 @@ public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBas
return ActionResult.FAIL; return ActionResult.FAIL;
} }
if (/* FIXME FABRIC tile instanceof CableBusBlockEntity || */ tile instanceof SkyChestBlockEntity) { if (tile instanceof CableBusBlockEntity || tile instanceof SkyChestBlockEntity) {
return ActionResult.FAIL; return ActionResult.FAIL;
} }
@@ -233,7 +235,7 @@ public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBas
return ActionResult.FAIL; return ActionResult.FAIL;
} }
if (heldItem.getItem() instanceof IMemoryCard /* FIXME FABRIC && !(this instanceof CableBusBlock)*/) { if (heldItem.getItem() instanceof IMemoryCard && !(this instanceof CableBusBlock)) {
final IMemoryCard memoryCard = (IMemoryCard) heldItem.getItem(); final IMemoryCard memoryCard = (IMemoryCard) heldItem.getItem();
final AEBaseBlockEntity tileEntity = this.getBlockEntity(world, pos); final AEBaseBlockEntity tileEntity = this.getBlockEntity(world, pos);
@@ -18,25 +18,21 @@
package appeng.block.crafting; package appeng.block.crafting;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock; import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator; import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener; import appeng.container.ContainerOpener;
import appeng.container.implementations.CraftingCPUContainer; import appeng.container.implementations.CraftingCPUContainer;
import appeng.tile.crafting.CraftingBlockEntity; import appeng.tile.crafting.CraftingBlockEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public abstract class AbstractCraftingUnitBlock<T extends CraftingBlockEntity> extends AEBaseTileBlock<T> { public abstract class AbstractCraftingUnitBlock<T extends CraftingBlockEntity> extends AEBaseTileBlock<T> {
public static final BooleanProperty FORMED = BooleanProperty.of("formed"); public static final BooleanProperty FORMED = BooleanProperty.of("formed");
@@ -57,16 +53,6 @@ public abstract class AbstractCraftingUnitBlock<T extends CraftingBlockEntity> e
builder.add(FORMED); builder.add(FORMED);
} }
@Override
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
TileEntity te = worldIn.getTileEntity(currentPos);
if (te != null) {
te.requestModelDataUpdate();
}
return super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
}
@Override @Override
public void neighborUpdate(final BlockState state, final World worldIn, final BlockPos pos, final Block blockIn, public void neighborUpdate(final BlockState state, final World worldIn, final BlockPos pos, final Block blockIn,
final BlockPos fromPos, boolean isMoving) { final BlockPos fromPos, boolean isMoving) {
@@ -64,7 +64,7 @@ import appeng.util.Platform;
public class ChargerBlock extends AEBaseTileBlock<ChargerBlockEntity> { public class ChargerBlock extends AEBaseTileBlock<ChargerBlockEntity> {
public ChargerBlock() { public ChargerBlock() {
super(defaultProps(Material.METAL).solidBlock((state, world, pos) -> false)); super(defaultProps(Material.METAL).nonOpaque());
} }
@Override @Override
@@ -29,6 +29,8 @@ import appeng.client.render.cablebus.CableBusBakedModel;
import appeng.client.render.cablebus.CableBusBreakingParticle; import appeng.client.render.cablebus.CableBusBreakingParticle;
import appeng.client.render.cablebus.CableBusRenderState; import appeng.client.render.cablebus.CableBusRenderState;
import appeng.core.AppEng; import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ClickPacket;
import appeng.helpers.AEMaterials; import appeng.helpers.AEMaterials;
import appeng.integration.abstraction.IAEFacade; import appeng.integration.abstraction.IAEFacade;
import appeng.parts.ICableBusContainer; import appeng.parts.ICableBusContainer;
@@ -331,9 +333,8 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
final Vec3d hitVec = rtr.getPos().subtract(new Vec3d(pos.getX(), pos.getY(), pos.getZ())); final Vec3d hitVec = rtr.getPos().subtract(new Vec3d(pos.getX(), pos.getY(), pos.getZ()));
if (this.cb(worldIn, pos).clicked(player, Hand.MAIN_HAND, hitVec)) { if (this.cb(worldIn, pos).clicked(player, Hand.MAIN_HAND, hitVec)) {
throw new IllegalStateException(); NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x,
// FIXME FABRIC NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, Hand.MAIN_HAND, true));
// FIXME FABRIC (float) hitVec.y, (float) hitVec.z, Hand.MAIN_HAND, true));
} }
} }
} }
@@ -58,10 +58,7 @@ public class WirelessBlock extends AEBaseTileBlock<WirelessBlockEntity> {
public static final EnumProperty<State> STATE = EnumProperty.of("state", State.class); public static final EnumProperty<State> STATE = EnumProperty.of("state", State.class);
public WirelessBlock() { public WirelessBlock() {
super(defaultProps(AEMaterials.GLASS) super(defaultProps(AEMaterials.GLASS).nonOpaque());
.nonOpaque()
.solidBlock((state, world, pos) -> false)
);
this.setDefaultState(this.getDefaultState().with(STATE, State.OFF)); this.setDefaultState(this.getDefaultState().with(STATE, State.OFF));
} }
@@ -42,8 +42,7 @@ import appeng.util.Platform;
public class PaintSplotchesBlock extends AEBaseTileBlock<PaintSplotchesBlockEntity> { public class PaintSplotchesBlock extends AEBaseTileBlock<PaintSplotchesBlockEntity> {
public PaintSplotchesBlock() { public PaintSplotchesBlock() {
super(defaultProps(Material.WATER, MaterialColor.CLEAR).solidBlock((state, world, pos) -> false) super(defaultProps(Material.WATER, MaterialColor.CLEAR).nonOpaque().air());
.air());
} }
@Override @Override
@@ -41,7 +41,7 @@ public class MatrixFrameBlock extends AEBaseBlock {
private static final Material MATERIAL = new Material(MaterialColor.CLEAR, false, true, true, false, false, false, PistonBehavior.PUSH_ONLY); private static final Material MATERIAL = new Material(MaterialColor.CLEAR, false, true, true, false, false, false, PistonBehavior.PUSH_ONLY);
public MatrixFrameBlock() { public MatrixFrameBlock() {
super(Settings.of(MATERIAL).strength(-1.0F, 6000000.0F).solidBlock((state, world, pos) -> false).dropsNothing()); super(Settings.of(MATERIAL).strength(-1.0F, 6000000.0F).nonOpaque().dropsNothing());
} }
@Override @Override
+142 -15
View File
@@ -8,16 +8,94 @@ import appeng.bootstrap.ModelsReloadCallback;
import appeng.bootstrap.components.IClientSetupComponent; import appeng.bootstrap.components.IClientSetupComponent;
import appeng.bootstrap.components.IItemColorRegistrationComponent; import appeng.bootstrap.components.IItemColorRegistrationComponent;
import appeng.bootstrap.components.IModelBakeComponent; import appeng.bootstrap.components.IModelBakeComponent;
import appeng.client.gui.implementations.*; import appeng.client.gui.implementations.CellWorkbenchScreen;
import appeng.client.gui.implementations.ChestScreen;
import appeng.client.gui.implementations.CondenserScreen;
import appeng.client.gui.implementations.CraftAmountScreen;
import appeng.client.gui.implementations.CraftConfirmScreen;
import appeng.client.gui.implementations.CraftingCPUScreen;
import appeng.client.gui.implementations.CraftingStatusScreen;
import appeng.client.gui.implementations.CraftingTermScreen;
import appeng.client.gui.implementations.DriveScreen;
import appeng.client.gui.implementations.FormationPlaneScreen;
import appeng.client.gui.implementations.GrinderScreen;
import appeng.client.gui.implementations.IOPortScreen;
import appeng.client.gui.implementations.InscriberScreen;
import appeng.client.gui.implementations.InterfaceScreen;
import appeng.client.gui.implementations.InterfaceTerminalScreen;
import appeng.client.gui.implementations.LevelEmitterScreen;
import appeng.client.gui.implementations.MEMonitorableScreen;
import appeng.client.gui.implementations.MEPortableCellScreen;
import appeng.client.gui.implementations.MolecularAssemblerScreen;
import appeng.client.gui.implementations.NetworkStatusScreen;
import appeng.client.gui.implementations.NetworkToolScreen;
import appeng.client.gui.implementations.PatternTermScreen;
import appeng.client.gui.implementations.PriorityScreen;
import appeng.client.gui.implementations.QNBScreen;
import appeng.client.gui.implementations.QuartzKnifeScreen;
import appeng.client.gui.implementations.SecurityStationScreen;
import appeng.client.gui.implementations.SkyChestScreen;
import appeng.client.gui.implementations.SpatialIOPortScreen;
import appeng.client.gui.implementations.StorageBusScreen;
import appeng.client.gui.implementations.UpgradeableScreen;
import appeng.client.gui.implementations.VibrationChamberScreen;
import appeng.client.gui.implementations.WirelessScreen;
import appeng.client.gui.implementations.WirelessTermScreen;
import appeng.client.render.FacadeItemModel;
import appeng.client.render.SimpleModelLoader; import appeng.client.render.SimpleModelLoader;
import appeng.client.render.cablebus.CableBusModelLoader; import appeng.client.render.cablebus.CableBusModelLoader;
import appeng.client.render.cablebus.P2PTunnelFrequencyModel;
import appeng.client.render.crafting.CraftingCubeModel; import appeng.client.render.crafting.CraftingCubeModel;
import appeng.client.render.effects.*; import appeng.client.render.effects.ChargedOreFX;
import appeng.client.render.model.*; import appeng.client.render.effects.CraftingFx;
import appeng.client.render.effects.EnergyFx;
import appeng.client.render.effects.LightningArcFX;
import appeng.client.render.effects.LightningFX;
import appeng.client.render.effects.MatterCannonFX;
import appeng.client.render.effects.ParticleTypes;
import appeng.client.render.effects.VibrantFX;
import appeng.client.render.model.BiometricCardModel;
import appeng.client.render.model.ColorApplicatorModel;
import appeng.client.render.model.DriveModel;
import appeng.client.render.model.GlassModel;
import appeng.client.render.model.MemoryCardModel;
import appeng.client.render.model.SkyCompassModel;
import appeng.client.render.spatial.SpatialPylonModel; import appeng.client.render.spatial.SpatialPylonModel;
import appeng.client.render.tesr.InscriberTESR; import appeng.client.render.tesr.InscriberTESR;
import appeng.client.render.tesr.SkyChestTESR; import appeng.client.render.tesr.SkyChestTESR;
import appeng.container.implementations.*; import appeng.container.implementations.CellWorkbenchContainer;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.CondenserContainer;
import appeng.container.implementations.CraftAmountContainer;
import appeng.container.implementations.CraftConfirmContainer;
import appeng.container.implementations.CraftingCPUContainer;
import appeng.container.implementations.CraftingStatusContainer;
import appeng.container.implementations.CraftingTermContainer;
import appeng.container.implementations.DriveContainer;
import appeng.container.implementations.FormationPlaneContainer;
import appeng.container.implementations.GrinderContainer;
import appeng.container.implementations.IOPortContainer;
import appeng.container.implementations.InscriberContainer;
import appeng.container.implementations.InterfaceContainer;
import appeng.container.implementations.InterfaceTerminalContainer;
import appeng.container.implementations.LevelEmitterContainer;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.container.implementations.MEPortableCellContainer;
import appeng.container.implementations.MolecularAssemblerContainer;
import appeng.container.implementations.NetworkStatusContainer;
import appeng.container.implementations.NetworkToolContainer;
import appeng.container.implementations.PatternTermContainer;
import appeng.container.implementations.PriorityContainer;
import appeng.container.implementations.QNBContainer;
import appeng.container.implementations.QuartzKnifeContainer;
import appeng.container.implementations.SecurityStationContainer;
import appeng.container.implementations.SkyChestContainer;
import appeng.container.implementations.SpatialIOPortContainer;
import appeng.container.implementations.StorageBusContainer;
import appeng.container.implementations.UpgradeableContainer;
import appeng.container.implementations.VibrationChamberContainer;
import appeng.container.implementations.WirelessContainer;
import appeng.container.implementations.WirelessTermContainer;
import appeng.core.Api; import appeng.core.Api;
import appeng.core.ApiDefinitions; import appeng.core.ApiDefinitions;
import appeng.core.AppEng; import appeng.core.AppEng;
@@ -25,10 +103,26 @@ import appeng.core.AppEngBase;
import appeng.core.features.registries.PartModels; import appeng.core.features.registries.PartModels;
import appeng.core.sync.network.ClientNetworkHandler; import appeng.core.sync.network.ClientNetworkHandler;
import appeng.core.worlddata.WorldData; import appeng.core.worlddata.WorldData;
import appeng.entity.*; import appeng.entity.ChargedQuartzEntity;
import appeng.fluids.client.gui.*; import appeng.entity.GrowingCrystalEntity;
import appeng.fluids.container.*; import appeng.entity.SingularityEntity;
import appeng.entity.TinyTNTPrimedEntity;
import appeng.entity.TinyTNTPrimedRenderer;
import appeng.fluids.client.gui.FluidFormationPlaneScreen;
import appeng.fluids.client.gui.FluidIOScreen;
import appeng.fluids.client.gui.FluidInterfaceScreen;
import appeng.fluids.client.gui.FluidLevelEmitterScreen;
import appeng.fluids.client.gui.FluidStorageBusScreen;
import appeng.fluids.client.gui.FluidTerminalScreen;
import appeng.fluids.container.FluidFormationPlaneContainer;
import appeng.fluids.container.FluidIOContainer;
import appeng.fluids.container.FluidInterfaceContainer;
import appeng.fluids.container.FluidLevelEmitterContainer;
import appeng.fluids.container.FluidStorageBusContainer;
import appeng.fluids.container.FluidTerminalContainer;
import appeng.hooks.ClientTickHandler; import appeng.hooks.ClientTickHandler;
import appeng.parts.automation.PlaneModel;
import appeng.tile.crafting.MolecularAssemblerRenderer;
import appeng.util.Platform; import appeng.util.Platform;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
@@ -53,7 +147,11 @@ import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.*; import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -240,6 +338,18 @@ public final class AppEngClient extends AppEngBase {
private void registerModelProviders() { private void registerModelProviders() {
ModelLoadingRegistry.INSTANCE.registerAppender((resourceManager, consumer) -> {
consumer.accept(MolecularAssemblerRenderer.LIGHTS_MODEL);
});
ModelLoadingRegistry.INSTANCE.registerVariantProvider((resourceManager) -> {
return (modelIdentifier, modelProviderContext) -> {
if (MolecularAssemblerRenderer.LIGHTS_MODEL.equals(modelIdentifier)) {
return modelProviderContext.loadModel(new Identifier(modelIdentifier.getNamespace(), modelIdentifier.getPath()));
}
return null;
};
});
ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> new CableBusModelLoader((PartModels) Api.INSTANCE.registries().partModels())); ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> new CableBusModelLoader((PartModels) Api.INSTANCE.registries().partModels()));
addBuiltInModel("block/quartz_glass", GlassModel::new); addBuiltInModel("block/quartz_glass", GlassModel::new);
@@ -249,14 +359,24 @@ public final class AppEngClient extends AppEngBase {
addBuiltInModel("item/memory_card", MemoryCardModel::new); addBuiltInModel("item/memory_card", MemoryCardModel::new);
addBuiltInModel("item/biometric_card", BiometricCardModel::new); addBuiltInModel("item/biometric_card", BiometricCardModel::new);
addBuiltInModel("block/drive", DriveModel::new); addBuiltInModel("block/drive", DriveModel::new);
addBuiltInModel("color_applicator", ColorApplicatorModel::new); // FIXME need to wire this up addBuiltInModel("color_applicator", ColorApplicatorModel::new); // FIXME need to wire this up (this might just not be needed)
addBuiltInModel("block/spatial_pylon", SpatialPylonModel::new); addBuiltInModel("block/spatial_pylon", SpatialPylonModel::new);
addBuiltInModel("block/paint", PaintSplotchesModel::new); addBuiltInModel("block/paint", PaintSplotchesModel::new);
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new); addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
// FIXME FABRIC addBuiltInModel("p2p_tunnel_frequency", P2PTunnelFrequencyModel::new); addBuiltInModel("part/p2p/p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
// FIXME FABRIC addBuiltInModel("facade", FacadeItemModel::new); addBuiltInModel("item/facade", FacadeItemModel::new);
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "part_plane"),
// FIXME FABRIC PlaneModelLoader.INSTANCE); addPlaneModel("part/annihilation_plane", "part/annihilation_plane");
addPlaneModel("part/annihilation_plane_on", "part/annihilation_plane_on");
addPlaneModel("part/identity_annihilation_plane", "part/identity_annihilation_plane");
addPlaneModel("part/identity_annihilation_plane_on", "part/identity_annihilation_plane_on");
addPlaneModel("part/fluid_annihilation_plane", "part/fluid_annihilation_plane");
addPlaneModel("part/fluid_annihilation_plane_on", "part/fluid_annihilation_plane_on");
addPlaneModel("part/fluid_formation_plane", "part/fluid_formation_plane");
addPlaneModel("part/fluid_formation_plane_on", "part/fluid_formation_plane_on");
addPlaneModel("part/formation_plane", "part/formation_plane");
addPlaneModel("part/formation_plane_on", "part/formation_plane_on");
addBuiltInModel("block/crafting/1k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_1K)); addBuiltInModel("block/crafting/1k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_1K));
addBuiltInModel("block/crafting/4k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_4K)); addBuiltInModel("block/crafting/4k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_4K));
addBuiltInModel("block/crafting/16k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_16K)); addBuiltInModel("block/crafting/16k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_16K));
@@ -267,9 +387,16 @@ public final class AppEngClient extends AppEngBase {
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "uvlightmap"), UVLModelLoader.INSTANCE); // FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "uvlightmap"), UVLModelLoader.INSTANCE);
} }
private static void addPlaneModel(String planeName, String frontTexture) {
Identifier frontTextureId = AppEng.makeId(frontTexture);
Identifier sidesTextureId = AppEng.makeId("part/plane_sides");
Identifier backTextureId = AppEng.makeId("part/transition_plane_back");
addBuiltInModel(planeName, () -> new PlaneModel(frontTextureId, sidesTextureId, backTextureId));
}
private static <T extends UnbakedModel> void addBuiltInModel(String id, Supplier<T> modelFactory) { private static <T extends UnbakedModel> void addBuiltInModel(String id, Supplier<T> modelFactory) {
ModelLoadingRegistry.INSTANCE.registerResourceProvider( ModelLoadingRegistry.INSTANCE.registerResourceProvider(
resourceManager -> new SimpleModelLoader<T>(AppEng.makeId(id), modelFactory) resourceManager -> new SimpleModelLoader<>(AppEng.makeId(id), modelFactory)
); );
} }
@@ -18,43 +18,9 @@
package appeng.client.gui; package appeng.client.gui;
import java.util.ArrayList; import alexiil.mc.lib.attributes.fluid.render.FluidRenderFace;
import java.util.Arrays; import alexiil.mc.lib.attributes.fluid.render.FluidVolumeRenderer;
import java.util.HashSet; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import appeng.mixins.SlotMixin;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.util.Formatting;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.widgets.CustomSlotWidget; import appeng.client.gui.widgets.CustomSlotWidget;
@@ -85,6 +51,41 @@ import appeng.core.sync.packets.SwapSlotsPacket;
import appeng.fluids.client.render.FluidStackSizeRenderer; import appeng.fluids.client.render.FluidStackSizeRenderer;
import appeng.fluids.container.slots.IMEFluidSlot; import appeng.fluids.container.slots.IMEFluidSlot;
import appeng.helpers.InventoryAction; import appeng.helpers.InventoryAction;
import appeng.mixins.SlotMixin;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScreen<T> { public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScreen<T> {
@@ -189,7 +190,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
} }
final Text msg = tooltip.getMessage(); final Text msg = tooltip.getMessage();
if (msg != null && !msg.isEmpty()) { if (msg != null && !msg.getString().isEmpty()) {
this.drawTooltip(matrices, x + 11, y + 4, msg); this.drawTooltip(matrices, x + 11, y + 4, msg);
} }
} }
@@ -328,7 +329,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
// TODO 1.9.4 aftermath - Whole SlotActionType thing, to be checked. // TODO 1.9.4 aftermath - Whole SlotActionType thing, to be checked.
@Override @Override
protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton, protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton,
final SlotActionType clickType) { final SlotActionType clickType) {
final PlayerEntity player = getPlayer(); final PlayerEntity player = getPlayer();
if (slot instanceof FakeSlot) { if (slot instanceof FakeSlot) {
@@ -510,7 +511,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
} }
protected int getSlotIndex(Slot slot) { protected int getSlotIndex(Slot slot) {
return ((SlotMixin)slot).getIndex(); return ((SlotMixin) slot).getIndex();
} }
protected boolean checkHotbarKeys(int keyCode, int scanCode) { protected boolean checkHotbarKeys(int keyCode, int scanCode) {
@@ -652,7 +653,16 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
final IAEFluidStack fs = slot.getAEFluidStack(); final IAEFluidStack fs = slot.getAEFluidStack();
if (fs != null && this.isPowered()) { if (fs != null && this.isPowered()) {
fs.getFluidStack().renderGuiRect(s.x, s.y, s.x + 16, s.y + 16); List<FluidRenderFace> faces = new ArrayList<>();
faces.add(FluidRenderFace.createFlatFaceZ(0, 0, 0, 16, 16, 0, 1 / 16., false, false));
matrices.push();
matrices.translate(s.x, s.y, 0);
FluidVolume fluidStack = fs.getFluidStack();
fluidStack.render(faces, FluidVolumeRenderer.VCPS, matrices);
RenderSystem.runAsFancy(FluidVolumeRenderer.VCPS::draw);
matrices.pop();
this.fluidStackSizeRenderer.renderStackSize(this.textRenderer, fs, s.x, s.y); this.fluidStackSizeRenderer.renderStackSize(this.textRenderer, fs, s.x, s.y);
} else if (!this.isPowered()) { } else if (!this.isPowered()) {
@@ -786,7 +796,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
public void tick() { public void tick() {
super.tick(); super.tick();
for (IGuiEventListener child : children) { for (Element child : children) {
if (child instanceof ITickingWidget) { if (child instanceof ITickingWidget) {
((ITickingWidget) child).tick(); ((ITickingWidget) child).tick();
} }
@@ -20,9 +20,7 @@ package appeng.client.gui.implementations;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@@ -57,7 +57,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
this::onLevelChange); this::onLevelChange);
this.level.setTextFieldBounds(25, 44, 75); this.level.setTextFieldBounds(25, 44, 75);
this.level.addButtons(children::add, this::addButton); this.level.addButtons(children::add, this::addButton);
container.setTextField(this.level); handler.setTextField(this.level);
} }
private void onLevelChange(long level) { private void onLevelChange(long level) {
@@ -100,7 +100,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
if (notCraftingMode) { if (notCraftingMode) {
if (currentLevelMode == LevelType.ENERGY_LEVEL) { if (currentLevelMode == LevelType.ENERGY_LEVEL) {
this.font.drawString(PowerUnits.AE.textComponent().getString(), 110, 44, COLOR_DARK_GRAY); this.textRenderer.draw(matrices, PowerUnits.AE.textComponent().getString(), 110, 44, COLOR_DARK_GRAY);
} }
} }
} }
@@ -3,15 +3,17 @@ package appeng.client.gui.implementations;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.LongConsumer; import java.util.function.LongConsumer;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.IGuiEventListener; import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.widget.ButtonWidget;
import appeng.client.gui.AEBaseScreen; import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.NumberEntryType; import appeng.client.gui.NumberEntryType;
import appeng.client.gui.widgets.ITickingWidget; import appeng.client.gui.widgets.ITickingWidget;
import appeng.client.gui.widgets.NumberBox; import appeng.client.gui.widgets.NumberBox;
import appeng.core.AEConfig; import appeng.core.AEConfig;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
/** /**
* A utility widget that consists of a text-field to enter a number with * A utility widget that consists of a text-field to enter a number with
@@ -26,14 +28,14 @@ public class NumberEntryWidget implements ITickingWidget {
private final NumberBox level; private final NumberBox level;
private final NumberEntryType type; private final NumberEntryType type;
private Button plus1; private ButtonWidget plus1;
private Button plus10; private ButtonWidget plus10;
private Button plus100; private ButtonWidget plus100;
private Button plus1000; private ButtonWidget plus1000;
private Button minus1; private ButtonWidget minus1;
private Button minus10; private ButtonWidget minus10;
private Button minus100; private ButtonWidget minus100;
private Button minus1000; private ButtonWidget minus1000;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type, public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
LongConsumer changeListener) { LongConsumer changeListener) {
@@ -42,20 +44,19 @@ public class NumberEntryWidget implements ITickingWidget {
this.y = y; this.y = y;
this.type = type; this.type = type;
FontRenderer font = parent.getMinecraft().fontRenderer; TextRenderer font = parent.getClient().textRenderer;
int inputX = parent.getGuiLeft() + x; int inputX = parent.getX() + x;
int inputY = parent.getGuiTop() + y; int inputY = parent.getY() + y;
this.level = new NumberBox(font, inputX, inputY, width, font.FONT_HEIGHT, type.getInputType(), changeListener); this.level = new NumberBox(font, inputX, inputY, width, font.fontHeight, type.getInputType(), changeListener);
this.level.setEnableBackgroundDrawing(false); this.level.setHasBorder(false);
this.level.setMaxStringLength(16); this.level.setMaxLength(16);
this.level.setTextColor(0xFFFFFF); this.level.setEditableColor(0xFFFFFF);
this.level.setVisible(true); this.level.setVisible(true);
this.level.setFocused2(true); parent.setInitialFocus(this.level);
parent.setFocusedDefault(this.level);
} }
public void setActive(boolean active) { public void setActive(boolean active) {
this.level.setEnabled(active); this.level.active = active;
this.plus1.active = active; this.plus1.active = active;
this.plus10.active = active; this.plus10.active = active;
this.plus100.active = active; this.plus100.active = active;
@@ -67,8 +68,8 @@ public class NumberEntryWidget implements ITickingWidget {
} }
public void setTextFieldBounds(int x, int y, int width) { public void setTextFieldBounds(int x, int y, int width) {
this.level.x = parent.getGuiLeft() + x; this.level.x = parent.getX() + x;
this.level.y = parent.getGuiTop() + y; this.level.y = parent.getY() + y;
this.level.setWidth(width); this.level.setWidth(width);
} }
@@ -76,28 +77,28 @@ public class NumberEntryWidget implements ITickingWidget {
this.level.setMinValue(minValue); this.level.setMinValue(minValue);
} }
public void addButtons(Consumer<IGuiEventListener> addChildren, Consumer<Button> addButton) { public void addButtons(Consumer<Element> addChildren, Consumer<ButtonWidget> addButton) {
final int[] steps = AEConfig.instance().getNumberEntrySteps(type); final int[] steps = AEConfig.instance().getNumberEntrySteps(type);
int a = steps[0]; int a = steps[0];
int b = steps[1]; int b = steps[1];
int c = steps[2]; int c = steps[2];
int d = steps[3]; int d = steps[3];
int left = parent.getGuiLeft() + x; int left = parent.getX() + x;
int top = parent.getGuiTop() + y; int top = parent.getY() + y;
addButton.accept(this.plus1 = new Button(left, top, 22, 20, "+" + a, btn -> addQty(a))); addButton.accept(this.plus1 = new ButtonWidget(left, top, 22, 20, new LiteralText("+" + a), btn -> addQty(a)));
addButton.accept(this.plus10 = new Button(left + 28, top, 28, 20, "+" + b, btn -> addQty(b))); addButton.accept(this.plus10 = new ButtonWidget(left + 28, top, 28, 20, new LiteralText("+" + b), btn -> addQty(b)));
addButton.accept(this.plus100 = new Button(left + 62, top, 32, 20, "+" + c, btn -> addQty(c))); addButton.accept(this.plus100 = new ButtonWidget(left + 62, top, 32, 20, new LiteralText("+" + c), btn -> addQty(c)));
addButton.accept(this.plus1000 = new Button(left + 100, top, 38, 20, "+" + d, btn -> addQty(d))); addButton.accept(this.plus1000 = new ButtonWidget(left + 100, top, 38, 20, new LiteralText("+" + d), btn -> addQty(d)));
// Placing this here will give a sensible tab order // Placing this here will give a sensible tab order
addChildren.accept(this.level); addChildren.accept(this.level);
addButton.accept(this.minus1 = new Button(left, top + 42, 22, 20, "-" + a, btn -> addQty(-a))); addButton.accept(this.minus1 = new ButtonWidget(left, top + 42, 22, 20, new LiteralText("-" + a), btn -> addQty(-a)));
addButton.accept(this.minus10 = new Button(left + 28, top + 42, 28, 20, "-" + b, btn -> addQty(-b))); addButton.accept(this.minus10 = new ButtonWidget(left + 28, top + 42, 28, 20, new LiteralText("-" + b), btn -> addQty(-b)));
addButton.accept(this.minus100 = new Button(left + 62, top + 42, 32, 20, "-" + c, btn -> addQty(-c))); addButton.accept(this.minus100 = new ButtonWidget(left + 62, top + 42, 32, 20, new LiteralText("-" + c), btn -> addQty(-c)));
addButton.accept(this.minus1000 = new Button(left + 100, top + 42, 38, 20, "-" + d, btn -> addQty(-d))); addButton.accept(this.minus1000 = new ButtonWidget(left + 100, top + 42, 38, 20, new LiteralText("-" + d), btn -> addQty(-d)));
} }
private void addQty(final long i) { private void addQty(final long i) {
@@ -106,8 +107,8 @@ public class NumberEntryWidget implements ITickingWidget {
this.level.setText(String.valueOf(Math.max(minValue, currentValue + i))); this.level.setText(String.valueOf(Math.max(minValue, currentValue + i)));
} }
public void render(int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
this.level.render(mouseX, mouseY, partialTicks); this.level.render(matrices, mouseX, mouseY, partialTicks);
} }
public void setValue(long value, boolean skipNotify) { public void setValue(long value, boolean skipNotify) {
@@ -49,7 +49,7 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY, this::onPriorityChange); this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY, this::onPriorityChange);
this.priority.setTextFieldBounds(62, 57, 50); this.priority.setTextFieldBounds(62, 57, 50);
this.priority.setMinValue(Integer.MIN_VALUE); this.priority.setMinValue(Integer.MIN_VALUE);
container.setTextField(this.priority); handler.setTextField(this.priority);
this.priority.addButtons(children::add, this::addButton); this.priority.addButtons(children::add, this::addButton);
this.subGui.addBackButton(this::addButton, 154, 0); this.subGui.addBackButton(this::addButton, 154, 0);
@@ -1,12 +1,13 @@
package appeng.client.gui.widgets; package appeng.client.gui.widgets;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
/** /**
* Indicates that a widget (anything that is in the {@link Screen#children()} * Indicates that a widget (anything that is in the {@link Screen#children()}
* list) should receive callbacks every tick. * list) should receive callbacks every tick.
*/ */
public interface ITickingWidget { public interface ITickingWidget extends Element {
void tick(); void tick();
@@ -38,7 +38,7 @@ public class NumberBox extends TextFieldWidget {
final Class<?> type, LongConsumer changeListener) { final Class<?> type, LongConsumer changeListener) {
super(fontRenderer, x, y, width, height, new LiteralText("0")); super(fontRenderer, x, y, width, height, new LiteralText("0"));
this.setText("0"); this.setText("0");
setResponder(this::onTextChanged); setChangedListener(this::onTextChanged);
this.lastValue = 0; this.lastValue = 0;
this.changeListener = changeListener; this.changeListener = changeListener;
if (type == int.class || type == Integer.class) { if (type == int.class || type == Integer.class) {
@@ -315,7 +315,7 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
return new LiteralText(name + '\n' + sb); return new LiteralText(name + '\n' + sb);
} }
return ""; return LiteralText.EMPTY;
} }
public String getFillVar() { public String getFillVar() {
@@ -93,7 +93,7 @@ public class ToggleButton extends ButtonWidget implements ITooltip {
return new LiteralText(name + '\n' + sb); return new LiteralText(name + '\n' + sb);
} }
return ""; return LiteralText.EMPTY;
} }
@Override @Override
@@ -18,35 +18,57 @@
package appeng.client.render; package appeng.client.render;
import java.util.List; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import java.util.Random; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections;
import com.google.common.collect.ImmutableList; import java.util.List;
import java.util.Random;
import net.minecraft.block.BlockState; import java.util.function.Supplier;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
/** /**
* @author DrummerMC * @author DrummerMC
* @version rv6 - 2018-01-22 * @version rv6 - 2018-01-22
* @since rv6 2018-01-22 * @since rv6 2018-01-22
*/ */
public class DummyFluidBakedModel implements BakedModel { public class DummyFluidBakedModel implements BakedModel, FabricBakedModel {
private final ImmutableList<BakedQuad> quads;
public DummyFluidBakedModel(ImmutableList<BakedQuad> quads) { private final FluidVolume volume;
this.quads = quads;
public DummyFluidBakedModel(FluidVolume volume) {
this.volume = volume;
} }
@Override @Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { public boolean isVanillaAdapter() {
return this.quads; return false;
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
// Not used as an item model
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
volume.renderGuiRect(0, 0, 16, 16);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return Collections.emptyList();
} }
@Override @Override
@@ -75,7 +97,13 @@ public class DummyFluidBakedModel implements BakedModel {
} }
@Override @Override
public ModelOverrideList getOverrides() { public ModelTransformation getTransformation() {
return null; return null;
} }
@Override
public ModelOverrideList getOverrides() {
return ModelOverrideList.EMPTY;
}
} }
@@ -24,18 +24,14 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.EmptyModelData;
import appeng.client.render.cablebus.FacadeBuilder; import appeng.client.render.cablebus.FacadeBuilder;
@@ -18,58 +18,58 @@
package appeng.client.render; package appeng.client.render;
import java.util.Objects;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import appeng.client.render.cablebus.FacadeBuilder; import appeng.client.render.cablebus.FacadeBuilder;
import appeng.items.parts.FacadeItem; import appeng.items.parts.FacadeItem;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import java.util.Objects;
import java.util.Random;
import java.util.function.Supplier;
/** /**
* This baked model class is used as a dispatcher to redirect the renderer to * This baked model class is used as a dispatcher to redirect the renderer to
* the *real* model that should be used based on the item stack. A custom Item * the *real* model that should be used based on the item stack. A custom Item
* Override List is used to accomplish this. * Override List is used to accomplish this.
*/ */
public class FacadeDispatcherBakedModel extends DelegateBakedModel { public class FacadeDispatcherBakedModel extends ForwardingBakedModel {
private final FacadeBuilder facadeBuilder; private final FacadeBuilder facadeBuilder;
private final Int2ObjectMap<FacadeBakedItemModel> cache = new Int2ObjectArrayMap<>(); private final Int2ObjectMap<FacadeBakedItemModel> cache = new Int2ObjectArrayMap<>();
public FacadeDispatcherBakedModel(BakedModel baseModel, FacadeBuilder facadeBuilder) { public FacadeDispatcherBakedModel(BakedModel baseModel, FacadeBuilder facadeBuilder) {
super(baseModel); this.wrapped = baseModel;
this.facadeBuilder = facadeBuilder; this.facadeBuilder = facadeBuilder;
} }
@Override @Override
public ModelOverrideList getOverrides() { public boolean isVanillaAdapter() {
return new ModelOverrideList() { return false;
@Override }
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
if (!(stack.getItem() instanceof FacadeItem)) {
return originalModel;
}
FacadeItem itemFacade = (FacadeItem) stack.getItem(); @Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
if (!(stack.getItem() instanceof FacadeItem)) {
return;
}
ItemStack textureItem = itemFacade.getTextureItem(stack); FacadeItem itemFacade = (FacadeItem) stack.getItem();
int hash = Objects.hash(textureItem.getItem().getRegistryName(), textureItem.getTag()); ItemStack textureItem = itemFacade.getTextureItem(stack);
FacadeBakedItemModel model = FacadeDispatcherBakedModel.this.cache.get(hash);
if (model == null) {
model = new FacadeBakedItemModel(FacadeDispatcherBakedModel.this.getBaseModel(), textureItem,
FacadeDispatcherBakedModel.this.facadeBuilder);
FacadeDispatcherBakedModel.this.cache.put(hash, model);
}
return model; int itemId = Item.getRawId(textureItem.getItem());
} int hash = Objects.hash(itemId, textureItem.getTag());
}; FacadeBakedItemModel model = FacadeDispatcherBakedModel.this.cache.get(hash);
if (model == null) {
model = new FacadeBakedItemModel(FacadeDispatcherBakedModel.this.wrapped, textureItem,
FacadeDispatcherBakedModel.this.facadeBuilder);
FacadeDispatcherBakedModel.this.cache.put(hash, model);
}
context.fallbackConsumer().accept(model);
} }
} }
@@ -18,22 +18,19 @@
package appeng.client.render; package appeng.client.render;
import java.util.Collection; import appeng.client.render.cablebus.FacadeBuilder;
import java.util.Set; import appeng.core.AppEng;
import java.util.function.Function; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import com.mojang.datafixers.util.Pair; import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.client.render.cablebus.FacadeBuilder; import javax.annotation.Nullable;
import appeng.core.AppEng; import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
/** /**
* The model class for facades. Since facades wrap existing models, they don't * The model class for facades. Since facades wrap existing models, they don't
@@ -44,20 +41,17 @@ public class FacadeItemModel implements BasicUnbakedModel {
// We use this to get the default item transforms and make our lives easier // We use this to get the default item transforms and make our lives easier
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/facade_base"); private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/facade_base");
@Nullable
@Override @Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery, public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform, BakedModel bakedBaseModel = loader.bake(MODEL_BASE, rotationContainer);
ModelOverrideList overrides, Identifier modelLocation) { FacadeBuilder facadeBuilder = new FacadeBuilder(loader);
BakedModel bakedBaseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder();
return new FacadeDispatcherBakedModel(bakedBaseModel, facadeBuilder); return new FacadeDispatcherBakedModel(bakedBaseModel, facadeBuilder);
} }
@Override @Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner, public Collection<Identifier> getModelDependencies() {
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) { return Collections.singleton(MODEL_BASE);
return modelGetter.apply(MODEL_BASE).getTextures(modelGetter, missingTextureErrors);
} }
} }
@@ -18,6 +18,7 @@
package appeng.client.render.cablebus; package appeng.client.render.cablebus;
import appeng.api.parts.IDynamicPartBakedModel;
import appeng.api.parts.IPartModel; import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
import appeng.api.util.AEColor; import appeng.api.util.AEColor;
@@ -25,17 +26,13 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess; import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelOverrideList;
@@ -49,8 +46,14 @@ import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Random;
import java.util.function.Supplier; import java.util.function.Supplier;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
@@ -125,7 +128,11 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
} }
context.pushTransform(QuadRotator.get(facing, Direction.UP)); context.pushTransform(QuadRotator.get(facing, Direction.UP));
if (bakedModel instanceof FabricBakedModel) { if (bakedModel instanceof IDynamicPartBakedModel) {
((IDynamicPartBakedModel) bakedModel).emitQuads(blockView, state, pos, randomSupplier, context,
facing, partModelData);
}
else if (bakedModel instanceof FabricBakedModel) {
((FabricBakedModel) bakedModel).emitBlockQuads(blockView, state, pos, randomSupplier, context); ((FabricBakedModel) bakedModel).emitBlockQuads(blockView, state, pos, randomSupplier, context);
} else { } else {
context.fallbackConsumer().accept(bakedModel); context.fallbackConsumer().accept(bakedModel);
@@ -134,7 +141,8 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
} }
} }
// FIXME this.facadeBuilder.buildFacadeQuads(layer, renderState, randomSupplier, context, this.partModels::get); Mesh mesh = this.facadeBuilder.getFacadeMesh(renderState, randomSupplier, this.partModels::get);
context.meshConsumer().accept(mesh);
} }
// Determines whether a cable is connected to exactly two sides that are // Determines whether a cable is connected to exactly two sides that are
@@ -67,7 +67,7 @@ public class CableBusModel implements BasicUnbakedModel {
Map<Identifier, BakedModel> partModels = this.loadPartModels(loader, rotationContainer); Map<Identifier, BakedModel> partModels = this.loadPartModels(loader, rotationContainer);
CableBuilder cableBuilder = new CableBuilder(textureGetter); CableBuilder cableBuilder = new CableBuilder(textureGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder(); FacadeBuilder facadeBuilder = new FacadeBuilder(loader);
// This should normally not be used, but we *have* to provide a particle texture // This should normally not be used, but we *have* to provide a particle texture
// or otherwise damage models will // or otherwise damage models will
@@ -26,8 +26,8 @@ import net.minecraft.fluid.FluidState;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockRenderView;
import net.minecraft.world.chunk.light.LightingProvider;
import net.minecraft.world.level.ColorResolver; import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.lighting.WorldLightManager;
/** /**
* This is used to retrieve the ExtendedState of a block for facade rendering. * This is used to retrieve the ExtendedState of a block for facade rendering.
@@ -69,12 +69,17 @@ public class FacadeBlockAccess implements BlockRenderView {
} }
@Override @Override
public WorldLightManager getLightingProvider() { public LightingProvider getLightingProvider() {
return world.getLightingProvider(); return world.getLightingProvider();
} }
@Override @Override
public int getBlockColor(BlockPos blockPosIn, ColorResolver colorResolverIn) { public float getBrightness(Direction direction, boolean shaded) {
return world.getBlockColor(blockPosIn, colorResolverIn); return world.getBrightness(direction, shaded);
}
@Override
public int getColor(BlockPos pos, ColorResolver colorResolver) {
return world.getColor(pos, colorResolver);
} }
} }
@@ -18,8 +18,42 @@
package appeng.client.render.cablebus; package appeng.client.render.cablebus;
import appeng.api.util.AEAxisAlignedBB;
import appeng.core.Api;
import appeng.parts.misc.CableAnchorPart;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadClamper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadCornerKicker;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStripper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -28,31 +62,6 @@ import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import appeng.api.util.AEAxisAlignedBB;
import appeng.core.Api;
import appeng.parts.misc.CableAnchorPart;
/** /**
* The FacadeBuilder builds for facades.. * The FacadeBuilder builds for facades..
* *
@@ -60,43 +69,93 @@ import appeng.parts.misc.CableAnchorPart;
*/ */
public class FacadeBuilder { public class FacadeBuilder {
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
public static final double THICK_THICKNESS = 2D / 16D; public static final double THICK_THICKNESS = 2D / 16D;
public static final double THIN_THICKNESS = 1D / 16D; public static final double THIN_THICKNESS = 1D / 16D;
public static final Box[] THICK_FACADE_BOXES = new Box[] { public static final Box[] THICK_FACADE_BOXES = new Box[]{
new Box(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0), new Box(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0),
new Box(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0), new Box(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS), new Box(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS),
new Box(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0), new Box(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0), new Box(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0),
new Box(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) }; new Box(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)};
public static final Box[] THIN_FACADE_BOXES = new Box[] { public static final Box[] THIN_FACADE_BOXES = new Box[]{
new Box(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0), new Box(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0),
new Box(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0), new Box(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS), new Box(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS),
new Box(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0), new Box(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0), new Box(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
new Box(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) }; new Box(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)};
//FIXME private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder() private final Map<Direction, Mesh> cableAnchorStilts;
//FIXME // Clamper is responsible for clamping the vertex to the bounds specified.
//FIXME .addElement("clamper", QuadClamper.FACTORY)
//FIXME // Strips faces if they match a mask.
//FIXME .addElement("face_stripper", QuadFaceStripper.FACTORY)
//FIXME // Kicks the edge inner corners in, solves Z fighting
//FIXME .addElement("corner_kicker", QuadCornerKicker.FACTORY)
//FIXME // Re-Interpolates the UV's for the quad.
//FIXME .addElement("interp", QuadReInterpolator.FACTORY)
//FIXME // Tints the quad if we need it to. Disabled by default.
//FIXME .addElement("tinter", QuadTinter.FACTORY, false)
//FIXME // Overrides the quad's alpha if we are forcing transparent facades.
//FIXME .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
//FIXME );
//FIXME private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
public void buildFacadeQuads(RenderLayer layer, CableBusRenderState renderState, Supplier<Random> rand, public FacadeBuilder(ModelLoader modelLoader) {
RenderContext context, Function<Identifier, BakedModel> modelLookup) { cableAnchorStilts = buildCableAnchorStems(modelLoader);
}
/**
* Build a map of pre-rotated cable anchor stilts, which are the shortened cable anchors that
* will still be visible for facades attached to a cable.
*/
private Map<Direction, Mesh> buildCableAnchorStems(ModelLoader modelLoader) {
Map<Direction, Mesh> stems = new EnumMap<>(Direction.class);
List<BakedModel> cableAnchorParts = new ArrayList<>();
for (Identifier model : CableAnchorPart.FACADE_MODELS.getModels()) {
BakedModel cableAnchor = modelLoader.bake(model, ModelRotation.X0_Y0);
cableAnchorParts.add(cableAnchor);
}
// Create pre-rotated variants of the cable anchor stems
for (Direction side : Direction.values()) {
RenderContext.QuadTransform rotator = QuadRotator.get(side, Direction.UP);
MeshBuilder meshBuilder = renderer.meshBuilder();
QuadEmitter emitter = meshBuilder.getEmitter();
for (BakedModel model : cableAnchorParts) {
for (int cullFaceIdx = 0; cullFaceIdx <= ModelHelper.NULL_FACE_ID; cullFaceIdx++) {
Direction cullFace = ModelHelper.faceFromIndex(cullFaceIdx);
List<BakedQuad> quads = model.getQuads(null, cullFace, new Random());
for (BakedQuad quad : quads) {
emitter.fromVanilla(quad.getVertexData(), 0, false);
emitter.cullFace(cullFace);
emitter.nominalFace(quad.getFace());
if (!rotator.transform(emitter)) {
continue;
}
emitter.emit();
}
}
}
stems.put(side, meshBuilder.build());
}
return stems;
}
// private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
// // Clamper is responsible for clamping the vertex to the bounds specified.
// .addElement("clamper", QuadClamper.FACTORY)
// // Strips faces if they match a mask.
// .addElement("face_stripper", QuadFaceStripper.FACTORY)
// // Kicks the edge inner corners in, solves Z fighting
// .addElement("corner_kicker", QuadCornerKicker.FACTORY)
// // Re-Interpolates the UV's for the quad.
// .addElement("interp", QuadReInterpolator.FACTORY)
// // Tints the quad if we need it to. Disabled by default.
// .addElement("tinter", QuadTinter.FACTORY, false)
// // Overrides the quad's alpha if we are forcing transparent facades.
// .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
// );
public Mesh getFacadeMesh(CableBusRenderState renderState,
Supplier<Random> rand,
Function<Identifier, BakedModel> modelLookup) {
//FIXME BakedPipeline pipeline = this.pipelines.get(); //FIXME BakedPipeline pipeline = this.pipelines.get();
//FIXME Quad collectorQuad = this.collectors.get(); //FIXME Quad collectorQuad = this.collectors.get();
boolean transparent = Api.instance().partHelper().getCableRenderMode().transparentFacades; boolean transparent = Api.instance().partHelper().getCableRenderMode().transparentFacades;
@@ -108,32 +167,29 @@ public class FacadeBuilder {
BlockColors blockColors = MinecraftClient.getInstance().getBlockColors(); BlockColors blockColors = MinecraftClient.getInstance().getBlockColors();
boolean thinFacades = isUseThinFacades(partBoxes); boolean thinFacades = isUseThinFacades(partBoxes);
MeshBuilder meshBuilder = renderer.meshBuilder();
QuadEmitter emitter = meshBuilder.getEmitter();
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) { for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
Direction side = entry.getKey(); Direction side = entry.getKey();
int sideIndex = side.ordinal(); int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue(); FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains(side); boolean renderStilt = !sidesWithParts.contains(side);
if (layer == RenderLayer.getCutout() && renderStilt) { if (renderStilt) {
context.pushTransform(QuadRotator.get(side, Direction.UP)); cableAnchorStilts.get(entry.getKey()).forEach(quad -> {
for (Identifier part : CableAnchorPart.FACADE_MODELS.getModels()) { quad.copyTo(emitter);
BakedModel partModel = modelLookup.apply(part); emitter.emit();
context.fallbackConsumer().accept(partModel); });
}
context.popTransform();
}
// If we are forcing transparency and this isn't the Translucent layer.
if (transparent && layer != RenderLayer.getTranslucent()) {
continue;
} }
BlockState blockState = facadeRenderState.getSourceBlock(); BlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render. // If we aren't forcing transparency let the block decide if it should render.
if (!transparent && layer != null) { // FIXME FABRIC if (!transparent && layer != null) {
// FIXME FABRIC only one layer per block // FIXME FABRIC only one layer per block
// FIXME FABRIC if (!RenderLayers.canRenderInLayer(blockState, layer)) { // FIXME FABRIC if (!RenderLayers.canRenderInLayer(blockState, layer)) {
// FIXME FABRIC continue; // FIXME FABRIC continue;
// FIXME FABRIC } // FIXME FABRIC }
} // FIXME FABRIC }
Box fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex]; Box fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
Box facadeBox = fullBounds; Box facadeBox = fullBounds;
@@ -179,97 +235,114 @@ public class FacadeBuilder {
} }
} }
// calculate the side mask.
int facadeMask = 0;
for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
Direction s = ent.getKey();
if (s.getAxis() != side.getAxis()) {
FacadeRenderState otherState = ent.getValue();
if (!otherState.isTransparent()) {
facadeMask |= 1 << s.ordinal();
}
}
}
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes); AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
List<Box> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis()); List<Box> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
// FIXME BlockRenderView facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState); BlockRenderView facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
// FIXME FABRIC BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager(); BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
// FIXME FABRIC BakedModel model = dispatcher.getModel(blockState); BakedModel model = dispatcher.getModel(blockState);
// FIXME FABRIC IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
// FIXME FABRIC QuadFaceStripper faceStripper = new QuadFaceStripper(fullBounds, facadeMask);
// FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>(); // Setup the kicker.
// FIXME FABRIC // If we are forcing transparent facades, fake the render layer, and grab all QuadCornerKicker kicker = new QuadCornerKicker();
// FIXME FABRIC // quads. kicker.setSide(sideIndex);
// FIXME FABRIC if (transparent || layer == null) { kicker.setFacadeMask(facadeMask);
// FIXME FABRIC for (RenderLayer forcedLayer : RenderLayer.getBlockRenderTypes()) { kicker.setBox(fullBounds);
// FIXME FABRIC // Check if the block renders on the layer we want to force. kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
// FIXME FABRIC if (RenderLayers.canRenderInLayer(blockState, forcedLayer)) {
// FIXME FABRIC // Force the layer and gather quads. QuadReInterpolator interpolator = new QuadReInterpolator();
// FIXME FABRIC ForgeHooksClient.setRenderLayer(forcedLayer);
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData)); for (int cullFaceIdx = 0; cullFaceIdx <= ModelHelper.NULL_FACE_ID; cullFaceIdx++) {
// FIXME FABRIC } Direction cullFace = ModelHelper.faceFromIndex(cullFaceIdx);
// FIXME FABRIC } List<BakedQuad> quads = model.getQuads(blockState, cullFace, rand.get());
// FIXME FABRIC
// FIXME FABRIC // Reset. for (BakedQuad quad : quads) {
// FIXME FABRIC ForgeHooksClient.setRenderLayer(layer); QuadTinter quadTinter = null;
// FIXME FABRIC } else {
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData)); // Prebake the color tint into the quad
// FIXME FABRIC } if (quad.getColorIndex() != -1) {
// FIXME FABRIC quadTinter = new QuadTinter(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
// FIXME FABRIC // No quads.. Cool, next! }
// FIXME FABRIC if (modelQuads.isEmpty()) {
// FIXME FABRIC continue; for (Box box : holeStrips) {
// FIXME FABRIC } emitter.fromVanilla(quad.getVertexData(), 0, false);
// FIXME FABRIC emitter.cullFace(cullFace);
// FIXME FABRIC // Grab out pipeline elements. emitter.nominalFace(quad.getFace());
// FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class); interpolator.setInputQuad(emitter);
// FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
// FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class); QuadClamper clamper = new QuadClamper(box);
// FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class); if (!clamper.transform(emitter)) {
// FIXME FABRIC continue;
// FIXME FABRIC // Set global element states. }
// FIXME FABRIC
// FIXME FABRIC // calculate the side mask. // Strips faces if they match a mask.
// FIXME FABRIC int facadeMask = 0; if (!faceStripper.transform(emitter)) {
// FIXME FABRIC for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) { continue;
// FIXME FABRIC Direction s = ent.getKey(); }
// FIXME FABRIC if (s.getAxis() != side.getAxis()) {
// FIXME FABRIC FacadeRenderState otherState = ent.getValue(); // Kicks the edge inner corners in, solves Z fighting
// FIXME FABRIC if (!otherState.isTransparent()) { if (!kicker.transform(emitter)) {
// FIXME FABRIC facadeMask |= 1 << s.ordinal(); continue;
// FIXME FABRIC } }
// FIXME FABRIC }
// FIXME FABRIC } interpolator.transform(emitter);
// FIXME FABRIC // Setup the edge stripper.
// FIXME FABRIC edgeStripper.setBounds(fullBounds); // Tints the quad if we need it to. Disabled by default.
// FIXME FABRIC edgeStripper.setMask(facadeMask); if (quadTinter != null) {
// FIXME FABRIC quadTinter.transform(emitter);
// FIXME FABRIC // Setup the kicker. }
// FIXME FABRIC kicker.setSide(sideIndex);
// FIXME FABRIC kicker.setFacadeMask(facadeMask); // // Overrides the quad's alpha if we are forcing transparent facades.
// FIXME FABRIC kicker.setBox(fullBounds); // .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
// FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
// FIXME FABRIC emitter.emit();
// FIXME FABRIC for (BakedQuad quad : modelQuads) { }
// FIXME FABRIC // lookup the format in CachedFormat. }
// FIXME FABRIC CachedFormat format = CachedFormat.lookup(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL); }
// FIXME FABRIC // If this quad has a tint index, setup the tinter.
// FIXME FABRIC if (quad.hasTintIndex()) { // FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>();
// FIXME FABRIC tinter.setTint(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex())); // FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand));
// FIXME FABRIC }
// FIXME FABRIC for (Box box : holeStrips) { // FIXME FABRIC // No quads.. Cool, next!
// FIXME FABRIC // setup the clamper for this box // FIXME FABRIC if (modelQuads.isEmpty()) {
// FIXME FABRIC clamper.setClampBounds(box); // FIXME FABRIC continue;
// FIXME FABRIC // Reset the pipeline, clears all enabled/disabled states. // FIXME FABRIC }
// FIXME FABRIC pipeline.reset(format); // FIXME FABRIC
// FIXME FABRIC // Reset out collector. // FIXME FABRIC // Grab out pipeline elements.
// FIXME FABRIC collectorQuad.reset(format); // FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
// FIXME FABRIC // Enable / disable the optional elements // FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
// FIXME FABRIC pipeline.setElementState("tinter", quad.hasTintIndex()); // FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
// FIXME FABRIC pipeline.setElementState("transparent", transparent); // FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
// FIXME FABRIC // Prepare the pipeline for a quad. // FIXME FABRIC
// FIXME FABRIC pipeline.prepare(collectorQuad); // FIXME FABRIC // Set global element states.
// FIXME FABRIC // FIXME FABRIC
// FIXME FABRIC // Pipe our quad into the pipeline. // FIXME FABRIC // Setup the kicker.
// FIXME FABRIC quad.pipe(pipeline); // FIXME FABRIC kicker.setSide(sideIndex);
// FIXME FABRIC // Check if the collector got any data. // FIXME FABRIC kicker.setFacadeMask(facadeMask);
// FIXME FABRIC if (collectorQuad.full) { // FIXME FABRIC kicker.setBox(fullBounds);
// FIXME FABRIC // Add the result. // FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
// FIXME FABRIC quads.add(collectorQuad.bake()); // FIXME FABRIC
// FIXME FABRIC } // FIXME FABRIC for (BakedQuad quad : modelQuads) {
// FIXME FABRIC } // FIXME FABRIC // lookup the format in CachedFormat.
// FIXME FABRIC } // FIXME FABRIC CachedFormat format = CachedFormat.lookup(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL);
// FIXME FABRIC }
} }
return meshBuilder.build();
} }
/** /**
@@ -362,7 +435,6 @@ public class FacadeBuilder {
* @param fb The Facade's box. * @param fb The Facade's box.
* @param hole The hole to 'cut'. * @param hole The hole to 'cut'.
* @param axis The axis the facade is on. * @param axis The axis the facade is on.
*
* @return The box segments. * @return The box segments.
*/ */
private static List<Box> getBoxes(Box fb, AEAxisAlignedBB hole, Axis axis) { private static List<Box> getBoxes(Box fb, AEAxisAlignedBB hole, Axis axis) {
@@ -1,50 +1,68 @@
package appeng.client.render.cablebus; package appeng.client.render.cablebus;
import java.util.Collections; import appeng.api.parts.IDynamicPartBakedModel;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import appeng.api.util.AEColor; import appeng.api.util.AEColor;
import appeng.util.Platform; import appeng.util.Platform;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
public class P2PTunnelFrequencyBakedModel implements FabricBakedModel { import javax.annotation.Nullable;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
public class P2PTunnelFrequencyBakedModel implements IDynamicPartBakedModel {
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
private final Sprite texture; private final Sprite texture;
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize(100).build(); private final static Cache<Long, Mesh> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
private static final int[][] QUAD_OFFSETS = new int[][] { { 4, 10, 2 }, { 10, 10, 2 }, { 4, 4, 2 }, { 10, 4, 2 } }; private static final int[][] QUAD_OFFSETS = new int[][]{{4, 10, 2}, {10, 10, 2}, {4, 4, 2}, {10, 4, 2}};
public P2PTunnelFrequencyBakedModel(final Sprite texture) { public P2PTunnelFrequencyBakedModel(final Sprite texture) {
this.texture = texture; this.texture = texture;
} }
@Override @Override
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData modelData) { public void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context,
if (side != null || !(modelData instanceof P2PTunnelFrequencyModelData)) { Direction partSide, @Nullable Object modelData) {
return Collections.emptyList(); if (!(modelData instanceof Long)) {
return;
} }
long frequency = (long) modelData;
P2PTunnelFrequencyModelData freqModelData = (P2PTunnelFrequencyModelData) modelData; Mesh frequencyMesh = getFrequencyModel(frequency);
if (frequencyMesh != null) {
return this.getPartQuads(freqModelData.getFrequency()); context.meshConsumer().accept(frequencyMesh);
}
} }
private List<BakedQuad> getQuadsForFrequency(final short frequency, final boolean active) { @Override
public ModelTransformation getTransformation() {
return ModelTransformation.NONE;
}
private Mesh createFrequencyMesh(final short frequency, final boolean active) {
MeshBuilder meshBuilder = renderer.meshBuilder();
final AEColor[] colors = Platform.p2p().toColors(frequency); final AEColor[] colors = Platform.p2p().toColors(frequency);
final CubeBuilder cb = new CubeBuilder(); final CubeBuilder cb = new CubeBuilder(meshBuilder.getEmitter());
cb.setTexture(this.texture); cb.setTexture(this.texture);
cb.useStandardUV(); cb.useStandardUV();
@@ -53,11 +71,10 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
final int[] offs = QUAD_OFFSETS[i]; final int[] offs = QUAD_OFFSETS[i];
for (int j = 0; j < 4; ++j) { for (int j = 0; j < 4; ++j) {
final AEColor c = colors[j]; final float[] cv = colors[j].dye.getColorComponents();
if (active) { if (active) {
cb.setColorRGB(c.dye.getColorValue()); cb.setColorRGB(cv[0], cv[1], cv[2]);
} else { } else {
final float[] cv = c.dye.getColorComponentValues();
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f); cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
} }
@@ -69,18 +86,19 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
} }
} }
return cb.getOutput();
return meshBuilder.build();
} }
private List<BakedQuad> getPartQuads(long partFlags) { private Mesh getFrequencyModel(long partFlags) {
try { try {
return modelCache.get(partFlags, () -> { return modelCache.get(partFlags, () -> {
short frequency = (short) (partFlags & 0xffffL); short frequency = (short) (partFlags & 0xffffL);
boolean active = (partFlags & 0x10000L) != 0; boolean active = (partFlags & 0x10000L) != 0;
return this.getQuadsForFrequency(frequency, active); return this.createFrequencyMesh(frequency, active);
}); });
} catch (ExecutionException e) { } catch (ExecutionException e) {
return Collections.emptyList(); return null;
} }
} }
@@ -96,7 +114,7 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
@Override @Override
public boolean isSideLit() { public boolean isSideLit() {
return false;// TODO return false;
} }
@Override @Override
@@ -0,0 +1,34 @@
package appeng.client.render.cablebus;
import appeng.client.render.BasicUnbakedModel;
import appeng.core.AppEng;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import javax.annotation.Nullable;
import java.util.function.Function;
import java.util.stream.Stream;
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "part/p2p_tunnel_frequency"));
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
final Sprite texture = textureGetter.apply(TEXTURE);
return new P2PTunnelFrequencyBakedModel(texture);
}
@Override
public Stream<SpriteIdentifier> getAdditionalTextures() {
return Stream.of(TEXTURE);
}
}
@@ -81,7 +81,7 @@ public class CraftingCPUContainer extends AEBaseContainer
} }
if (te instanceof CraftingBlockEntity) { if (te instanceof CraftingBlockEntity) {
this.setCPU(((CraftingTileEntity) te).getCluster()); this.setCPU(((CraftingBlockEntity) te).getCluster());
} }
if (this.getNetwork() == null && Platform.isServer()) { if (this.getNetwork() == null && Platform.isServer()) {
+262 -12
View File
@@ -1,8 +1,14 @@
package appeng.core; package appeng.core;
import appeng.core.Api; import appeng.api.config.Upgrades;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IItems;
import appeng.api.definitions.IParts;
import appeng.api.features.AEFeature; import appeng.api.features.AEFeature;
import appeng.api.features.IRegistryContainer; import appeng.api.features.IRegistryContainer;
import appeng.api.features.IWirelessTermHandler;
import appeng.api.features.IWorldGen;
import appeng.api.movable.IMovableRegistry;
import appeng.api.networking.IGridCacheRegistry; import appeng.api.networking.IGridCacheRegistry;
import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
@@ -17,28 +23,82 @@ import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.client.render.effects.ParticleTypes; import appeng.client.render.effects.ParticleTypes;
import appeng.container.AEBaseContainer; import appeng.container.AEBaseContainer;
import appeng.container.ContainerOpener; import appeng.container.ContainerOpener;
import appeng.container.implementations.*; import appeng.container.implementations.CellWorkbenchContainer;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.CondenserContainer;
import appeng.container.implementations.CraftAmountContainer;
import appeng.container.implementations.CraftConfirmContainer;
import appeng.container.implementations.CraftingCPUContainer;
import appeng.container.implementations.CraftingStatusContainer;
import appeng.container.implementations.CraftingTermContainer;
import appeng.container.implementations.DriveContainer;
import appeng.container.implementations.FormationPlaneContainer;
import appeng.container.implementations.GrinderContainer;
import appeng.container.implementations.IOPortContainer;
import appeng.container.implementations.InscriberContainer;
import appeng.container.implementations.InterfaceContainer;
import appeng.container.implementations.InterfaceTerminalContainer;
import appeng.container.implementations.LevelEmitterContainer;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.container.implementations.MEPortableCellContainer;
import appeng.container.implementations.MolecularAssemblerContainer;
import appeng.container.implementations.NetworkStatusContainer;
import appeng.container.implementations.NetworkToolContainer;
import appeng.container.implementations.PatternTermContainer;
import appeng.container.implementations.PriorityContainer;
import appeng.container.implementations.QNBContainer;
import appeng.container.implementations.QuartzKnifeContainer;
import appeng.container.implementations.SecurityStationContainer;
import appeng.container.implementations.SkyChestContainer;
import appeng.container.implementations.SpatialIOPortContainer;
import appeng.container.implementations.StorageBusContainer;
import appeng.container.implementations.UpgradeableContainer;
import appeng.container.implementations.VibrationChamberContainer;
import appeng.container.implementations.WirelessContainer;
import appeng.container.implementations.WirelessTermContainer;
import appeng.core.features.registries.P2PTunnelRegistry;
import appeng.core.features.registries.cell.BasicCellHandler; import appeng.core.features.registries.cell.BasicCellHandler;
import appeng.core.features.registries.cell.BasicItemCellGuiHandler; import appeng.core.features.registries.cell.BasicItemCellGuiHandler;
import appeng.core.features.registries.cell.CreativeCellHandler; import appeng.core.features.registries.cell.CreativeCellHandler;
import appeng.core.localization.GuiText;
import appeng.core.stats.AdvancementTriggers; import appeng.core.stats.AdvancementTriggers;
import appeng.core.stats.AeStats; import appeng.core.stats.AeStats;
import appeng.core.sync.BasePacket; import appeng.core.sync.BasePacket;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.network.TargetPoint; import appeng.core.sync.network.TargetPoint;
import appeng.fluids.container.*; import appeng.fluids.container.FluidFormationPlaneContainer;
import appeng.fluids.container.FluidIOContainer;
import appeng.fluids.container.FluidInterfaceContainer;
import appeng.fluids.container.FluidLevelEmitterContainer;
import appeng.fluids.container.FluidStorageBusContainer;
import appeng.fluids.container.FluidTerminalContainer;
import appeng.fluids.registries.BasicFluidCellGuiHandler; import appeng.fluids.registries.BasicFluidCellGuiHandler;
import appeng.forge.data.AE2DataGenerators; import appeng.forge.data.AE2DataGenerators;
import appeng.hooks.ToolItemHook;
import appeng.items.tools.NetworkToolItem;
import appeng.me.cache.*;
import appeng.mixins.CriteriaRegisterMixin;
import appeng.hooks.RegisterDimensionTypeCallback; import appeng.hooks.RegisterDimensionTypeCallback;
import appeng.recipes.handlers.*; import appeng.hooks.ToolItemHook;
import appeng.items.parts.FacadeItem;
import appeng.items.tools.NetworkToolItem;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cache.EnergyGridCache;
import appeng.me.cache.GridStorageCache;
import appeng.me.cache.P2PCache;
import appeng.me.cache.PathGridCache;
import appeng.me.cache.SecurityCache;
import appeng.me.cache.SpatialPylonCache;
import appeng.me.cache.TickManagerCache;
import appeng.mixins.CriteriaRegisterMixin;
import appeng.recipes.game.DisassembleRecipe;
import appeng.recipes.game.FacadeRecipe;
import appeng.recipes.handlers.GrinderRecipe;
import appeng.recipes.handlers.GrinderRecipeSerializer;
import appeng.recipes.handlers.InscriberRecipe;
import appeng.recipes.handlers.InscriberRecipeSerializer;
import appeng.recipes.handlers.QuartzKnifeRecipeSerializer;
import appeng.server.AECommand; import appeng.server.AECommand;
import appeng.spatial.SpatialDimensionManager; import appeng.spatial.SpatialDimensionManager;
import appeng.spatial.StorageCellBiome; import appeng.spatial.StorageCellBiome;
import appeng.spatial.StorageChunkGenerator; import appeng.spatial.StorageChunkGenerator;
import appeng.tile.AEBaseBlockEntity;
import appeng.worldgen.ChargedQuartzOreConfig; import appeng.worldgen.ChargedQuartzOreConfig;
import appeng.worldgen.ChargedQuartzOreFeature; import appeng.worldgen.ChargedQuartzOreFeature;
import appeng.worldgen.meteorite.MeteoriteStructure; import appeng.worldgen.meteorite.MeteoriteStructure;
@@ -47,6 +107,25 @@ import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState; 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.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -55,6 +134,7 @@ import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeType; import net.minecraft.recipe.RecipeType;
import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.tag.BlockTags; import net.minecraft.tag.BlockTags;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -136,6 +216,177 @@ public abstract class AppEngBase implements AppEng {
registries.cell().addCellGuiHandler(new BasicFluidCellGuiHandler()); registries.cell().addCellGuiHandler(new BasicFluidCellGuiHandler());
registries.matterCannon().registerAmmoItem(api.definitions().materials().matterBall().item(), 32); registries.matterCannon().registerAmmoItem(api.definitions().materials().matterBall().item(), 32);
// TODO: Do not use the internal API
ApiDefinitions definitions = Api.INSTANCE.definitions();
final IParts parts = definitions.parts();
final IBlocks blocks = definitions.blocks();
final IItems items = definitions.items();
// Block and part interface have different translation keys, but support the
// same upgrades
String interfaceGroup = parts.iface().asItem().getTranslationKey();
String itemIoBusGroup = GuiText.IOBuses.getTranslationKey();
String fluidIoBusGroup = GuiText.IOBusesFluids.getTranslationKey();
String storageCellGroup = GuiText.IOBusesFluids.getTranslationKey();
// default settings..
((P2PTunnelRegistry) registries.p2pTunnel()).configure();
// Interface
Upgrades.CRAFTING.registerItem(parts.iface(), 1, interfaceGroup);
Upgrades.CRAFTING.registerItem(blocks.iface(), 1, interfaceGroup);
// IO Port!
Upgrades.SPEED.registerItem(blocks.iOPort(), 3);
Upgrades.REDSTONE.registerItem(blocks.iOPort(), 1);
// Level Emitter!
Upgrades.FUZZY.registerItem(parts.levelEmitter(), 1);
Upgrades.CRAFTING.registerItem(parts.levelEmitter(), 1);
// Import Bus
Upgrades.FUZZY.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.importBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.importBus(), 4, itemIoBusGroup);
// Fluid Import Bus
Upgrades.CAPACITY.registerItem(parts.fluidImportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidImportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidImportBus(), 4, fluidIoBusGroup);
// Export Bus
Upgrades.FUZZY.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.exportBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.exportBus(), 4, itemIoBusGroup);
Upgrades.CRAFTING.registerItem(parts.exportBus(), 1, itemIoBusGroup);
// Fluid Export Bus
Upgrades.CAPACITY.registerItem(parts.fluidExportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidExportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidExportBus(), 4, fluidIoBusGroup);
// Storage Cells
Upgrades.FUZZY.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.viewCell(), 1);
Upgrades.INVERTER.registerItem(items.viewCell(), 1);
// Storage Bus
Upgrades.FUZZY.registerItem(parts.storageBus(), 1);
Upgrades.INVERTER.registerItem(parts.storageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.storageBus(), 5);
// Storage Bus Fluids
Upgrades.INVERTER.registerItem(parts.fluidStorageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.fluidStorageBus(), 5);
// Formation Plane
Upgrades.FUZZY.registerItem(parts.formationPlane(), 1);
Upgrades.INVERTER.registerItem(parts.formationPlane(), 1);
Upgrades.CAPACITY.registerItem(parts.formationPlane(), 5);
// Matter Cannon
Upgrades.FUZZY.registerItem(items.massCannon(), 1);
Upgrades.INVERTER.registerItem(items.massCannon(), 1);
Upgrades.SPEED.registerItem(items.massCannon(), 4);
// Molecular Assembler
Upgrades.SPEED.registerItem(blocks.molecularAssembler(), 5);
// Inscriber
Upgrades.SPEED.registerItem(blocks.inscriber(), 3);
// Wireless Terminal Handler
items.wirelessTerminal().maybeItem()
.ifPresent(terminal -> registries.wireless().registerWirelessHandler((IWirelessTermHandler) terminal));
// Charge Rates
items.chargedStaff().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 320d));
items.portableCell().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 800d));
items.colorApplicator().maybeItem()
.ifPresent(colorApplicator -> registries.charger().addChargeRate(colorApplicator, 800d));
items.wirelessTerminal().maybeItem().ifPresent(terminal -> registries.charger().addChargeRate(terminal, 8000d));
items.entropyManipulator().maybeItem()
.ifPresent(entropyManipulator -> registries.charger().addChargeRate(entropyManipulator, 8000d));
items.massCannon().maybeItem().ifPresent(massCannon -> registries.charger().addChargeRate(massCannon, 8000d));
blocks.energyCell().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 8000d));
blocks.energyCellDense().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 16000d));
// FIXME // add villager trading to black smiths for a few basic materials
// FIXME if( AEConfig.instance().isFeatureEnabled( AEFeature.VILLAGER_TRADING ) )
// FIXME {
// FIXME // TODO: VILLAGER TRADING
// FIXME // VillagerRegistry.instance().getRegisteredVillagers().registerVillageTradeHandler( 3, new AETrading() );
// FIXME }
final IMovableRegistry mr = registries.movable();
/*
* You can't move bed rock.
*/
mr.blacklistBlock(net.minecraft.block.Blocks.BEDROCK);
/*
* White List Vanilla...
*/
mr.whiteListBlockEntity(BannerBlockEntity.class);
mr.whiteListBlockEntity(BeaconBlockEntity.class);
mr.whiteListBlockEntity(BrewingStandBlockEntity.class);
mr.whiteListBlockEntity(ChestBlockEntity.class);
mr.whiteListBlockEntity(CommandBlockBlockEntity.class);
mr.whiteListBlockEntity(ComparatorBlockEntity.class);
mr.whiteListBlockEntity(DaylightDetectorBlockEntity.class);
mr.whiteListBlockEntity(DispenserBlockEntity.class);
mr.whiteListBlockEntity(DropperBlockEntity.class);
mr.whiteListBlockEntity(EnchantingTableBlockEntity.class);
mr.whiteListBlockEntity(EnderChestBlockEntity.class);
mr.whiteListBlockEntity(EndPortalBlockEntity.class);
mr.whiteListBlockEntity(FurnaceBlockEntity.class);
mr.whiteListBlockEntity(HopperBlockEntity.class);
mr.whiteListBlockEntity(MobSpawnerBlockEntity.class);
mr.whiteListBlockEntity(PistonBlockEntity.class);
mr.whiteListBlockEntity(ShulkerBoxBlockEntity.class);
mr.whiteListBlockEntity(SignBlockEntity.class);
mr.whiteListBlockEntity(SkullBlockEntity.class);
/*
* Whitelist AE2
*/
mr.whiteListBlockEntity(AEBaseBlockEntity.class);
/*
* world gen
*/
for (final IWorldGen.WorldGenType type : IWorldGen.WorldGenType.values()) {
// FIXME: registries.worldgen().disableWorldGenForProviderID( type,
// StorageWorldProvider.class );
registries.worldgen().disableWorldGenForDimension(type, DimensionType.THE_NETHER_REGISTRY_KEY.getValue());
}
// whitelist from config
for (final String dimension : AEConfig.instance().getMeteoriteDimensionWhitelist()) {
registries.worldgen().enableWorldGenForDimension(IWorldGen.WorldGenType.METEORITES,
new Identifier(dimension));
}
} }
protected void registerParticleTypes() { protected void registerParticleTypes() {
@@ -167,10 +418,9 @@ public abstract class AppEngBase implements AppEng {
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("quartz_knife"), QuartzKnifeRecipeSerializer.INSTANCE); Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("quartz_knife"), QuartzKnifeRecipeSerializer.INSTANCE);
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("grinder"), GrinderRecipeSerializer.INSTANCE); Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("grinder"), GrinderRecipeSerializer.INSTANCE);
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("inscriber"), InscriberRecipeSerializer.INSTANCE); Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("inscriber"), InscriberRecipeSerializer.INSTANCE);
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("disassemble"), DisassembleRecipe.SERIALIZER);
// FIXME FABRIC FacadeItem facadeItem = (FacadeItem) Api.INSTANCE.definitions().items().facade().item(); FacadeItem facadeItem = (FacadeItem) Api.INSTANCE.definitions().items().facade().item();
// FIXME FABRIC r.registerAll(DisassembleRecipe.SERIALIZER, Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("facade"), FacadeRecipe.getSerializer(facadeItem));
// FIXME FABRIC FacadeRecipe.getSerializer(facadeItem));
} }
@Override @Override
+1 -1
View File
@@ -41,7 +41,7 @@ public final class CreativeTab {
.icon(() -> { .icon(() -> {
final IDefinitions definitions = Api.instance().definitions(); final IDefinitions definitions = Api.instance().definitions();
final IBlocks blocks = definitions.blocks(); final IBlocks blocks = definitions.blocks();
return blocks.quartzOre().stack(1); // FIXME FABRIC blocks.controller().stack(1); return blocks.controller().stack(1);
}) })
.appendItems(CreativeTab::fill) .appendItems(CreativeTab::fill)
.build(); .build();
@@ -27,6 +27,7 @@ import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.FluidExtractable; import alexiil.mc.lib.attributes.fluid.FluidExtractable;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount; import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import appeng.crafting.CraftingLink;
import appeng.fluids.util.FluidList; import appeng.fluids.util.FluidList;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ClassToInstanceMap; import com.google.common.collect.ClassToInstanceMap;
@@ -99,8 +100,7 @@ public class ApiStorage implements IStorageHelper {
Preconditions.checkNotNull(data); Preconditions.checkNotNull(data);
Preconditions.checkNotNull(req); Preconditions.checkNotNull(req);
// FIXME FABRIC return new CraftingLink(data, req); return new CraftingLink(data, req);
throw new IllegalStateException();
} }
@Override @Override
@@ -173,7 +173,7 @@ public final class ApiBlocks implements IBlocks {
.sounds(BlockSoundGroup.GLASS) .sounds(BlockSoundGroup.GLASS)
.nonOpaque() .nonOpaque()
.allowsSpawning((state, world, pos, type) -> false) .allowsSpawning((state, world, pos, type) -> false)
.solidBlock((state, world, pos) -> false) .nonOpaque()
.suffocates((state, world, pos) -> false) .suffocates((state, world, pos) -> false)
.blockVision((state, world, pos) -> false); .blockVision((state, world, pos) -> false);
} }
@@ -249,7 +249,7 @@ public final class ApiBlocks implements IBlocks {
AbstractBlock.Settings skyStoneChestProps = defaultProps(Material.STONE) AbstractBlock.Settings skyStoneChestProps = defaultProps(Material.STONE)
.strength(50, 150) .strength(50, 150)
.solidBlock((state, world, pos) -> false); .nonOpaque();
TileEntityDefinition skyChestTile = registry TileEntityDefinition skyChestTile = registry
.tileEntity("sky_chest", SkyChestBlockEntity.class, SkyChestBlockEntity::new) .tileEntity("sky_chest", SkyChestBlockEntity.class, SkyChestBlockEntity::new)
@@ -281,7 +281,7 @@ public final class ApiBlocks implements IBlocks {
this.crank = registry this.crank = registry
.block("crank", .block("crank",
() -> new CrankBlock( () -> new CrankBlock(
defaultProps(Material.WOOD).breakByTool(FabricToolTags.AXES, 0).solidBlock((state, world, pos) -> false))) defaultProps(Material.WOOD).breakByTool(FabricToolTags.AXES, 0).nonOpaque()))
.features(AEFeature.GRIND_STONE) .features(AEFeature.GRIND_STONE)
.tileEntity(registry.tileEntity("crank", CrankBlockEntity.class, CrankBlockEntity::new) .tileEntity(registry.tileEntity("crank", CrankBlockEntity.class, CrankBlockEntity::new)
.rendering(new TileEntityRenderingCustomizer<CrankBlockEntity>() { .rendering(new TileEntityRenderingCustomizer<CrankBlockEntity>() {
@@ -292,7 +292,7 @@ public final class ApiBlocks implements IBlocks {
} }
}).build()) }).build())
.build(); .build();
this.inscriber = registry.block("inscriber", () -> new InscriberBlock(defaultProps(Material.METAL).solidBlock((state, world, pos) -> false))) this.inscriber = registry.block("inscriber", () -> new InscriberBlock(defaultProps(Material.METAL).nonOpaque()))
.features(AEFeature.INSCRIBER) .features(AEFeature.INSCRIBER)
.tileEntity(registry.tileEntity("inscriber", InscriberBlockEntity.class, InscriberBlockEntity::new) .tileEntity(registry.tileEntity("inscriber", InscriberBlockEntity.class, InscriberBlockEntity::new)
.rendering(new InscriberRendering()).build()) .rendering(new InscriberRendering()).build())
@@ -486,7 +486,7 @@ public final class ApiBlocks implements IBlocks {
}).build(); }).build();
this.molecularAssembler = registry this.molecularAssembler = registry
.block("molecular_assembler", () -> new MolecularAssemblerBlock(defaultProps(Material.METAL).solidBlock((state, world, pos) -> false))) .block("molecular_assembler", () -> new MolecularAssemblerBlock(defaultProps(Material.METAL).nonOpaque()))
.features(AEFeature.MOLECULAR_ASSEMBLER).rendering(new BlockRenderingCustomizer() { .features(AEFeature.MOLECULAR_ASSEMBLER).rendering(new BlockRenderingCustomizer() {
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
@Override @Override
@@ -97,8 +97,7 @@ public final class WirelessRegistry implements IWirelessTermRegistry {
} }
if (handler.hasPower(player, 0.5, item)) { if (handler.hasPower(player, 0.5, item)) {
// FIXME FABRIC ContainerOpener.openContainer(WirelessTermContainer.TYPE, player, ContainerLocator.forHand(player, hand)); ContainerOpener.openContainer(WirelessTermContainer.TYPE, player, ContainerLocator.forHand(player, hand));
throw new IllegalStateException();
} else { } else {
player.sendSystemMessage(PlayerMessages.DeviceNotPowered.get(), Util.NIL_UUID); player.sendSystemMessage(PlayerMessages.DeviceNotPowered.get(), Util.NIL_UUID);
} }
@@ -18,6 +18,8 @@
package appeng.entity; package appeng.entity;
import appeng.client.EffectType;
import appeng.items.misc.CrystalSeedItem;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Material; import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
@@ -116,8 +118,8 @@ public final class GrowingCrystalEntity extends AEBaseItemEntity {
if (this.progress_1000 >= len) { if (this.progress_1000 >= len) {
this.progress_1000 = 0; this.progress_1000 = 0;
// FIXME FABRIC AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2, AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2,
// FIXME FABRIC this.getZ(), null); this.getZ(), null);
} }
} else { } else {
if (this.progress_1000 > 1000) { if (this.progress_1000 > 1000) {
@@ -174,11 +176,10 @@ public final class GrowingCrystalEntity extends AEBaseItemEntity {
@Override @Override
public void applyBuoyancy() { public void applyBuoyancy() {
ItemStack item = getStack(); ItemStack item = getStack();
throw new IllegalStateException(); if (item.getItem() instanceof CrystalSeedItem) {
// FIXME FABRIC if (item.getItem() instanceof CrystalSeedItem) { return;
// FIXME FABRIC return; }
// FIXME FABRIC } super.applyBuoyancy();
// FIXME FABRIC super.applyBuoyancy();
} }
} }
@@ -35,12 +35,12 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_FLUID_VOLUME, this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_FLUID_VOLUME,
this::onLevelChange); this::onLevelChange);
this.level.setTextFieldBounds(25, 44, 75); this.level.setTextFieldBounds(25, 44, 75);
container.setTextField(this.level); handler.setTextField(this.level);
this.level.addButtons(children::add, this::addButton); this.level.addButtons(children::add, this::addButton);
final int y = 40; final int y = 40;
final int x = 80 + 57; final int x = 80 + 57;
this.guiSlots.add(new FluidSlotWidget(this.container.getFluidConfigInventory(), 0, 0, x, y)); this.guiSlots.add(new FluidSlotWidget(this.handler.getFluidConfigInventory(), 0, 0, x, y));
} }
@Override @Override
@@ -57,10 +57,10 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
} }
@Override @Override
public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { public void drawFG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int mouseY) {
super.drawFG(offsetX, offsetY, mouseX, mouseY); super.drawFG(matrices, offsetX, offsetY, mouseX, mouseY);
this.font.drawString(GuiText.FluidLevelEmitterUnit.getLocal(), 110, 44, COLOR_DARK_GRAY); this.textRenderer.draw(matrices, GuiText.FluidLevelEmitterUnit.getLocal(), 110, 44, COLOR_DARK_GRAY);
} }
@Override @Override
@@ -1,24 +1,23 @@
package appeng.fluids.client.gui.widgets; package appeng.fluids.client.gui.widgets;
import java.math.RoundingMode;
import java.util.Collections;
import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.FluidAttributes; import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.FluidExtractable; import alexiil.mc.lib.attributes.fluid.GroupedFluidInvView;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount; import alexiil.mc.lib.attributes.fluid.volume.FluidKey;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.client.gui.widgets.CustomSlotWidget; import appeng.client.gui.widgets.CustomSlotWidget;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.FluidSlotPacket; import appeng.core.sync.packets.FluidSlotPacket;
import appeng.fluids.util.AEFluidStack; import appeng.fluids.util.AEFluidStack;
import appeng.fluids.util.IAEFluidTank; import appeng.fluids.util.IAEFluidTank;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Set;
public class FluidSlotWidget extends CustomSlotWidget { public class FluidSlotWidget extends CustomSlotWidget {
private final IAEFluidTank fluids; private final IAEFluidTank fluids;
@@ -50,9 +49,11 @@ public class FluidSlotWidget extends CustomSlotWidget {
if (clickStack.isEmpty() || mouseButton == 1) { if (clickStack.isEmpty() || mouseButton == 1) {
this.setFluidStack(null); this.setFluidStack(null);
} else if (mouseButton == 0) { } else if (mouseButton == 0) {
FluidExtractable extractable = FluidAttributes.EXTRACTABLE.getFirstOrNull(clickStack); GroupedFluidInvView groupView = FluidAttributes.GROUPED_INV_VIEW.get(clickStack);
if (extractable != null && extractable.couldExtractAnything()) { Set<FluidKey> fluids = groupView.getStoredFluids();
FluidVolume volume = extractable.attemptAnyExtraction(FluidAmount.MAX_VALUE, Simulation.ACTION); if (!fluids.isEmpty()) {
FluidKey firstFluid = groupView.getStoredFluids().iterator().next();
FluidVolume volume = firstFluid.withAmount(groupView.getAmount_F(firstFluid));
this.setFluidStack(AEFluidStack.fromFluidVolume(volume, RoundingMode.DOWN)); this.setFluidStack(AEFluidStack.fromFluidVolume(volume, RoundingMode.DOWN));
} }
} }
@@ -88,7 +88,7 @@ public class FluidTankWidget extends AbstractButtonWidget implements ITooltip {
return desc.copy().append("\n").append(amountToText); return desc.copy().append("\n").append(amountToText);
} }
return ""; return LiteralText.EMPTY;
} }
@Override @Override
@@ -25,9 +25,12 @@ import java.nio.BufferOverflowException;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import alexiil.mc.lib.attributes.Simulation; import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.FixedFluidInv;
import alexiil.mc.lib.attributes.fluid.FluidAttributes; import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.FluidExtractable; import alexiil.mc.lib.attributes.fluid.FluidExtractable;
import alexiil.mc.lib.attributes.fluid.FluidInsertable; import alexiil.mc.lib.attributes.fluid.FluidInsertable;
import alexiil.mc.lib.attributes.fluid.GroupedFluidInv;
import alexiil.mc.lib.attributes.fluid.SingleFluidTank;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount; import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.filter.ExactFluidFilter; import alexiil.mc.lib.attributes.fluid.filter.ExactFluidFilter;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
@@ -327,9 +330,10 @@ public class FluidTerminalContainer extends AEBaseContainer
} }
// Check how much we can store in the item // Check how much we can store in the item
FluidVolume volumeAllowed = insertable.attemptInsertion(this.clientRequestedTargetFluid.getFluidStack().withAmount(FluidAmount.MAX_VALUE), Simulation.SIMULATE); FluidVolume volumeOverflow = insertable.attemptInsertion(this.clientRequestedTargetFluid.getFluidStack().withAmount(FluidAmount.ofWhole(Long.MAX_VALUE)), Simulation.SIMULATE);
FluidAmount amountAllowed = FluidAmount.ofWhole(Long.MAX_VALUE).saturatedSub(volumeOverflow.amount());
final IAEFluidStack stack = AEFluidStack.fromFluidVolume(this.clientRequestedTargetFluid.getFluidStack().withAmount(volumeAllowed.amount()), RoundingMode.DOWN); final IAEFluidStack stack = AEFluidStack.fromFluidVolume(this.clientRequestedTargetFluid.getFluidStack().withAmount(amountAllowed), RoundingMode.DOWN);
if (stack == null) { if (stack == null) {
return; // Might be nothing allowed... return; // Might be nothing allowed...
} }
@@ -342,13 +346,13 @@ public class FluidTerminalContainer extends AEBaseContainer
} }
// How much could fit into the container // How much could fit into the container
volumeAllowed = insertable.attemptInsertion(canPull.getFluidStack(), Simulation.SIMULATE); volumeOverflow = insertable.attemptInsertion(canPull.getFluidStack(), Simulation.SIMULATE);
if (volumeAllowed.isEmpty()) { if (!volumeOverflow.isEmpty()) {
return; return;
} }
// Now actually pull out of the system // Now actually pull out of the system
stack.setStackSize(volumeAllowed.amount().asLong(1000, RoundingMode.DOWN)); stack.setStackSize(canPull.getStackSize());
final IAEFluidStack pulled = Platform.poweredExtraction(this.getPowerSource(), this.monitor, stack, final IAEFluidStack pulled = Platform.poweredExtraction(this.getPowerSource(), this.monitor, stack,
this.getActionSource()); this.getActionSource());
if (pulled == null || pulled.getStackSize() < 1) { if (pulled == null || pulled.getStackSize() < 1) {
@@ -358,11 +362,11 @@ public class FluidTerminalContainer extends AEBaseContainer
} }
// Actually fill // Actually fill
final FluidVolume reallyFilled = insertable.attemptInsertion(pulled.getFluidStack(), Simulation.ACTION); volumeOverflow = insertable.attemptInsertion(pulled.getFluidStack(), Simulation.ACTION);
if (!reallyFilled.amount().equals(volumeAllowed.amount())) { if (!volumeOverflow.isEmpty()) {
AELog.error("Fluid item [%s] reported a different possible amount than it actually accepted.", AELog.error("Fluid item [%s] reported a different possible amount than it actually accepted. Overflow: %s.",
held.getName()); held, volumeOverflow);
} }
player.inventory.setCursorStack(container.get()); player.inventory.setCursorStack(container.get());
@@ -4,7 +4,7 @@ package appeng.fluids.parts;
import alexiil.mc.lib.attributes.Simulation; import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount; import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume; import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import appeng.core.Api; import alexiil.mc.lib.attributes.fluid.world.FluidWorldUtil;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.IncludeExclude; import appeng.api.config.IncludeExclude;
@@ -42,16 +42,14 @@ import net.minecraft.block.FluidBlock;
import net.minecraft.block.FluidFillable; import net.minecraft.block.FluidFillable;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.math.RoundingMode; import java.math.RoundingMode;
@@ -116,7 +114,7 @@ public class FluidFormationPlanePart extends AbstractFormationPlanePart<IAEFluid
final BlockPos pos = te.getPos().offset(side.getFacing()); final BlockPos pos = te.getPos().offset(side.getFacing());
FluidVolume volume = input.getFluidStack(); FluidVolume volume = input.getFluidStack();
FluidVolume remainder = fill(w, pos, volume, type == Actionable.MODULATE ? Simulation.ACTION : Simulation.SIMULATE); FluidVolume remainder = FluidWorldUtil.fill(w, pos, volume, type == Actionable.MODULATE ? Simulation.ACTION : Simulation.SIMULATE);
if (remainder.getAmount_F().isLessThan(volume.getAmount_F())) { if (remainder.getAmount_F().isLessThan(volume.getAmount_F())) {
// calculate the effective amount consumed // calculate the effective amount consumed
// round UP here because we might otherwise duplicate fluids // round UP here because we might otherwise duplicate fluids
@@ -132,62 +130,6 @@ public class FluidFormationPlanePart extends AbstractFormationPlanePart<IAEFluid
} }
} }
// FIXME https://github.com/AlexIIL/LibBlockAttributes/pull/21
/**
* Attempts to fill the given block with a bucket's worth of fluid
* @return The remainder of the given fluid volume after placing a bucket
*/
public static FluidVolume fill(WorldAccess world, BlockPos pos, FluidVolume volume, Simulation simulation) {
if (volume.getAmount_F().isLessThan(FluidAmount.BUCKET)) {
return volume; // Need at least a buckets worth
}
Fluid fluid = volume.getRawFluid();
if (fluid == null) {
return volume; // Can't be placed if it doesn't have an associated vanilla fluid
}
// This code assumes that placing a fluid in the world will always consume a bucket's worth
boolean success = false;
BlockState state = world.getBlockState(pos);
Block block = state.getBlock();
if (state.isAir()) {
// The easiest case, probably
if (simulation == Simulation.ACTION) {
BlockState fluidStillState = fluid.getDefaultState().getBlockState();
world.setBlockState(pos, fluidStillState, 3);
}
success = true;
} else if (block instanceof FluidFillable) {
// FluidFillable includes waterloggable blocks, but not cauldrons, etc.
FluidFillable fillable = (FluidFillable) block;
if (simulation == Simulation.SIMULATE) {
success = fillable.canFillWithFluid(world, pos, state, fluid);
} else {
success = fillable.tryFillWithFluid(world, pos, state, fluid.getDefaultState());
}
} else if (block instanceof FluidBlock) {
FluidState fluidState = world.getFluidState(pos);
// Top up a non-still fluid block, but this consumes a full bucket regardless of the level
if (!fluidState.isStill() && fluidState.getFluid() == fluid) {
if (simulation == Simulation.ACTION) {
world.setBlockState(pos, fluid.getDefaultState().getBlockState(), 3);
}
success = true;
}
}
if (success) {
// Reduce by one bucket
return volume.copy().withAmount(volume.getAmount_F().roundedSub(FluidAmount.ONE, RoundingMode.DOWN));
} else {
return volume;
}
}
@Override @Override
public void onFluidInventoryChanged(IAEFluidTank inv, int slot) { public void onFluidInventoryChanged(IAEFluidTank inv, int slot) {
if (inv == this.config) { if (inv == this.config) {
@@ -195,6 +137,13 @@ public class FluidFormationPlanePart extends AbstractFormationPlanePart<IAEFluid
} }
} }
protected boolean isBlocking(BlockView w, BlockPos pos) {
// Mirror the restrictions from the fill method
BlockState state = w.getBlockState(pos);
Block block = state.getBlock();
return !state.isAir() && !(block instanceof FluidFillable) && !(block instanceof FluidBlock);
}
@Override @Override
public void readFromNBT(final CompoundTag data) { public void readFromNBT(final CompoundTag data) {
super.readFromNBT(data); super.readFromNBT(data);
@@ -19,7 +19,6 @@
package appeng.fluids.util; package appeng.fluids.util;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount; import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.volume.FluidKey; import alexiil.mc.lib.attributes.fluid.volume.FluidKey;
@@ -48,10 +47,8 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
private static final String NBT_REQUESTABLE = "req"; private static final String NBT_REQUESTABLE = "req";
private static final String NBT_CRAFTABLE = "craft"; private static final String NBT_CRAFTABLE = "craft";
private static final String NBT_FLUID_ID = "f"; private static final String NBT_FLUID_ID = "f";
private static final String NBT_FLUID_TAG = "ft";
private final FluidKey fluid; private final FluidKey fluid;
private CompoundTag tagCompound;
private AEFluidStack(final AEFluidStack fluidStack) { private AEFluidStack(final AEFluidStack fluidStack) {
this.fluid = fluidStack.fluid; this.fluid = fluidStack.fluid;
@@ -60,18 +57,13 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
// priority = is.priority; // priority = is.priority;
this.setCraftable(fluidStack.isCraftable()); this.setCraftable(fluidStack.isCraftable());
this.setCountRequestable(fluidStack.getCountRequestable()); this.setCountRequestable(fluidStack.getCountRequestable());
if (fluidStack.hasTagCompound()) {
this.tagCompound = fluidStack.tagCompound.copy();
}
} }
private AEFluidStack(@Nonnull FluidKey fluid, long amount, @Nullable CompoundTag tag) { private AEFluidStack(@Nonnull FluidKey fluid, long amount) {
this.fluid = Preconditions.checkNotNull(fluid); this.fluid = Preconditions.checkNotNull(fluid);
this.setStackSize(amount); this.setStackSize(amount);
this.setCraftable(false); this.setCraftable(false);
this.setCountRequestable(0); this.setCountRequestable(0);
this.tagCompound = tag;
} }
public static AEFluidStack fromFluidVolume(final FluidVolume input, RoundingMode roundingMode) { public static AEFluidStack fromFluidVolume(final FluidVolume input, RoundingMode roundingMode) {
@@ -84,14 +76,9 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
throw new IllegalArgumentException("Fluid is null."); throw new IllegalArgumentException("Fluid is null.");
} }
CompoundTag tag = input.toTag();
if (tag.isEmpty()) {
tag = null;
}
long amount = input.amount().asLong(1000, roundingMode); long amount = input.amount().asLong(1000, roundingMode);
return new AEFluidStack(fluid, amount, tag); return new AEFluidStack(fluid, amount);
} }
public static IAEFluidStack fromNBT(final CompoundTag data) { public static IAEFluidStack fromNBT(final CompoundTag data) {
@@ -101,14 +88,9 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
return null; return null;
} }
CompoundTag tag = null;
if (data.contains(NBT_FLUID_TAG, NbtType.COMPOUND)) {
tag = data.getCompound(NBT_FLUID_TAG);
}
long amount = data.getLong(NBT_STACKSIZE); long amount = data.getLong(NBT_STACKSIZE);
AEFluidStack fluidStack = new AEFluidStack(fluid, amount, tag); AEFluidStack fluidStack = new AEFluidStack(fluid, amount);
fluidStack.setCountRequestable(data.getLong(NBT_REQUESTABLE)); fluidStack.setCountRequestable(data.getLong(NBT_REQUESTABLE));
fluidStack.setCraftable(data.getBoolean(NBT_CRAFTABLE)); fluidStack.setCraftable(data.getBoolean(NBT_CRAFTABLE));
return fluidStack; return fluidStack;
@@ -127,9 +109,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
@Override @Override
public void writeToNBT(final CompoundTag data) { public void writeToNBT(final CompoundTag data) {
data.put(NBT_FLUID_ID, this.fluid.toTag()); data.put(NBT_FLUID_ID, this.fluid.toTag());
if (this.hasTagCompound()) {
data.put(NBT_FLUID_TAG, this.tagCompound);
}
data.putLong(NBT_STACKSIZE, this.getStackSize()); data.putLong(NBT_STACKSIZE, this.getStackSize());
data.putLong(NBT_REQUESTABLE, this.getCountRequestable()); data.putLong(NBT_REQUESTABLE, this.getCountRequestable());
data.putBoolean(NBT_CRAFTABLE, this.isCraftable()); data.putBoolean(NBT_CRAFTABLE, this.isCraftable());
@@ -162,12 +141,7 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
if (this.fluid != other.fluid) { if (this.fluid != other.fluid) {
return this.fluid.entry.getId().compareTo(other.fluid.entry.getId()); return this.fluid.entry.getId().compareTo(other.fluid.entry.getId());
} }
return 0;
if (Platform.itemComparisons().isNbtTagEqual(this.tagCompound, other.tagCompound)) {
return 0;
}
return this.tagCompound.hashCode() - other.tagCompound.hashCode();
} }
@Override @Override
@@ -175,7 +149,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((this.fluid == null) ? 0 : this.fluid.hashCode()); result = prime * result + ((this.fluid == null) ? 0 : this.fluid.hashCode());
result = prime * result + ((this.tagCompound == null) ? 0 : this.tagCompound.hashCode());
return result; return result;
} }
@@ -184,29 +157,28 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
public boolean equals(final Object other) { public boolean equals(final Object other) {
if (other instanceof AEFluidStack) { if (other instanceof AEFluidStack) {
final AEFluidStack is = (AEFluidStack) other; final AEFluidStack is = (AEFluidStack) other;
return is.fluid == this.fluid && Platform.itemComparisons().isNbtTagEqual(this.tagCompound, is.tagCompound); return is.fluid == this.fluid;
} else if (other instanceof FluidVolume) { } else if (other instanceof FluidVolume) {
final FluidVolume is = (FluidVolume) other; final FluidVolume is = (FluidVolume) other;
return is.getFluidKey() == this.fluid return is.getFluidKey() == this.fluid;
&& Platform.itemComparisons().isNbtTagEqual(this.tagCompound, is.toTag());
} }
return false; return false;
} }
@Override @Override
public String toString() { public String toString() {
return this.getStackSize() + "x" + this.getFluidStack().getFluidKey().entry.getId() + " " + this.tagCompound; return this.getStackSize() + "x" + this.getFluidStack().getFluidKey().entry.getId();
} }
@Override @Override
public boolean hasTagCompound() { public boolean hasTagCompound() {
return this.tagCompound != null; return false;
} }
@Override @Override
public FluidVolume getFluidStack() { public FluidVolume getFluidStack() {
FluidAmount amount = FluidAmount.of(this.getStackSize(), 1000); FluidAmount amount = FluidAmount.of(this.getStackSize(), 1000);
return this.fluid.readVolume(tagCompound).withAmount(amount); return this.fluid.withAmount(amount);
} }
@Override @Override
@@ -234,11 +206,10 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
final boolean isCraftable = buffer.readBoolean(); final boolean isCraftable = buffer.readBoolean();
FluidKey fluid = FluidKey.fromTag(buffer.readCompoundTag()); FluidKey fluid = FluidKey.fromTag(buffer.readCompoundTag());
CompoundTag compoundTag = buffer.readCompoundTag();
final long amount = buffer.readVarLong(); final long amount = buffer.readVarLong();
final long countRequestable = buffer.readVarLong(); final long countRequestable = buffer.readVarLong();
final AEFluidStack fluidStack = new AEFluidStack(fluid, amount, compoundTag); final AEFluidStack fluidStack = new AEFluidStack(fluid, amount);
fluidStack.setCountRequestable(countRequestable); fluidStack.setCountRequestable(countRequestable);
fluidStack.setCraftable(isCraftable); fluidStack.setCraftable(isCraftable);
return fluidStack; return fluidStack;
@@ -248,7 +219,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
public void writeToPacket(final PacketByteBuf buffer) { public void writeToPacket(final PacketByteBuf buffer) {
buffer.writeBoolean(this.isCraftable()); buffer.writeBoolean(this.isCraftable());
buffer.writeCompoundTag(fluid.toTag()); buffer.writeCompoundTag(fluid.toTag());
buffer.writeCompoundTag(tagCompound);
buffer.writeVarLong(this.getStackSize()); buffer.writeVarLong(this.getStackSize());
buffer.writeVarLong(this.getCountRequestable()); buffer.writeVarLong(this.getCountRequestable());
} }
@@ -1,13 +1,24 @@
package appeng.hooks; package appeng.hooks;
import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import appeng.client.render.DummyFluidBakedModel;
import appeng.fluids.items.FluidDummyItem;
import appeng.items.misc.EncodedPatternItem; import appeng.items.misc.EncodedPatternItem;
import appeng.mixins.ItemRendererAccessor; import appeng.mixins.ItemRendererAccessor;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
public final class ItemRendererHooks { public final class ItemRendererHooks {
@@ -22,7 +33,11 @@ public final class ItemRendererHooks {
* if shift is held. * if shift is held.
*/ */
public static boolean onRenderGuiItemModel(ItemRenderer renderer, ItemStack stack, int x, int y, BakedModel model) { public static boolean onRenderGuiItemModel(ItemRenderer renderer, ItemStack stack, int x, int y, BakedModel model) {
if (stack.getItem() instanceof EncodedPatternItem && OVERRIDING_FOR.get() != stack) { if (OVERRIDING_FOR.get() == stack) {
return false; // Don't allow recursive model replacements
}
if (stack.getItem() instanceof EncodedPatternItem) {
boolean shiftHeld = Screen.hasShiftDown(); boolean shiftHeld = Screen.hasShiftDown();
ClientWorld world = MinecraftClient.getInstance().world; ClientWorld world = MinecraftClient.getInstance().world;
if (shiftHeld && world != null) { if (shiftHeld && world != null) {
@@ -31,18 +46,28 @@ public final class ItemRendererHooks {
if (!output.isEmpty()) { if (!output.isEmpty()) {
BakedModel realModel = MinecraftClient.getInstance().getItemRenderer().getModels() BakedModel realModel = MinecraftClient.getInstance().getItemRenderer().getModels()
.getModel(output); .getModel(output);
ItemRendererAccessor self = (ItemRendererAccessor) renderer; renderInstead(renderer, stack, x, y, realModel);
OVERRIDING_FOR.set(stack);
try {
self.callRenderGuiItemModel(stack, x, y, realModel);
} finally {
OVERRIDING_FOR.remove();
}
return true; return true;
} }
} }
} else if (stack.getItem() instanceof FluidDummyItem) {
FluidDummyItem itemFacade = (FluidDummyItem) stack.getItem();
FluidVolume fluidStack = itemFacade.getFluidStack(stack);
renderInstead(renderer, stack, x, y, new DummyFluidBakedModel(fluidStack));
return true;
} }
return false; return false;
} }
private static void renderInstead(ItemRenderer renderer, ItemStack stack, int x, int y, BakedModel realModel) {
ItemRendererAccessor self = (ItemRendererAccessor) renderer;
OVERRIDING_FOR.set(stack);
try {
self.callRenderGuiItemModel(stack, x, y, realModel);
} finally {
OVERRIDING_FOR.remove();
}
}
} }
+47 -19
View File
@@ -18,23 +18,7 @@
package appeng.hooks; package appeng.hooks;
import java.util.ArrayDeque; import appeng.api.networking.IGridNode;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.world.World;
import appeng.api.util.AEColor; import appeng.api.util.AEColor;
import appeng.core.AEConfig; import appeng.core.AEConfig;
import appeng.core.AELog; import appeng.core.AELog;
@@ -44,14 +28,32 @@ import appeng.me.Grid;
import appeng.tile.AEBaseBlockEntity; import appeng.tile.AEBaseBlockEntity;
import appeng.util.IWorldCallable; import appeng.util.IWorldCallable;
import appeng.util.Platform; import appeng.util.Platform;
import com.google.common.base.Stopwatch;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
public class TickHandler { public class TickHandler {
private static final TickHandler INSTANCE = new TickHandler(); private static TickHandler INSTANCE;
private final Queue<IWorldCallable<?>> serverQueue = new ArrayDeque<>(); private final Queue<IWorldCallable<?>> serverQueue = new ArrayDeque<>();
private final Multimap<World, CraftingJob> craftingJobs = LinkedListMultimap.create(); private final Multimap<World, CraftingJob> craftingJobs = LinkedListMultimap.create();
private final Map<WorldAccess, Queue<IWorldCallable<?>>> callQueue = new WeakHashMap<>(); private final Map<WorldAccess, Queue<IWorldCallable<?>>> callQueue = new WeakHashMap<>();
@@ -60,11 +62,16 @@ public class TickHandler {
private final HashMap<Integer, PlayerColor> srvPlayerColors = new HashMap<>(); private final HashMap<Integer, PlayerColor> srvPlayerColors = new HashMap<>();
public TickHandler() { public TickHandler() {
if (INSTANCE != null) {
throw new IllegalStateException("There can only be a single tick handler.");
}
INSTANCE = this;
// Register for all the tick events we care about // Register for all the tick events we care about
ServerTickEvents.END_SERVER_TICK.register(this::onAfterServerTick); ServerTickEvents.END_SERVER_TICK.register(this::onAfterServerTick);
ServerTickEvents.START_WORLD_TICK.register(this::onBeforeWorldTick); ServerTickEvents.START_WORLD_TICK.register(this::onBeforeWorldTick);
ServerTickEvents.END_WORLD_TICK.register(this::onAfterWorldTick); ServerTickEvents.END_WORLD_TICK.register(this::onAfterWorldTick);
ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStopping);
} }
public static TickHandler instance() { public static TickHandler instance() {
@@ -147,6 +154,27 @@ public class TickHandler {
// FIXME FABRIC } // FIXME FABRIC }
// FIXME FABRIC } // FIXME FABRIC }
/**
* This is primarily useful for an integrated server being stopped, and can be fully replaced by the event
* above once world unload events hit.
*/
private void onServerStopping(MinecraftServer server) {
final List<IGridNode> toDestroy = new ArrayList<>();
this.server.updateNetworks();
for (final Grid g : this.server.networks) {
for (final IGridNode n : g.getNodes()) {
WorldAccess nodeWorld = n.getWorld();
if (nodeWorld instanceof ServerWorld && ((ServerWorld) nodeWorld).getServer() == server) {
toDestroy.add(n);
}
}
}
for (final IGridNode n : toDestroy) {
n.destroy();
}
}
private void onBeforeWorldTick(ServerWorld world) { private void onBeforeWorldTick(ServerWorld world) {
final Queue<IWorldCallable<?>> queue = this.callQueue.get(world); final Queue<IWorldCallable<?>> queue = this.callQueue.get(world);
this.processQueue(queue, world); this.processQueue(queue, world);
@@ -20,7 +20,10 @@ package appeng.items.tools;
import java.util.List; import java.util.List;
import appeng.block.AEBaseTileBlock;
import appeng.hooks.AEToolItem;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.minecraft.block.BlockState;
import net.minecraft.client.item.TooltipContext; import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -29,6 +32,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
@@ -40,7 +44,7 @@ import appeng.core.localization.PlayerMessages;
import appeng.items.AEBaseItem; import appeng.items.AEBaseItem;
import appeng.util.Platform; import appeng.util.Platform;
public class MemoryCardItem extends AEBaseItem implements IMemoryCard { public class MemoryCardItem extends AEBaseItem implements AEToolItem, IMemoryCard {
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT, private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT,
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
@@ -158,15 +162,21 @@ public class MemoryCardItem extends AEBaseItem implements IMemoryCard {
} }
@Override @Override
public ActionResult useOnBlock(ItemUsageContext context) { public ActionResult onItemUseFirst(ItemStack stack, ItemUsageContext context) {
if (context.getPlayer().isInSneakingPose()) { if (context.getPlayer().isInSneakingPose()) {
// Bypass the memory card's own use handler and go straight to the block
if (!context.getPlayer().world.isClient) { if (!context.getPlayer().world.isClient) {
this.clearCard(context.getPlayer(), context.getWorld(), context.getHand()); BlockState state = context.getWorld().getBlockState(context.getBlockPos());
ActionResult useResult = state.onUse(context.getWorld(), context.getPlayer(), context.getHand(),
new BlockHitResult(context.getHitPos(), context.getSide(), context.getBlockPos(), context.hitsInsideBlock()));
if (!useResult.isAccepted()) {
clearCard(context.getPlayer(), context.getWorld(), context.getHand());
}
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} else {
return super.useOnBlock(context);
} }
return ActionResult.PASS;
} }
@Override @Override
@@ -180,15 +190,10 @@ public class MemoryCardItem extends AEBaseItem implements IMemoryCard {
return super.use(w, player, hand); return super.use(w, player, hand);
} }
// FIXME FABRIC probably needs a custom mixin
// FIXME FABRIC @Override
// FIXME FABRIC public boolean doesSneakBypassUse(ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player) {
// FIXME FABRIC return true;
// FIXME FABRIC }
private void clearCard(final PlayerEntity player, final World w, final Hand hand) { private void clearCard(final PlayerEntity player, final World w, final Hand hand) {
final IMemoryCard mem = (IMemoryCard) player.getStackInHand(hand).getItem(); final IMemoryCard mem = (IMemoryCard) player.getStackInHand(hand).getItem();
mem.notifyUser(player, MemoryCardMessages.SETTINGS_CLEARED); mem.notifyUser(player, MemoryCardMessages.SETTINGS_CLEARED);
player.getStackInHand(hand).setTag(null); player.getStackInHand(hand).setTag(null);
} }
} }
@@ -109,6 +109,7 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench,
} }
// FIXME FABRIC: No direct equivalent // FIXME FABRIC: No direct equivalent
// FIXME FABRIC: Might already be handled by onItemUseFirst though
// FIXME FABRIC @Override // FIXME FABRIC @Override
// FIXME FABRIC public boolean doesSneakBypassUse(ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player) { // FIXME FABRIC public boolean doesSneakBypassUse(ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player) {
// FIXME FABRIC return true; // FIXME FABRIC return true;
@@ -19,6 +19,9 @@
package appeng.items.tools.quartz; package appeng.items.tools.quartz;
import appeng.container.ContainerLocator; import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.QuartzKnifeContainer;
import appeng.items.contents.QuartzKnifeObj;
import appeng.mixins.RemainderSetter; import appeng.mixins.RemainderSetter;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@@ -48,8 +51,7 @@ public class QuartzCuttingKnifeItem extends AEBaseItem implements IGuiItem {
@Override @Override
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) { public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
if (Platform.isServer()) { if (Platform.isServer()) {
// FIXME FABRIC ContainerOpener.openContainer(QuartzKnifeContainer.TYPE, p, ContainerLocator.forHand(p, hand)); ContainerOpener.openContainer(QuartzKnifeContainer.TYPE, p, ContainerLocator.forHand(p, hand));
throw new IllegalStateException();
} }
p.swingHand(hand); p.swingHand(hand);
return new TypedActionResult<>(ActionResult.SUCCESS, p.getStackInHand(hand)); return new TypedActionResult<>(ActionResult.SUCCESS, p.getStackInHand(hand));
@@ -58,7 +60,6 @@ public class QuartzCuttingKnifeItem extends AEBaseItem implements IGuiItem {
@Override @Override
public IGuiItemObject getGuiObject(final ItemStack is, int playerInventorySlot, final World world, public IGuiItemObject getGuiObject(final ItemStack is, int playerInventorySlot, final World world,
final BlockPos pos) { final BlockPos pos) {
// FIXME FABRIC return new QuartzKnifeObj(is); return new QuartzKnifeObj(is);
throw new IllegalStateException();
} }
} }
+4 -5
View File
@@ -64,11 +64,10 @@ public class GridStorage implements IGridStorage {
} }
public void saveState() { public void saveState() {
throw new IllegalStateException(); final Grid currentGrid = (Grid) this.getGrid();
// FIXME FABRIC final Grid currentGrid = (Grid) this.getGrid(); if (currentGrid != null) {
// FIXME FABRIC if (currentGrid != null) { currentGrid.saveState();
// FIXME FABRIC currentGrid.saveState(); }
// FIXME FABRIC }
} }
public IGrid getGrid() { public IGrid getGrid() {
@@ -95,8 +95,8 @@ public abstract class MBCalculator<TTile extends IAEMultiBlock<TCluster>, TClust
} }
try { try {
final BlockPos.Mutable min = new BlockPos.Mutable(loc); final BlockPos.Mutable min = loc.mutableCopy();
final BlockPos.Mutable max = new BlockPos.Mutable(loc); final BlockPos.Mutable max = loc.mutableCopy();
// find size of MB structure... // find size of MB structure...
while (this.isValidTileAt(world, min.getX() - 1, min.getY(), min.getZ())) { while (this.isValidTileAt(world, min.getX() - 1, min.getY(), min.getZ())) {
@@ -259,7 +259,7 @@ public abstract class MBCalculator<TTile extends IAEMultiBlock<TCluster>, TClust
return false; return false;
} }
for (BlockPos p : BlockPos.getAllInBoxMutable(minX, minY, minZ, maxX, maxY, maxZ)) { for (BlockPos p : BlockPos.iterate(minX, minY, minZ, maxX, maxY, maxZ)) {
final BlockEntity te = w.getBlockEntity(p); final BlockEntity te = w.getBlockEntity(p);
if (this.isValidTile(te)) { if (this.isValidTile(te)) {
return true; return true;
@@ -33,9 +33,9 @@ import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator; import appeng.me.cluster.MBCalculator;
import appeng.tile.crafting.CraftingBlockEntity; import appeng.tile.crafting.CraftingBlockEntity;
public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, CraftingCPUCluster> { public class CraftingCPUCalculator extends MBCalculator<CraftingBlockEntity, CraftingCPUCluster> {
public CraftingCPUCalculator(final CraftingTileEntity t) { public CraftingCPUCalculator(final CraftingBlockEntity t) {
super(t); super(t);
} }
@@ -65,7 +65,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) { public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
boolean storage = false; boolean storage = false;
for (BlockPos blockPos : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos blockPos : BlockPos.iterate(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(blockPos); final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(blockPos);
if (te == null || !te.isValid()) { if (te == null || !te.isValid()) {
@@ -82,7 +82,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
@Override @Override
public void updateTiles(final CraftingCPUCluster c, final World w, final BlockPos min, final BlockPos max) { public void updateTiles(final CraftingCPUCluster c, final World w, final BlockPos min, final BlockPos max) {
for (BlockPos blockPos : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos blockPos : BlockPos.iterate(min, max)) {
final CraftingBlockEntity te = (CraftingBlockEntity) w.getBlockEntity(blockPos); final CraftingBlockEntity te = (CraftingBlockEntity) w.getBlockEntity(blockPos);
te.updateStatus(c); te.updateStatus(c);
c.addTile(te); c.addTile(te);
@@ -90,7 +90,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
c.done(); c.done();
final Iterator<CraftingTileEntity> i = c.getTiles(); final Iterator<CraftingBlockEntity> i = c.getTiles();
while (i.hasNext()) { while (i.hasNext()) {
final IGridHost gh = i.next(); final IGridHost gh = i.next();
final IGridNode n = gh.getGridNode(AEPartLocation.INTERNAL); final IGridNode n = gh.getGridNode(AEPartLocation.INTERNAL);
@@ -183,7 +183,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
} }
@Override @Override
public Iterator<CraftingTileEntity> getTiles() { public Iterator<CraftingBlockEntity> getTiles() {
return this.tiles.iterator(); return this.tiles.iterator();
} }
@@ -30,9 +30,9 @@ import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator; import appeng.me.cluster.MBCalculator;
import appeng.tile.qnb.QuantumBridgeBlockEntity; import appeng.tile.qnb.QuantumBridgeBlockEntity;
public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, QuantumCluster> { public class QuantumCalculator extends MBCalculator<QuantumBridgeBlockEntity, QuantumCluster> {
public QuantumCalculator(final QuantumBridgeTileEntity t) { public QuantumCalculator(final QuantumBridgeBlockEntity t) {
super(t); super(t);
} }
@@ -60,8 +60,8 @@ public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, Qua
byte num = 0; byte num = 0;
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos p : BlockPos.iterate(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p); final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(p);
if (te == null || !te.isValid()) { if (te == null || !te.isValid()) {
return false; return false;
@@ -87,7 +87,7 @@ public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, Qua
byte num = 0; byte num = 0;
byte ringNum = 0; byte ringNum = 0;
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos p : BlockPos.iterate(min, max)) {
final QuantumBridgeBlockEntity te = (QuantumBridgeBlockEntity) w.getBlockEntity(p); final QuantumBridgeBlockEntity te = (QuantumBridgeBlockEntity) w.getBlockEntity(p);
num++; num++;
@@ -20,6 +20,7 @@ package appeng.me.cluster.implementations;
import java.util.Iterator; import java.util.Iterator;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
@@ -234,7 +235,7 @@ public class QuantumCluster implements ILocatable, IAECluster {
} }
@Override @Override
public Iterator<QuantumBridgeTileEntity> getTiles() { public Iterator<QuantumBridgeBlockEntity> getTiles() {
return new ChainedIterator<>(this.getRing()[0], this.getRing()[1], this.getRing()[2], this.getRing()[3], return new ChainedIterator<>(this.getRing()[0], this.getRing()[1], this.getRing()[2], this.getRing()[3],
this.getRing()[4], this.getRing()[5], this.getRing()[6], this.getRing()[7], this.center); this.getRing()[4], this.getRing()[5], this.getRing()[6], this.getRing()[7], this.center);
} }
@@ -26,9 +26,9 @@ import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator; import appeng.me.cluster.MBCalculator;
import appeng.tile.spatial.SpatialPylonBlockEntity; import appeng.tile.spatial.SpatialPylonBlockEntity;
public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity, SpatialPylonCluster> { public class SpatialPylonCalculator extends MBCalculator<SpatialPylonBlockEntity, SpatialPylonCluster> {
public SpatialPylonCalculator(final SpatialPylonTileEntity t) { public SpatialPylonCalculator(final SpatialPylonBlockEntity t) {
super(t); super(t);
} }
@@ -47,8 +47,8 @@ public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity,
@Override @Override
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) { public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos p : BlockPos.iterate(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p); final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(p);
if (te == null || !te.isValid()) { if (te == null || !te.isValid()) {
return false; return false;
@@ -60,8 +60,8 @@ public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity,
@Override @Override
public void updateTiles(final SpatialPylonCluster c, final World w, final BlockPos min, final BlockPos max) { public void updateTiles(final SpatialPylonCluster c, final World w, final BlockPos min, final BlockPos max) {
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) { for (BlockPos p : BlockPos.iterate(min, max)) {
final SpatialPylonTileEntity te = (SpatialPylonTileEntity) w.getTileEntity(p); final SpatialPylonBlockEntity te = (SpatialPylonBlockEntity) w.getBlockEntity(p);
te.updateStatus(c); te.updateStatus(c);
c.getLine().add(te); c.getLine().add(te);
} }
@@ -87,7 +87,7 @@ public class SpatialPylonCluster implements IAECluster {
} }
@Override @Override
public Iterator<SpatialPylonTileEntity> getTiles() { public Iterator<SpatialPylonBlockEntity> getTiles() {
return this.getLine().iterator(); return this.getLine().iterator();
} }
@@ -171,10 +171,14 @@ public abstract class AbstractFormationPlanePart<T extends IAEStack<T>> extends
final BlockPos tePos = te.getPos().offset(side.getFacing()); final BlockPos tePos = te.getPos().offset(side.getFacing());
this.blocked = !w.getBlockState(tePos).getMaterial().isReplaceable(); this.blocked = isBlocking(w, tePos);
} }
} }
protected boolean isBlocking(BlockView w, BlockPos pos) {
return !w.getBlockState(pos).getMaterial().isReplaceable();
}
@Override @Override
public float getCableConnectionLength(AECableType cable) { public float getCableConnectionLength(AECableType cable) {
return 1; return 1;
@@ -18,47 +18,54 @@
package appeng.parts.automation; package appeng.parts.automation;
import java.util.ArrayList; import appeng.api.parts.IDynamicPartBakedModel;
import appeng.client.render.cablebus.CubeBuilder;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.client.render.cablebus.CubeBuilder;
/** /**
* Built-in model for annihilation planes that supports connected textures. * Built-in model for annihilation planes that supports connected textures.
*/ */
public class PlaneBakedModel implements IDynamicBakedModel { public class PlaneBakedModel implements BakedModel, IDynamicPartBakedModel {
private static final PlaneConnections DEFAULT_PERMUTATION = PlaneConnections.of(false, false, false, false); private static final PlaneConnections DEFAULT_PERMUTATION = PlaneConnections.of(false, false, false, false);
private final Sprite frontTexture; private final Sprite frontTexture;
private final Map<PlaneConnections, List<BakedQuad>> quads; private final Map<PlaneConnections, Mesh> meshes;
PlaneBakedModel(Sprite frontTexture, Sprite sidesTexture, Sprite backTexture) { PlaneBakedModel(Sprite frontTexture, Sprite sidesTexture, Sprite backTexture) {
this.frontTexture = frontTexture; this.frontTexture = frontTexture;
quads = new HashMap<>(PlaneConnections.PERMUTATIONS.size()); Renderer renderer = RendererAccess.INSTANCE.getRenderer();
meshes = new HashMap<>(PlaneConnections.PERMUTATIONS.size());
// Create all possible permutations (16) // Create all possible permutations (16)
for (PlaneConnections permutation : PlaneConnections.PERMUTATIONS) { for (PlaneConnections permutation : PlaneConnections.PERMUTATIONS) {
List<BakedQuad> quads = new ArrayList<>(4 * 6);
CubeBuilder builder = new CubeBuilder(quads); MeshBuilder meshBuilder = renderer.meshBuilder();
CubeBuilder builder = new CubeBuilder(meshBuilder.getEmitter());
builder.setTextures(sidesTexture, sidesTexture, frontTexture, backTexture, sidesTexture, sidesTexture); builder.setTextures(sidesTexture, sidesTexture, frontTexture, backTexture, sidesTexture, sidesTexture);
@@ -72,22 +79,29 @@ public class PlaneBakedModel implements IDynamicBakedModel {
builder.addCube(minX, minY, 0, maxX, maxY, 1); builder.addCube(minX, minY, 0, maxX, maxY, 1);
this.quads.put(permutation, ImmutableList.copyOf(quads)); this.meshes.put(permutation, meshBuilder.build());
} }
} }
@Override @Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, public void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context, Direction partSide, @Nullable Object modelData) {
IModelData modelData) { PlaneConnections connections = DEFAULT_PERMUTATION;
if (side == null) {
PlaneConnections connections = DEFAULT_PERMUTATION; if (modelData instanceof PlaneConnections) {
if (modelData instanceof PlaneModelData) { connections = (PlaneConnections) modelData;
connections = ((PlaneModelData) modelData).getConnections();
}
return this.quads.get(connections);
} else {
return Collections.emptyList();
} }
context.meshConsumer().accept(this.meshes.get(connections));
}
@Override
public ModelTransformation getTransformation() {
return ModelTransformation.NONE;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return Collections.emptyList();
} }
@Override @Override
@@ -102,7 +116,7 @@ public class PlaneBakedModel implements IDynamicBakedModel {
@Override @Override
public boolean isSideLit() { public boolean isSideLit() {
return false;// TODO return false;
} }
@Override @Override
@@ -18,24 +18,18 @@
package appeng.parts.automation; package appeng.parts.automation;
import java.util.Arrays; import appeng.client.render.BasicUnbakedModel;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform; import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader; import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry; import javax.annotation.Nullable;
import java.util.function.Function;
import java.util.stream.Stream;
/** /**
* Built-in model for annihilation planes that supports connected textures. * Built-in model for annihilation planes that supports connected textures.
@@ -52,21 +46,19 @@ public class PlaneModel implements BasicUnbakedModel {
this.backTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, backTexture); this.backTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, backTexture);
} }
@Nullable
@Override @Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery, public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform, Sprite frontSprite = textureGetter.apply(this.frontTexture);
ModelOverrideList overrides, Identifier modelLocation) { Sprite sidesSprite = textureGetter.apply(this.sidesTexture);
Sprite frontSprite = spriteGetter.apply(this.frontTexture); Sprite backSprite = textureGetter.apply(this.backTexture);
Sprite sidesSprite = spriteGetter.apply(this.sidesTexture);
Sprite backSprite = spriteGetter.apply(this.backTexture);
return new PlaneBakedModel(frontSprite, sidesSprite, backSprite); return new PlaneBakedModel(frontSprite, sidesSprite, backSprite);
} }
@Override @Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner, public Stream<SpriteIdentifier> getAdditionalTextures() {
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) { return Stream.of(frontTexture, sidesTexture, backTexture);
return Arrays.asList(frontTexture, sidesTexture, backTexture);
} }
} }
@@ -18,21 +18,6 @@
package appeng.recipes.game; package appeng.recipes.game;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.item.crafting.SpecialRecipe;
import net.minecraft.item.crafting.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import appeng.api.definitions.IBlocks; import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IDefinitions; import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IItemDefinition; import appeng.api.definitions.IItemDefinition;
@@ -43,16 +28,24 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.Api; import appeng.core.Api;
import appeng.core.AppEng; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
public final class DisassembleRecipe extends SpecialRecipe { import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public final class DisassembleRecipe extends SpecialCraftingRecipe {
public static final RecipeSerializer<DisassembleRecipe> SERIALIZER = new SpecialRecipeSerializer<>( public static final RecipeSerializer<DisassembleRecipe> SERIALIZER = new SpecialRecipeSerializer<>(
DisassembleRecipe::new); DisassembleRecipe::new);
static {
SERIALIZER.setRegistryName(new Identifier(AppEng.MOD_ID, "disassemble"));
}
private static final ItemStack MISMATCHED_STACK = ItemStack.EMPTY; private static final ItemStack MISMATCHED_STACK = ItemStack.EMPTY;
private final Map<IItemDefinition, IItemDefinition> cellMappings; private final Map<IItemDefinition, IItemDefinition> cellMappings;
@@ -155,7 +148,7 @@ public final class DisassembleRecipe extends SpecialRecipe {
} }
@Override @Override
public boolean canFit(int i, int i1) { public boolean fits(int i, int i1) {
return false; return false;
} }
@@ -18,24 +18,23 @@
package appeng.recipes.game; package appeng.recipes.game;
import javax.annotation.Nonnull;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.item.crafting.SpecialRecipe;
import net.minecraft.item.crafting.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import appeng.api.definitions.IComparableDefinition; import appeng.api.definitions.IComparableDefinition;
import appeng.api.definitions.IDefinitions; import appeng.api.definitions.IDefinitions;
import appeng.core.Api; import appeng.core.Api;
import appeng.core.AppEng; import appeng.core.AppEng;
import appeng.items.parts.FacadeItem; import appeng.items.parts.FacadeItem;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
public final class FacadeRecipe extends SpecialRecipe { import javax.annotation.Nonnull;
public final class FacadeRecipe extends SpecialCraftingRecipe {
public static SpecialRecipeSerializer<FacadeRecipe> SERIALIZER = null; public static SpecialRecipeSerializer<FacadeRecipe> SERIALIZER = null;
private final IComparableDefinition anchor; private final IComparableDefinition anchor;
@@ -77,7 +76,7 @@ public final class FacadeRecipe extends SpecialRecipe {
} }
@Override @Override
public boolean canFit(int i, int i1) { public boolean fits(int i, int i1) {
return false; return false;
} }
@@ -90,7 +89,6 @@ public final class FacadeRecipe extends SpecialRecipe {
public static RecipeSerializer<FacadeRecipe> getSerializer(FacadeItem facade) { public static RecipeSerializer<FacadeRecipe> getSerializer(FacadeItem facade) {
if (SERIALIZER == null) { if (SERIALIZER == null) {
SERIALIZER = new SpecialRecipeSerializer<>(id -> new FacadeRecipe(id, facade)); SERIALIZER = new SpecialRecipeSerializer<>(id -> new FacadeRecipe(id, facade));
SERIALIZER.setRegistryName(new Identifier(AppEng.MOD_ID, "facade"));
} }
return SERIALIZER; return SERIALIZER;
} }
@@ -0,0 +1,47 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
/**
* This transformer simply overrides the alpha of the quad.
*
* @author covers1624
*/
public class QuadAlphaOverride implements RenderContext.QuadTransform {
private static final int INV_ALPHA_MASK = 0x00_FF_FF_FF;
private final int alphaOverride;
public QuadAlphaOverride(float alphaOverride) {
this.alphaOverride = (int) (alphaOverride * 255) << 24;
}
@Override
public boolean transform(MutableQuadView quad) {
for (int i = 0; i < 4; i++) {
int color = (quad.spriteColor(i, 0) & INV_ALPHA_MASK) | alphaOverride;
quad.spriteColor(i, 0, color);
}
return true;
}
}
@@ -0,0 +1,107 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
/**
* This transformer simply clamps the vertices inside the provided box. You
* probably want to Re-Interpolate the UV's, Color, and Lmap, see
* {@link QuadReInterpolator}
*
* @author covers1624
*/
public class QuadClamper implements RenderContext.QuadTransform {
private final Box clampBounds;
private final Vector3f pos = new Vector3f();
public QuadClamper(Box clampBounds) {
this.clampBounds = clampBounds;
}
@Override
public boolean transform(MutableQuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
clamp(quad, this.clampBounds);
// Check if the quad would be invisible and cull it.
float x1 = quad.posByIndex(0, dx(s));
float x2 = quad.posByIndex(1, dx(s));
float x3 = quad.posByIndex(2, dx(s));
float x4 = quad.posByIndex(3, dx(s));
float y1 = quad.posByIndex(0, dy(s));
float y2 = quad.posByIndex(1, dy(s));
float y3 = quad.posByIndex(2, dy(s));
float y4 = quad.posByIndex(3, dy(s));
// These comparisons are safe as we are comparing clamped values.
boolean flag1 = x1 == x2 && x2 == x3 && x3 == x4;
boolean flag2 = y1 == y2 && y2 == y3 && y3 == y4;
return !flag1 && !flag2;
}
private void clamp(MutableQuadView quad, Box bb) {
for (int i = 0; i < 4; i++) {
quad.copyPos(i, pos);
pos.set(
(float) MathHelper.clamp(pos.getX(), bb.minX, bb.maxX),
(float) MathHelper.clamp(pos.getY(), bb.minY, bb.maxY),
(float) MathHelper.clamp(pos.getZ(), bb.minZ, bb.maxZ)
);
quad.pos(i, pos);
}
}
/**
* Gets the 2d X coord for the given axis.
*
* @param s The axis. side >> 1
* @return The x coord.
*/
private static int dx(int s) {
if (s <= 1) {
return 0;
} else {
return 2;
}
}
/**
* Gets the 2d Y coord for the given axis.
*
* @param s The axis. side >> 1
* @return The y coord.
*/
private static int dy(int s) {
if (s > 0) {
return 1;
} else {
return 2;
}
}
}
@@ -18,17 +18,15 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers; package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import static net.minecraft.util.math.Direction.AxisDirection.NEGATIVE; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.AxisDirection; import net.minecraft.util.math.Direction.AxisDirection;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex; import static net.minecraft.util.math.Direction.AxisDirection.NEGATIVE;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory; import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/** /**
* This transformer is a little complicated. Basically a Facade / Cover can use * This transformer is a little complicated. Basically a Facade / Cover can use
@@ -40,31 +38,30 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
* *
* @author covers1624 * @author covers1624
*/ */
public class QuadCornerKicker extends QuadTransformer { public class QuadCornerKicker implements RenderContext.QuadTransform {
// The factory for pipeline creation. public static final QuadCornerKicker INSTANCE = new QuadCornerKicker();
public static final IPipelineElementFactory<QuadCornerKicker> FACTORY = QuadCornerKicker::new;
// Simple horizonal lookups. // Simple horizonal lookups.
public static int[][] horizonals = new int[][] { public static int[][] horizonals = new int[][]{
// Around Y axis, NSWE. // Around Y axis, NSWE.
{ 2, 3, 4, 5 }, // {2, 3, 4, 5}, //
{ 2, 3, 4, 5 }, // {2, 3, 4, 5}, //
// Around Z axis, DUWE. // Around Z axis, DUWE.
{ 0, 1, 4, 5 }, // {0, 1, 4, 5}, //
{ 0, 1, 4, 5 }, // {0, 1, 4, 5}, //
// Around X axis, DUNS. // Around X axis, DUNS.
{ 0, 1, 2, 3 }, // {0, 1, 2, 3}, //
{ 0, 1, 2, 3 } }; {0, 1, 2, 3}};
private int mySide; private int mySide;
private int facadeMask; private int facadeMask;
private Box box; private Box box;
private double thickness; private double thickness;
QuadCornerKicker() { public QuadCornerKicker() {
super(); super();
} }
@@ -107,27 +104,24 @@ public class QuadCornerKicker extends QuadTransformer {
} }
@Override @Override
public boolean transform() { public boolean transform(MutableQuadView quad) {
int side = quad.nominalFace().ordinal();
int side = this.quad.orientation.ordinal();
if (side != this.mySide && side != (this.mySide ^ 1)) { if (side != this.mySide && side != (this.mySide ^ 1)) {
for (int hoz : horizonals[this.mySide]) { for (int hoz : horizonals[this.mySide]) {
if (side != hoz && side != (hoz ^ 1)) { if (side != hoz && side != (hoz ^ 1)) {
if ((this.facadeMask & (1 << hoz)) != 0) { if ((this.facadeMask & (1 << hoz)) != 0) {
Corner corner = Corner.fromSides(this.mySide ^ 1, side, hoz); Corner corner = Corner.fromSides(this.mySide ^ 1, side, hoz);
for (Vertex vertex : this.quad.vertices) { for (int i = 0; i < 4; i++) {
float x = vertex.vec[0]; float x = quad.posByIndex(i, 0);
float y = vertex.vec[1]; float y = quad.posByIndex(i, 1);
float z = vertex.vec[2]; float z = quad.posByIndex(i, 2);
if (epsComp(x, corner.pX(this.box)) && epsComp(y, corner.pY(this.box)) if (epsComp(x, corner.pX(this.box)) && epsComp(y, corner.pY(this.box))
&& epsComp(z, corner.pZ(this.box))) { && epsComp(z, corner.pZ(this.box))) {
Vec3i vec = Direction.values()[hoz].getVector(); Vec3i vec = Direction.values()[hoz].getVector();
x -= vec.getX() * this.thickness; x -= vec.getX() * this.thickness;
y -= vec.getY() * this.thickness; y -= vec.getY() * this.thickness;
z -= vec.getZ() * this.thickness; z -= vec.getZ() * this.thickness;
vertex.vec[0] = x; quad.pos(i, x, y, z);
vertex.vec[1] = y;
vertex.vec[2] = z;
} }
} }
} }
@@ -150,7 +144,7 @@ public class QuadCornerKicker extends QuadTransformer {
private AxisDirection yAxis; private AxisDirection yAxis;
private AxisDirection zAxis; private AxisDirection zAxis;
private static final int[] sideMask = { 0, 2, 0, 1, 0, 4 }; private static final int[] sideMask = {0, 2, 0, 1, 0, 4};
Corner(AxisDirection xAxis, AxisDirection yAxis, AxisDirection zAxis) { Corner(AxisDirection xAxis, AxisDirection yAxis, AxisDirection zAxis) {
this.xAxis = xAxis; this.xAxis = xAxis;
@@ -167,7 +161,6 @@ public class QuadCornerKicker extends QuadTransformer {
* @param sideA Side one. * @param sideA Side one.
* @param sideB Side two. * @param sideB Side two.
* @param sideC Side three. * @param sideC Side three.
*
* @return The corner at the 3 sides. * @return The corner at the 3 sides.
*/ */
public static Corner fromSides(int sideA, int sideB, int sideC) { public static Corner fromSides(int sideA, int sideB, int sideC) {
@@ -187,4 +180,16 @@ public class QuadCornerKicker extends QuadTransformer {
return (float) (this.zAxis == NEGATIVE ? box.minZ : box.maxZ); return (float) (this.zAxis == NEGATIVE ? box.minZ : box.maxZ);
} }
} }
// Should be small enough.
private final static double EPSILON = 0.00001;
private static boolean epsComp(float a, float b) {
if (a == b) {
return true;
} else {
return Math.abs(a - b) < EPSILON;
}
}
} }
@@ -18,15 +18,13 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers; package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.util.math.Direction.AxisDirection;
import net.minecraft.util.math.Box; import net.minecraft.util.math.Box;
import net.minecraftforge.client.model.pipeline.IVertexConsumer; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.AxisDirection;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex; import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/** /**
* This transformer strips quads that are on faces. Simply set the bounds for * This transformer strips quads that are on faces. Simply set the bounds for
@@ -34,9 +32,7 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
* *
* @author covers1624 * @author covers1624
*/ */
public class QuadFaceStripper extends QuadTransformer { public class QuadFaceStripper implements RenderContext.QuadTransform {
public static final IPipelineElementFactory<QuadFaceStripper> FACTORY = QuadFaceStripper::new;
private Box bounds; private Box bounds;
private int mask; private int mask;
@@ -45,8 +41,7 @@ public class QuadFaceStripper extends QuadTransformer {
super(); super();
} }
public QuadFaceStripper(IVertexConsumer parent, Box bounds, int mask) { public QuadFaceStripper(Box bounds, int mask) {
super(parent);
this.bounds = bounds; this.bounds = bounds;
this.mask = mask; this.mask = mask;
} }
@@ -72,37 +67,37 @@ public class QuadFaceStripper extends QuadTransformer {
} }
@Override @Override
public boolean transform() { public boolean transform(MutableQuadView quad) {
if (this.mask == 0) { if (this.mask == 0) {
return true;// No mask, nothing changes. return true;// No mask, nothing changes.
} }
// If the bit for this quad is set, then check if we should strip. // If the bit for this quad is set, then check if we should strip.
if ((this.mask & (1 << this.quad.orientation.ordinal())) != 0) { Direction face = quad.nominalFace();
AxisDirection dir = this.quad.orientation.getAxisDirection(); if ((this.mask & (1 << face.ordinal())) != 0) {
Vertex[] vertices = this.quad.vertices; AxisDirection dir = face.getDirection();
switch (this.quad.orientation.getAxis()) { switch (face.getAxis()) {
case X: { case X: {
float bound = (float) (dir == POSITIVE ? this.bounds.maxX : this.bounds.minX); float bound = (float) (dir == POSITIVE ? this.bounds.maxX : this.bounds.minX);
float x1 = vertices[0].vec[0]; float x1 = quad.posByIndex(0, 0);
float x2 = vertices[1].vec[0]; float x2 = quad.posByIndex(1, 0);
float x3 = vertices[2].vec[0]; float x3 = quad.posByIndex(2, 0);
float x4 = vertices[3].vec[0]; float x4 = quad.posByIndex(3, 0);
return x1 != x2 || x2 != x3 || x3 != x4 || x4 != bound; return x1 != x2 || x2 != x3 || x3 != x4 || x4 != bound;
} }
case Y: { case Y: {
float bound = (float) (dir == POSITIVE ? this.bounds.maxY : this.bounds.minY); float bound = (float) (dir == POSITIVE ? this.bounds.maxY : this.bounds.minY);
float y1 = vertices[0].vec[1]; float y1 = quad.posByIndex(0, 1);
float y2 = vertices[1].vec[1]; float y2 = quad.posByIndex(1, 1);
float y3 = vertices[2].vec[1]; float y3 = quad.posByIndex(2, 1);
float y4 = vertices[3].vec[1]; float y4 = quad.posByIndex(3, 1);
return y1 != y2 || y2 != y3 || y3 != y4 || y4 != bound; return y1 != y2 || y2 != y3 || y3 != y4 || y4 != bound;
} }
case Z: { case Z: {
float bound = (float) (dir == POSITIVE ? this.bounds.maxZ : this.bounds.minZ); float bound = (float) (dir == POSITIVE ? this.bounds.maxZ : this.bounds.minZ);
float z1 = vertices[0].vec[2]; float z1 = quad.posByIndex(0, 2);
float z2 = vertices[1].vec[2]; float z2 = quad.posByIndex(1, 2);
float z3 = vertices[2].vec[2]; float z3 = quad.posByIndex(2, 2);
float z4 = vertices[3].vec[2]; float z4 = quad.posByIndex(3, 2);
return z1 != z2 || z2 != z3 || z3 != z4 || z4 != bound; return z1 != z2 || z2 != z3 || z3 != z4 || z4 != bound;
} }
} }
@@ -18,20 +18,17 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers; package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.util.math.Vector4f; import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.IVertexConsumer; import net.minecraft.util.math.Matrix4f;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/** /**
* Created by covers1624 on 2/6/20. * Created by covers1624 on 2/6/20.
*/ */
public class QuadMatrixTransformer extends QuadTransformer { public class QuadMatrixTransformer implements RenderContext.QuadTransform {
public static IPipelineElementFactory<QuadMatrixTransformer> FACTORY = QuadMatrixTransformer::new;
private static final Matrix4f identity; private static final Matrix4f identity;
static { static {
@@ -39,6 +36,7 @@ public class QuadMatrixTransformer extends QuadTransformer {
identity.loadIdentity(); identity.loadIdentity();
} }
private final Vector3f storage3 = new Vector3f();
private final Vector4f storage = new Vector4f(); private final Vector4f storage = new Vector4f();
private Matrix4f matrix; private Matrix4f matrix;
private boolean identityMatrix; private boolean identityMatrix;
@@ -47,8 +45,7 @@ public class QuadMatrixTransformer extends QuadTransformer {
super(); super();
} }
public QuadMatrixTransformer(IVertexConsumer parent, Matrix4f matrix) { public QuadMatrixTransformer(Matrix4f matrix) {
super(parent);
this.matrix = matrix; this.matrix = matrix;
this.identityMatrix = matrix.equals(identity); this.identityMatrix = matrix.equals(identity);
} }
@@ -59,26 +56,30 @@ public class QuadMatrixTransformer extends QuadTransformer {
} }
@Override @Override
public boolean transform() { public boolean transform(MutableQuadView quad) {
if (identityMatrix) { if (identityMatrix) {
return true; return true;
} }
for (Quad.Vertex vertex : this.quad.vertices) { for (int i = 0; i < 4; i++) {
storage.set(vertex.vec[0], vertex.vec[1], vertex.vec[2], 1); quad.copyPos(i, storage3);
storage.set(storage3.getX(), storage3.getY(), storage3.getZ(), 1);
storage.transform(matrix); storage.transform(matrix);
vertex.vec[0] = storage.getX(); quad.pos(i, storage.getX(), storage.getY(), storage.getZ());
vertex.vec[1] = storage.getY();
vertex.vec[2] = storage.getZ();
storage.set(vertex.normal[0], vertex.normal[1], vertex.normal[2], 0); if (quad.hasNormal(i)) {
storage.transform(matrix); quad.copyNormal(i, storage3);
storage.normalize(); storage.set(storage3.getX(), storage3.getY(), storage3.getZ(), 0);
vertex.normal[0] = storage.getX(); storage.transform(matrix);
vertex.normal[1] = storage.getY(); storage.normalize();
vertex.normal[2] = storage.getZ(); quad.normal(i, storage.getX(), storage.getY(), storage.getZ());
if (i == 0) {
Direction face = Direction.getFacing(storage.getX(), storage.getY(), storage.getZ());
quad.nominalFace(face);
quad.cullFace(face);
}
}
} }
Quad.Vertex v0 = quad.vertices[0];
quad.orientation = Direction.getFacing(v0.normal[0], v0.normal[1], v0.normal[2]);
return true; return true;
} }
} }
@@ -0,0 +1,180 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import appeng.thirdparty.codechicken.lib.math.InterpHelper;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
/**
* This transformer Re-Interpolates the Color, UV's and LightMaps. Use this
* after all transformations that translate vertices in the pipeline.
* <p>
* This Transformation can only be used in the BakedPipeline.
*
* @author covers1624
*/
public class QuadReInterpolator implements RenderContext.QuadTransform {
private final InterpHelper interpHelper = new InterpHelper();
private final MutableQuadViewImpl bufferQuad = new MutableQuadViewImpl() {
{
data = new int[EncodingFormat.TOTAL_STRIDE];
}
@Override
public QuadEmitter emit() {
throw new UnsupportedOperationException();
}
};
public QuadReInterpolator() {
super();
}
public void setInputQuad(QuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
int xIdx = dx(s);
int yIdx = dy(s);
interpHelper.reset( //
quad.posByIndex(0, xIdx), quad.posByIndex(0, yIdx), //
quad.posByIndex(1, xIdx), quad.posByIndex(1, yIdx), //
quad.posByIndex(2, xIdx), quad.posByIndex(2, yIdx), //
quad.posByIndex(3, xIdx), quad.posByIndex(3, yIdx));
quad.copyTo(bufferQuad);
}
@Override
public boolean transform(MutableQuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
int xIdx = dx(s);
int yIdx = dy(s);
this.interpHelper.setup();
for (int i = 0; i < 4; i++) {
float x = quad.posByIndex(i, xIdx);
float y = quad.posByIndex(i, yIdx);
this.interpHelper.locate(x, y);
interpColorFrom(quad, i);
interpUVFrom(quad, i);
interpLightMapFrom(quad, i);
}
return true;
}
/**
* Interpolates the new color values for this Vertex using the others as a
* reference.
*/
public void interpColorFrom(MutableQuadView quad, int vertexIndex) {
int p1 = bufferQuad.spriteColor(0, 0);
int p2 = bufferQuad.spriteColor(1, 0);
int p3 = bufferQuad.spriteColor(2, 0);
int p4 = bufferQuad.spriteColor(3, 0);
if (p1 == p2 && p2 == p3 && p3 == p4) {
return; // Don't bother for uniformly colored quads
}
// Interpolate each color component separately
int color = 0;
int mask = 0xFF;
for (int i = 0; i < 4; i++) {
float p1c = (float) (p1 & mask);
float p2c = (float) (p2 & mask);
float p3c = (float) (p3 & mask);
float p4c = (float) (p4 & mask);
int interp = (int) interpHelper.interpolate(p1c, p2c, p3c, p4c);
color |= interp & mask;
mask <<= 8;
}
quad.spriteColor(vertexIndex, 0, color);
}
/**
* Interpolates the new UV values for this Vertex using the others as a
* reference.
*/
public void interpUVFrom(MutableQuadView quad, int vertexIndex) {
float p1 = bufferQuad.spriteU(0, 0);
float p2 = bufferQuad.spriteU(1, 0);
float p3 = bufferQuad.spriteU(2, 0);
float p4 = bufferQuad.spriteU(3, 0);
float u = interpHelper.interpolate(p1, p2, p3, p4);
p1 = bufferQuad.spriteV(0, 0);
p2 = bufferQuad.spriteV(1, 0);
p3 = bufferQuad.spriteV(2, 0);
p4 = bufferQuad.spriteV(3, 0);
float v = interpHelper.interpolate(p1, p2, p3, p4);
quad.sprite(vertexIndex, 0, u, v);
}
/**
* Interpolates the new LightMap values for this Vertex using the others as a
* reference.
*
* @return The same Vertex.
*/
public void interpLightMapFrom(MutableQuadView quad, int vertexIndex) {
for (int e = 0; e < 2; e++) {
// FIXME float p1 = others[0].lightmap[e];
// FIXME float p2 = others[1].lightmap[e];
// FIXME float p3 = others[2].lightmap[e];
// FIXME float p4 = others[3].lightmap[e];
// FIXME if (p1 != p2 || p2 != p3 || p3 != p4) {
// FIXME this.lightmap[e] = interpHelper.interpolate(p1, p2, p3, p4);
// FIXME }
}
}
/**
* Gets the 2d X coord for the given axis.
*
* @param s The axis. side >> 1
* @return The x coord.
*/
private static int dx(int s) {
if (s <= 1) {
return 0;
} else {
return 2;
}
}
/**
* Gets the 2d Y coord for the given axis.
*
* @param s The axis. side >> 1
* @return The y coord.
*/
private static int dy(int s) {
if (s > 0) {
return 1;
} else {
return 2;
}
}
}
@@ -18,11 +18,9 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers; package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraftforge.client.model.pipeline.IVertexConsumer; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/** /**
* This transformer tints quads.. Feed it the output of * This transformer tints quads.. Feed it the output of
@@ -30,9 +28,7 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
* *
* @author covers1624 * @author covers1624
*/ */
public class QuadTinter extends QuadTransformer { public class QuadTinter implements RenderContext.QuadTransform {
public static final IPipelineElementFactory<QuadTinter> FACTORY = QuadTinter::new;
private int tint; private int tint;
@@ -40,9 +36,8 @@ public class QuadTinter extends QuadTransformer {
super(); super();
} }
public QuadTinter(IVertexConsumer consumer, int tint) { public QuadTinter(int tint) {
super(consumer); this.tint = tint | 0xFF000000;
this.tint = tint;
} }
public QuadTinter setTint(int tint) { public QuadTinter setTint(int tint) {
@@ -51,18 +46,13 @@ public class QuadTinter extends QuadTransformer {
} }
@Override @Override
public boolean transform() { public boolean transform(MutableQuadView quad) {
// Nuke tintIndex. // Nuke tintIndex.
this.quad.tintIndex = -1; quad.colorIndex(-1);
if (this.format.hasColor) { for (int i = 0; i < 4; i++) {
float r = (this.tint >> 0x10 & 0xFF) / 255F; int color = quad.spriteColor(i, 0);
float g = (this.tint >> 0x08 & 0xFF) / 255F; color = ColorHelper.multiplyColor(color, tint);
float b = (this.tint & 0xFF) / 255F; quad.spriteColor(i, 0, color);
for (Vertex v : this.quad.vertices) {
v.color[0] *= r;
v.color[1] *= g;
v.color[2] *= b;
}
} }
return true; return true;
} }
@@ -24,9 +24,7 @@ import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Optional; import java.util.Optional;
import appeng.util.BlockUpdateFlag;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
@@ -251,15 +249,15 @@ public class CraftingBlockEntity extends AENetworkBlockEntity
final LinkedList<BlockPos> places = new LinkedList<>(); final LinkedList<BlockPos> places = new LinkedList<>();
final Iterator<CraftingTileEntity> i = this.cluster.getTiles(); final Iterator<CraftingBlockEntity> i = this.cluster.getTiles();
while (i.hasNext()) { while (i.hasNext()) {
final CraftingTileEntity h = i.next(); final CraftingBlockEntity h = i.next();
if (h == this) { if (h == this) {
places.add(pos); places.add(pos);
} else { } else {
for (Direction d : Direction.values()) { for (Direction d : Direction.values()) {
BlockPos p = h.pos.offset(d); BlockPos p = h.pos.offset(d);
if (this.world.isAirBlock(p)) { if (this.world.isAir(p)) {
places.add(p); places.add(p);
} }
} }
@@ -50,8 +50,8 @@ import appeng.core.AppEng;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAssemblerBlockEntity> { public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAssemblerBlockEntity> {
public static final Identifier LIGHTS_MODEL = new Identifier(AppEng.MOD_ID, public static final ModelIdentifier LIGHTS_MODEL = new ModelIdentifier(AppEng.makeId(
"block/molecular_assembler_lights"); "block/molecular_assembler_lights"), "");
private static final RenderLayer MC_161917_RENDERTYPE_FIX = createRenderType(); private static final RenderLayer MC_161917_RENDERTYPE_FIX = createRenderType();
@@ -93,7 +93,7 @@ public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAss
// even the fully transparent part) // even the fully transparent part)
// https://bugs.mojang.com/browse/MC-161917 // https://bugs.mojang.com/browse/MC-161917
MinecraftClient minecraft = MinecraftClient.getInstance(); MinecraftClient minecraft = MinecraftClient.getInstance();
BakedModel lightsModel = minecraft.getBakedModelManager().getModel(new ModelIdentifier(LIGHTS_MODEL, "")); BakedModel lightsModel = minecraft.getBakedModelManager().getModel(LIGHTS_MODEL);
VertexConsumer buffer = bufferIn.getBuffer(MC_161917_RENDERTYPE_FIX); VertexConsumer buffer = bufferIn.getBuffer(MC_161917_RENDERTYPE_FIX);
minecraft.getBlockRenderManager().getModelRenderer().render(ms.peek(), buffer, null, minecraft.getBlockRenderManager().getModelRenderer().render(ms.peek(), buffer, null,
@@ -53,6 +53,7 @@ import appeng.api.util.AEColor;
import appeng.api.util.IConfigManager; import appeng.api.util.IConfigManager;
import appeng.container.implementations.MEMonitorableContainer; import appeng.container.implementations.MEMonitorableContainer;
import appeng.core.Api; import appeng.core.Api;
import appeng.fluids.container.FluidTerminalContainer;
import appeng.fluids.util.AEFluidStack; import appeng.fluids.util.AEFluidStack;
import appeng.helpers.IPriorityHost; import appeng.helpers.IPriorityHost;
import appeng.me.GridAccessException; import appeng.me.GridAccessException;
@@ -782,8 +783,7 @@ public class ChestBlockEntity extends AENetworkPowerBlockEntity
} }
if (this.cellHandler.getChannel() == Api.instance().storage() if (this.cellHandler.getChannel() == Api.instance().storage()
.getStorageChannel(IFluidStorageChannel.class)) { .getStorageChannel(IFluidStorageChannel.class)) {
throw new IllegalStateException(); return FluidTerminalContainer.TYPE;
// FIXME FABRIC return FluidTerminalContainer.TYPE;
} }
} }
return null; return null;
@@ -39,6 +39,9 @@ import net.minecraft.util.math.Direction;
*/ */
public abstract class InventoryAdaptor implements Iterable<ItemSlot> { public abstract class InventoryAdaptor implements Iterable<ItemSlot> {
public static InventoryAdaptor getAdaptor(final BlockEntity te, final Direction d) { public static InventoryAdaptor getAdaptor(final BlockEntity te, final Direction d) {
if (te == null) {
return null;
}
FixedItemInv inv = ItemAttributes.FIXED_INV.get(te.getWorld(), te.getPos(), SearchOptions.inDirection(d.getOpposite())); FixedItemInv inv = ItemAttributes.FIXED_INV.get(te.getWorld(), te.getPos(), SearchOptions.inDirection(d.getOpposite()));
if (inv == ItemAttributes.FIXED_INV.defaultValue) { if (inv == ItemAttributes.FIXED_INV.defaultValue) {
@@ -671,7 +671,7 @@
"item.appliedenergistics2.yellow_paint_ball": "Yellow Paint Ball", "item.appliedenergistics2.yellow_paint_ball": "Yellow Paint Ball",
"item.appliedenergistics2.yellow_smart_cable": "Yellow ME Smart Cable", "item.appliedenergistics2.yellow_smart_cable": "Yellow ME Smart Cable",
"item.appliedenergistics2.yellow_smart_dense_cable": "Yellow ME Dense Smart Cable", "item.appliedenergistics2.yellow_smart_dense_cable": "Yellow ME Dense Smart Cable",
"itemGroup.appliedenergistics2": "Applied Energistics 2", "itemGroup.appliedenergistics2.main": "Applied Energistics 2",
"itemGroup.appliedenergistics2.facades": "Applied Energistics 2 - Facades", "itemGroup.appliedenergistics2.facades": "Applied Energistics 2 - Facades",
"key.appliedenergistics2.category": "Applied Energistics 2", "key.appliedenergistics2.category": "Applied Energistics 2",
"key.toggle_focus.desc": "Toggle search box focus", "key.toggle_focus.desc": "Toggle search box focus",
@@ -1,3 +0,0 @@
{
"loader": "appliedenergistics2:facade"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_formation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_formation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/formation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/formation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/identity_annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/identity_annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,3 +0,0 @@
{
"loader": "appliedenergistics2:p2p_tunnel_frequency"
}
@@ -12,7 +12,7 @@
"item": "minecraft:stone" "item": "minecraft:stone"
}, },
"d": { "d": {
"item": "minecraft:cobblestone" "tag": "minecraft:stone_tool_materials"
}, },
"b": { "b": {
"tag": "appliedenergistics2:gears/wooden" "tag": "appliedenergistics2:gears/wooden"
@@ -1,93 +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.client.render;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
public abstract class DelegateBakedModel implements BakedModel {
private final BakedModel baseModel;
protected DelegateBakedModel(BakedModel base) {
this.baseModel = base;
}
@Override
@Deprecated
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return baseModel.getQuads(state, side, rand);
}
@Override
public boolean isSideLit() {
return baseModel.isSideLit();
}
@Override
public ModelOverrideList getOverrides() {
return baseModel.getOverrides();
}
@Override
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
baseModel.handlePerspective(cameraTransformType, mat);
return this;
}
@Override
public Sprite getSprite() {
return this.baseModel.getSprite();
}
@Override
public ModelTransformation getTransformation() {
return this.baseModel.getTransformation();
}
@Override
public boolean useAmbientOcclusion() {
return this.baseModel.useAmbientOcclusion();
}
@Override
public boolean hasDepth() {
return this.baseModel.hasDepth();
}
@Override
public boolean isBuiltin() {
return this.baseModel.isBuiltin();
}
public BakedModel getBaseModel() {
return this.baseModel;
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import net.minecraftforge.client.model.ItemLayerModel;
import net.minecraftforge.fluids.FluidAttributes;
import appeng.fluids.items.FluidDummyItem;
/**
* This baked model class is used as a dispatcher to redirect the renderer to
* the *real* model that should be used based on the item stack. A custom Item
* Override List is used to accomplish this.
*/
public class DummyFluidDispatcherBakedModel extends DelegateBakedModel {
private final Function<SpriteIdentifier, Sprite> bakedTextureGetter;
public DummyFluidDispatcherBakedModel(BakedModel baseModel,
Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
super(baseModel);
this.bakedTextureGetter = bakedTextureGetter;
}
// This is never used. See the item override list below.
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return Collections.emptyList();
}
@Override
public boolean hasDepth() {
return this.getBaseModel().hasDepth();
}
@Override
public boolean isSideLit() {
return getBaseModel().isSideLit();
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public ModelOverrideList getOverrides() {
return new ModelOverrideList() {
@Override
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
if (!(stack.getItem() instanceof FluidDummyItem)) {
return originalModel;
}
FluidDummyItem itemFacade = (FluidDummyItem) stack.getItem();
FluidVolume fluidStack = itemFacade.getFluidStack(stack);
if (fluidStack.isEmpty()) {
fluidStack = new FluidVolume(Fluids.WATER, FluidAttributes.BUCKET_VOLUME);
}
FluidAttributes attributes = fluidStack.getFluidKey().getAttributes();
Identifier stillTexture = attributes.getStillTexture(fluidStack);
SpriteIdentifier stillMaterial = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, stillTexture);
Sprite sprite = DummyFluidDispatcherBakedModel.this.bakedTextureGetter.apply(stillMaterial);
if (sprite == null) {
return new DummyFluidBakedModel(ImmutableList.of());
}
return new DummyFluidBakedModel(
ItemLayerModel.getQuadsForSprite(0, sprite, AffineTransformation.identity()));
}
};
}
}
@@ -1,46 +0,0 @@
package appeng.client.render.cablebus;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "parts/p2p_tunnel_frequency"));
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
try {
final Sprite texture = spriteGetter.apply(TEXTURE);
return new P2PTunnelFrequencyBakedModel(texture);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.singleton(TEXTURE);
}
}
@@ -1,134 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.List;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
/**
* Applies an arbitrary transformation matrix to the vertices of a quad.
*/
final class MatrixVertexTransformer extends QuadGatheringTransformer {
private final Matrix4f transform;
public MatrixVertexTransformer(Matrix4f transform) {
this.transform = transform;
}
@Override
protected void processQuad() {
VertexFormat format = this.parent.getVertexFormat();
List<VertexFormatElement> elements = format.getElements();
int count = elements.size();
for (int v = 0; v < 4; v++) {
for (int e = 0; e < count; e++) {
VertexFormatElement element = elements.get(e);
if (element.getType() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v], element.getElementCount()));
} else if (element.getType() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
}
}
}
}
@Override
public void setQuadTint(int tint) {
this.parent.setQuadTint(tint);
}
@Override
public void setQuadOrientation(Direction orientation) {
this.parent.setQuadOrientation(orientation);
}
@Override
public void setApplyDiffuseLighting(boolean diffuse) {
this.parent.setApplyDiffuseLighting(diffuse);
}
@Override
public void setTexture(Sprite texture) {
this.parent.setTexture(texture);
}
private float[] transform(float[] fs, int elemCount) {
switch (fs.length) {
case 3:
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
// Otherwise all translation is lost
if (elemCount == 3) {
vecc.setW(1);
}
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.transform);
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
default:
return fs;
}
}
private float[] transformNormal(float[] fs) {
Vector4f normal;
switch (fs.length) {
case 3:
normal = new Vector4f(fs[0], fs[1], fs[2], 0);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ() };
case 4:
normal = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ(), normal.getW() };
default:
return fs;
}
}
}
@@ -1,302 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, 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.core;
import appeng.bootstrap.ModelsReloadCallback;
import appeng.client.render.model.*;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.*;
import net.minecraft.client.gui.ScreenManager;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import net.minecraft.world.gen.placement.CountRangeConfig;
import net.minecraft.world.gen.placement.IPlacementConfig;
import net.minecraft.world.gen.placement.Placement;
import appeng.core.Api;
import appeng.api.config.Upgrades;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IItems;
import appeng.api.definitions.IParts;
import appeng.api.features.AEFeature;
import appeng.api.features.IRegistryContainer;
import appeng.api.features.IWirelessTermHandler;
import appeng.api.features.IWorldGen;
import appeng.api.movable.IMovableRegistry;
import appeng.core.features.registries.P2PTunnelRegistry;
import appeng.core.localization.GuiText;
import appeng.core.stats.AdvancementTriggers;
import appeng.server.AECommand;
import appeng.spatial.StorageCellBiome;
import appeng.spatial.StorageCellModDimension;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.crafting.MolecularAssemblerRenderer;
import appeng.worldgen.ChargedQuartzOreConfig;
import appeng.worldgen.ChargedQuartzOreFeature;
import appeng.worldgen.meteorite.MeteoriteStructure;
final class Registration {
public Registration() {
}
AdvancementTriggers advancementTriggers;
@Environment(EnvType.CLIENT)
public void modelRegistryEvent(ModelRegistryEvent event) {
registerSpecialModels();
}
/**
* Registers any JSON model files with Minecraft that are not referenced via
* blockstates or item IDs
*/
@Environment(EnvType.CLIENT)
private void registerSpecialModels() {
SkyCompassModel.DEPENDENCIES.forEach(ModelLoader::addSpecialModel);
ModelLoader.addSpecialModel(BiometricCardModel.MODEL_BASE);
ModelLoader.addSpecialModel(MemoryCardModel.MODEL_BASE);
DriveModel.DEPENDENCIES.forEach(ModelLoader::addSpecialModel);
ModelLoader.addSpecialModel(MolecularAssemblerRenderer.LIGHTS_MODEL);
}
// FIXME LATER
public static void postInit() {
final IRegistryContainer registries = AEApi.instance().registries();
// TODO: Do not use the internal API
ApiDefinitions definitions = Api.INSTANCE.definitions();
final IParts parts = definitions.parts();
final IBlocks blocks = definitions.blocks();
final IItems items = definitions.items();
// Block and part interface have different translation keys, but support the
// same upgrades
Text interfaceGroup = parts.iface().asItem().getName();
Text itemIoBusGroup = GuiText.IOBuses.text();
Text fluidIoBusGroup = GuiText.IOBusesFluids.text();
Text storageCellGroup = GuiText.IOBusesFluids.text();
// default settings..
((P2PTunnelRegistry) registries.p2pTunnel()).configure();
// Interface
Upgrades.CRAFTING.registerItem(parts.iface(), 1, interfaceGroup);
Upgrades.CRAFTING.registerItem(blocks.iface(), 1, interfaceGroup);
// IO Port!
Upgrades.SPEED.registerItem(blocks.iOPort(), 3);
Upgrades.REDSTONE.registerItem(blocks.iOPort(), 1);
// Level Emitter!
Upgrades.FUZZY.registerItem(parts.levelEmitter(), 1);
Upgrades.CRAFTING.registerItem(parts.levelEmitter(), 1);
// Import Bus
Upgrades.FUZZY.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.importBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.importBus(), 4, itemIoBusGroup);
// Fluid Import Bus
Upgrades.CAPACITY.registerItem(parts.fluidImportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidImportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidImportBus(), 4, fluidIoBusGroup);
// Export Bus
Upgrades.FUZZY.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.exportBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.exportBus(), 4, itemIoBusGroup);
Upgrades.CRAFTING.registerItem(parts.exportBus(), 1, itemIoBusGroup);
// Fluid Export Bus
Upgrades.CAPACITY.registerItem(parts.fluidExportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidExportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidExportBus(), 4, fluidIoBusGroup);
// Storage Cells
Upgrades.FUZZY.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.viewCell(), 1);
Upgrades.INVERTER.registerItem(items.viewCell(), 1);
// Storage Bus
Upgrades.FUZZY.registerItem(parts.storageBus(), 1);
Upgrades.INVERTER.registerItem(parts.storageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.storageBus(), 5);
// Storage Bus Fluids
Upgrades.INVERTER.registerItem(parts.fluidStorageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.fluidStorageBus(), 5);
// Formation Plane
Upgrades.FUZZY.registerItem(parts.formationPlane(), 1);
Upgrades.INVERTER.registerItem(parts.formationPlane(), 1);
Upgrades.CAPACITY.registerItem(parts.formationPlane(), 5);
// Matter Cannon
Upgrades.FUZZY.registerItem(items.massCannon(), 1);
Upgrades.INVERTER.registerItem(items.massCannon(), 1);
Upgrades.SPEED.registerItem(items.massCannon(), 4);
// Molecular Assembler
Upgrades.SPEED.registerItem(blocks.molecularAssembler(), 5);
// Inscriber
Upgrades.SPEED.registerItem(blocks.inscriber(), 3);
// Wireless Terminal Handler
items.wirelessTerminal().maybeItem()
.ifPresent(terminal -> registries.wireless().registerWirelessHandler((IWirelessTermHandler) terminal));
// Charge Rates
items.chargedStaff().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 320d));
items.portableCell().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 800d));
items.colorApplicator().maybeItem()
.ifPresent(colorApplicator -> registries.charger().addChargeRate(colorApplicator, 800d));
items.wirelessTerminal().maybeItem().ifPresent(terminal -> registries.charger().addChargeRate(terminal, 8000d));
items.entropyManipulator().maybeItem()
.ifPresent(entropyManipulator -> registries.charger().addChargeRate(entropyManipulator, 8000d));
items.massCannon().maybeItem().ifPresent(massCannon -> registries.charger().addChargeRate(massCannon, 8000d));
blocks.energyCell().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 8000d));
blocks.energyCellDense().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 16000d));
// FIXME // add villager trading to black smiths for a few basic materials
// FIXME if( AEConfig.instance().isFeatureEnabled( AEFeature.VILLAGER_TRADING ) )
// FIXME {
// FIXME // TODO: VILLAGER TRADING
// FIXME // VillagerRegistry.instance().getRegisteredVillagers().registerVillageTradeHandler( 3, new AETrading() );
// FIXME }
final IMovableRegistry mr = registries.movable();
/*
* You can't move bed rock.
*/
mr.blacklistBlock(net.minecraft.block.Blocks.BEDROCK);
/*
* White List Vanilla...
*/
mr.whiteListBlockEntity(BannerBlockEntity.class);
mr.whiteListBlockEntity(BeaconBlockEntity.class);
mr.whiteListBlockEntity(BrewingStandBlockEntity.class);
mr.whiteListBlockEntity(ChestBlockEntity.class);
mr.whiteListBlockEntity(CommandBlockBlockEntity.class);
mr.whiteListBlockEntity(ComparatorBlockEntity.class);
mr.whiteListBlockEntity(DaylightDetectorBlockEntity.class);
mr.whiteListBlockEntity(DispenserBlockEntity.class);
mr.whiteListBlockEntity(DropperBlockEntity.class);
mr.whiteListBlockEntity(EnchantingTableBlockEntity.class);
mr.whiteListBlockEntity(EnderChestBlockEntity.class);
mr.whiteListBlockEntity(EndPortalBlockEntity.class);
mr.whiteListBlockEntity(FurnaceBlockEntity.class);
mr.whiteListBlockEntity(HopperBlockEntity.class);
mr.whiteListBlockEntity(MobSpawnerBlockEntity.class);
mr.whiteListBlockEntity(PistonBlockEntity.class);
mr.whiteListBlockEntity(ShulkerBoxBlockEntity.class);
mr.whiteListBlockEntity(SignBlockEntity.class);
mr.whiteListBlockEntity(SkullBlockEntity.class);
/*
* Whitelist AE2
*/
mr.whiteListBlockEntity(AEBaseBlockEntity.class);
/*
* world gen
*/
for (final IWorldGen.WorldGenType type : IWorldGen.WorldGenType.values()) {
// FIXME: registries.worldgen().disableWorldGenForProviderID( type,
// StorageWorldProvider.class );
registries.worldgen().disableWorldGenForDimension(type, DimensionType.THE_NETHER_REGISTRY_KEY.getValue());
}
// whitelist from config
for (final String dimension : AEConfig.instance().getMeteoriteDimensionWhitelist()) {
registries.worldgen().enableWorldGenForDimension(IWorldGen.WorldGenType.METEORITES,
new Identifier(dimension));
}
Biome.BIOMES.forEach(b -> {
addMeteoriteWorldGen(b);
addQuartzWorldGen(b);
});
}
public void registerWorldGen(RegistryEvent.Register<Feature<?>> evt) {
IForgeRegistry<Feature<?>> r = evt.getRegistry();
// r.register(MeteoriteWorldGen.INSTANCE);
r.register(MeteoriteStructure.INSTANCE);
r.register(ChargedQuartzOreFeature.INSTANCE);
}
public void registerBiomes(RegistryEvent.Register<Biome> evt) {
evt.getRegistry().register(StorageCellBiome.INSTANCE);
}
public void registerModDimension(RegistryEvent.Register<ModDimension> evt) {
evt.getRegistry().register(StorageCellModDimension.INSTANCE);
}
public void registerCommands(final FMLServerStartingEvent evt) {
new AECommand().register(evt.getCommandDispatcher());
}
@Environment(EnvType.CLIENT)
public void registerClientEvents() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::registerParticleFactories);
modEventBus.addListener(this::registerTextures);
modEventBus.addListener(this::modelRegistryEvent);
modEventBus.addListener(this::registerItemColors);
ModelsReloadCallback.EVENT.register(this::onModelsReloaded);
}
}
@@ -1,28 +0,0 @@
package appeng.parts.automation;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelLoader;
public class PlaneModelLoader implements IModelLoader<PlaneModel> {
public static final PlaneModelLoader INSTANCE = new PlaneModelLoader();
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
}
@Override
public PlaneModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
String frontTexture = modelContents.get("front").getAsString();
String sidesTexture = modelContents.get("sides").getAsString();
String backTexture = modelContents.get("back").getAsString();
return new PlaneModel(new Identifier(frontTexture), new Identifier(sidesTexture),
new Identifier(backTexture));
}
}
@@ -18,14 +18,14 @@
package appeng.thirdparty.codechicken.lib.model; package appeng.thirdparty.codechicken.lib.model;
import net.minecraftforge.client.model.pipeline.IVertexConsumer; import appeng.thirdparty.codechicken.lib.model.pipeline.VertexConsumer;
/** /**
* Marks a standard IVertexConsumer as compatible with {@link Quad}. * Marks a standard IVertexConsumer as compatible with {@link Quad}.
* *
* @author covers1624 * @author covers1624
*/ */
public interface ISmartVertexConsumer extends IVertexConsumer { public interface ISmartVertexConsumer extends VertexConsumer {
/** /**
* Assumes the data is already completely unpacked. You must always copy the * Assumes the data is already completely unpacked. You must always copy the
@@ -18,6 +18,8 @@
package appeng.thirdparty.codechicken.lib.model; package appeng.thirdparty.codechicken.lib.model;
import appeng.thirdparty.codechicken.lib.model.pipeline.VertexConsumer;
import appeng.thirdparty.codechicken.lib.model.pipeline.VertexProducer;
import net.minecraft.client.render.VertexFormats; import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.Vector3f; import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.BakedQuad;
@@ -26,9 +28,6 @@ import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Box; import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.IVertexProducer;
import net.minecraftforge.client.model.pipeline.LightUtil;
import appeng.thirdparty.codechicken.lib.math.InterpHelper; import appeng.thirdparty.codechicken.lib.math.InterpHelper;
@@ -38,7 +37,7 @@ import appeng.thirdparty.codechicken.lib.math.InterpHelper;
* *
* @author covers1624 * @author covers1624
*/ */
public class Quad implements IVertexProducer, ISmartVertexConsumer { public class Quad implements VertexProducer, ISmartVertexConsumer {
public CachedFormat format; public CachedFormat format;
@@ -127,7 +126,7 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
} }
@Override @Override
public void pipe(IVertexConsumer consumer) { public void pipe(VertexConsumer consumer) {
if (consumer instanceof ISmartVertexConsumer) { if (consumer instanceof ISmartVertexConsumer) {
((ISmartVertexConsumer) consumer).put(this); ((ISmartVertexConsumer) consumer).put(this);
} else { } else {
@@ -175,19 +174,23 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
this.calculateOrientation(true); this.calculateOrientation(true);
} }
private static void setVector(Vector3f to, float[] from) {
to.set(from[0], from[1], from[2]);
}
/** /**
* Re-calculates the Orientation of this quad, optionally the normal vector. * Re-calculates the Orientation of this quad, optionally the normal vector.
* *
* @param setNormal If the normal vector should be updated. * @param setNormal If the normal vector should be updated.
*/ */
public void calculateOrientation(boolean setNormal) { public void calculateOrientation(boolean setNormal) {
this.v1.set(this.vertices[3].vec); setVector(this.v1, this.vertices[3].vec);
this.t.set(this.vertices[1].vec); setVector(this.t, this.vertices[1].vec);
this.v1.sub(this.t); this.v1.subtract(this.t);
this.v2.set(this.vertices[2].vec); setVector(this.v2, this.vertices[2].vec);
this.t.set(this.vertices[0].vec); setVector(this.t, this.vertices[0].vec);
this.v2.sub(this.t); this.v2.subtract(this.t);
this.normal.set(this.v2.getX(), this.v2.getY(), this.v2.getZ()); this.normal.set(this.v2.getX(), this.v2.getY(), this.v2.getZ());
this.normal.cross(this.v1); this.normal.cross(this.v1);
@@ -278,10 +281,10 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
if (format.format != VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL) { if (format.format != VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL) {
throw new IllegalStateException("Unable to bake this quad to the specified format. " + format.format); throw new IllegalStateException("Unable to bake this quad to the specified format. " + format.format);
} }
int[] packedData = new int[this.format.format.getSize()]; int[] packedData = new int[this.format.format.getVertexSizeInteger()];
for (int v = 0; v < 4; v++) { for (int v = 0; v < 4; v++) {
for (int e = 0; e < this.format.elementCount; e++) { for (int e = 0; e < this.format.elementCount; e++) {
LightUtil.pack(this.vertices[v].raw[e], packedData, this.format.format, v, e); // FIXME FABRIC LightUtil.pack(this.vertices[v].raw[e], packedData, this.format.format, v, e);
} }
} }
return new BakedQuad(packedData, this.tintIndex, this.orientation, this.sprite, this.diffuseLighting); return new BakedQuad(packedData, this.tintIndex, this.orientation, this.sprite, this.diffuseLighting);
@@ -0,0 +1,14 @@
package appeng.thirdparty.codechicken.lib.model.pipeline;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
public interface VertexConsumer {
VertexFormat getVertexFormat();
void setQuadTint(int tint);
void setQuadOrientation(Direction orientation);
void setApplyDiffuseLighting(boolean diffuse);
void setTexture(Sprite texture);
void put(int element, float... data);
}
@@ -0,0 +1,5 @@
package appeng.thirdparty.codechicken.lib.model.pipeline;
public interface VertexProducer {
void pipe(VertexConsumer consumer);
}
@@ -1,62 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer simply overrides the alpha of the quad. Only operates if the
* format has color.
*
* @author covers1624
*/
public class QuadAlphaOverride extends QuadTransformer {
public static final IPipelineElementFactory<QuadAlphaOverride> FACTORY = QuadAlphaOverride::new;
private float alphaOverride;
QuadAlphaOverride() {
super();
}
public QuadAlphaOverride(IVertexConsumer consumer, float alphaOverride) {
super(consumer);
this.alphaOverride = alphaOverride;
}
public QuadAlphaOverride setAlphaOverride(float alphaOverride) {
this.alphaOverride = alphaOverride;
return this;
}
@Override
public boolean transform() {
if (this.format.hasColor) {
for (Vertex v : this.quad.vertices) {
v.color[3] = this.alphaOverride;
}
}
return true;
}
}
@@ -1,77 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraft.util.math.Box;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer simply clamps the vertices inside the provided box. You
* probably want to Re-Interpolate the UV's, Color, and Lmap, see
* {@link QuadReInterpolator}
*
* @author covers1624
*/
public class QuadClamper extends QuadTransformer {
public static IPipelineElementFactory<QuadClamper> FACTORY = QuadClamper::new;
private Box clampBounds;
QuadClamper() {
super();
}
public QuadClamper(IVertexConsumer parent, Box bounds) {
super(parent);
this.clampBounds = bounds;
}
public void setClampBounds(Box bounds) {
this.clampBounds = bounds;
}
@Override
public boolean transform() {
int s = this.quad.orientation.ordinal() >> 1;
this.quad.clamp(this.clampBounds);
// Check if the quad would be invisible and cull it.
Vertex[] vertices = this.quad.vertices;
float x1 = vertices[0].dx(s);
float x2 = vertices[1].dx(s);
float x3 = vertices[2].dx(s);
float x4 = vertices[3].dx(s);
float y1 = vertices[0].dy(s);
float y2 = vertices[1].dy(s);
float y3 = vertices[2].dy(s);
float y4 = vertices[3].dy(s);
// These comparisons are safe as we are comparing clamped values.
boolean flag1 = x1 == x2 && x2 == x3 && x3 == x4;
boolean flag2 = y1 == y2 && y2 == y3 && y3 == y4;
return !flag1 && !flag2;
}
}
@@ -1,80 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib 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 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib 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 CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import appeng.thirdparty.codechicken.lib.math.InterpHelper;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer Re-Interpolates the Color, UV's and LightMaps. Use this
* after all transformations that translate vertices in the pipeline.
*
* This Transformation can only be used in the BakedPipeline.
*
* @author covers1624
*/
public class QuadReInterpolator extends QuadTransformer {
public static final IPipelineElementFactory<QuadReInterpolator> FACTORY = QuadReInterpolator::new;
private Quad interpCache = new Quad();
private InterpHelper interpHelper = new InterpHelper();
QuadReInterpolator() {
super();
}
@Override
public void reset(CachedFormat format) {
super.reset(format);
this.interpCache.reset(format);
}
@Override
public void setInputQuad(Quad quad) {
super.setInputQuad(quad);
quad.resetInterp(this.interpHelper, quad.orientation.ordinal() >> 1);
}
@Override
public boolean transform() {
int s = this.quad.orientation.ordinal() >> 1;
if (this.format.hasColor || this.format.hasUV || this.format.hasLightMap) {
this.interpCache.copyFrom(this.quad);
this.interpHelper.setup();
for (Vertex v : this.quad.vertices) {
this.interpHelper.locate(v.dx(s), v.dy(s));
if (this.format.hasColor) {
v.interpColorFrom(this.interpHelper, this.interpCache.vertices);
}
if (this.format.hasUV) {
v.interpUVFrom(this.interpHelper, this.interpCache.vertices);
}
if (this.format.hasLightMap) {
v.interpLightMapFrom(this.interpHelper, this.interpCache.vertices);
}
}
}
return true;
}
}