Lots of fixes
This commit is contained in:
@@ -141,7 +141,7 @@ public class AEBaseBlockItem extends BlockItem {
|
||||
}
|
||||
|
||||
if (tile instanceof IGridProxyable) {
|
||||
// FIXME FABRIC ((IGridProxyable) tile).getProxy().setOwner(player);
|
||||
((IGridProxyable) tile).getProxy().setOwner(player);
|
||||
}
|
||||
|
||||
tile.onPlacement(context);
|
||||
|
||||
@@ -28,6 +28,8 @@ import javax.annotation.Nullable;
|
||||
import alexiil.mc.lib.attributes.AttributeList;
|
||||
import alexiil.mc.lib.attributes.AttributeProvider;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import appeng.block.networking.CableBusBlock;
|
||||
import appeng.tile.networking.CableBusBlockEntity;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (/* FIXME FABRIC tile instanceof CableBusBlockEntity || */ tile instanceof SkyChestBlockEntity) {
|
||||
if (tile instanceof CableBusBlockEntity || tile instanceof SkyChestBlockEntity) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
@@ -233,7 +235,7 @@ public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBas
|
||||
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 AEBaseBlockEntity tileEntity = this.getBlockEntity(world, pos);
|
||||
|
||||
|
||||
@@ -18,25 +18,21 @@
|
||||
|
||||
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.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.CraftingCPUContainer;
|
||||
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 static final BooleanProperty FORMED = BooleanProperty.of("formed");
|
||||
@@ -57,16 +53,6 @@ public abstract class AbstractCraftingUnitBlock<T extends CraftingBlockEntity> e
|
||||
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
|
||||
public void neighborUpdate(final BlockState state, final World worldIn, final BlockPos pos, final Block blockIn,
|
||||
final BlockPos fromPos, boolean isMoving) {
|
||||
|
||||
@@ -64,7 +64,7 @@ import appeng.util.Platform;
|
||||
public class ChargerBlock extends AEBaseTileBlock<ChargerBlockEntity> {
|
||||
|
||||
public ChargerBlock() {
|
||||
super(defaultProps(Material.METAL).solidBlock((state, world, pos) -> false));
|
||||
super(defaultProps(Material.METAL).nonOpaque());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,8 @@ import appeng.client.render.cablebus.CableBusBakedModel;
|
||||
import appeng.client.render.cablebus.CableBusBreakingParticle;
|
||||
import appeng.client.render.cablebus.CableBusRenderState;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.ClickPacket;
|
||||
import appeng.helpers.AEMaterials;
|
||||
import appeng.integration.abstraction.IAEFacade;
|
||||
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()));
|
||||
|
||||
if (this.cb(worldIn, pos).clicked(player, Hand.MAIN_HAND, hitVec)) {
|
||||
throw new IllegalStateException();
|
||||
// FIXME FABRIC NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x,
|
||||
// FIXME FABRIC (float) hitVec.y, (float) hitVec.z, Hand.MAIN_HAND, true));
|
||||
NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x,
|
||||
(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 WirelessBlock() {
|
||||
super(defaultProps(AEMaterials.GLASS)
|
||||
.nonOpaque()
|
||||
.solidBlock((state, world, pos) -> false)
|
||||
);
|
||||
super(defaultProps(AEMaterials.GLASS).nonOpaque());
|
||||
this.setDefaultState(this.getDefaultState().with(STATE, State.OFF));
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ import appeng.util.Platform;
|
||||
|
||||
public class PaintSplotchesBlock extends AEBaseTileBlock<PaintSplotchesBlockEntity> {
|
||||
public PaintSplotchesBlock() {
|
||||
super(defaultProps(Material.WATER, MaterialColor.CLEAR).solidBlock((state, world, pos) -> false)
|
||||
.air());
|
||||
super(defaultProps(Material.WATER, MaterialColor.CLEAR).nonOpaque().air());
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
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
|
||||
|
||||
@@ -8,16 +8,94 @@ import appeng.bootstrap.ModelsReloadCallback;
|
||||
import appeng.bootstrap.components.IClientSetupComponent;
|
||||
import appeng.bootstrap.components.IItemColorRegistrationComponent;
|
||||
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.cablebus.CableBusModelLoader;
|
||||
import appeng.client.render.cablebus.P2PTunnelFrequencyModel;
|
||||
import appeng.client.render.crafting.CraftingCubeModel;
|
||||
import appeng.client.render.effects.*;
|
||||
import appeng.client.render.model.*;
|
||||
import appeng.client.render.effects.ChargedOreFX;
|
||||
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.tesr.InscriberTESR;
|
||||
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.ApiDefinitions;
|
||||
import appeng.core.AppEng;
|
||||
@@ -25,10 +103,26 @@ import appeng.core.AppEngBase;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.core.sync.network.ClientNetworkHandler;
|
||||
import appeng.core.worlddata.WorldData;
|
||||
import appeng.entity.*;
|
||||
import appeng.fluids.client.gui.*;
|
||||
import appeng.fluids.container.*;
|
||||
import appeng.entity.ChargedQuartzEntity;
|
||||
import appeng.entity.GrowingCrystalEntity;
|
||||
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.parts.automation.PlaneModel;
|
||||
import appeng.tile.crafting.MolecularAssemblerRenderer;
|
||||
import appeng.util.Platform;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
@@ -53,7 +147,11 @@ import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
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.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -240,6 +338,18 @@ public final class AppEngClient extends AppEngBase {
|
||||
|
||||
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()));
|
||||
|
||||
addBuiltInModel("block/quartz_glass", GlassModel::new);
|
||||
@@ -249,14 +359,24 @@ public final class AppEngClient extends AppEngBase {
|
||||
addBuiltInModel("item/memory_card", MemoryCardModel::new);
|
||||
addBuiltInModel("item/biometric_card", BiometricCardModel::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/paint", PaintSplotchesModel::new);
|
||||
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("facade", FacadeItemModel::new);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "part_plane"),
|
||||
// FIXME FABRIC PlaneModelLoader.INSTANCE);
|
||||
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
|
||||
addBuiltInModel("part/p2p/p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
|
||||
addBuiltInModel("item/facade", FacadeItemModel::new);
|
||||
|
||||
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/4k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_4K));
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 alexiil.mc.lib.attributes.fluid.render.FluidRenderFace;
|
||||
import alexiil.mc.lib.attributes.fluid.render.FluidVolumeRenderer;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
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.container.slots.IMEFluidSlot;
|
||||
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> {
|
||||
|
||||
@@ -189,7 +190,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
|
||||
final Text msg = tooltip.getMessage();
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
if (msg != null && !msg.getString().isEmpty()) {
|
||||
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.
|
||||
@Override
|
||||
protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton,
|
||||
final SlotActionType clickType) {
|
||||
final SlotActionType clickType) {
|
||||
final PlayerEntity player = getPlayer();
|
||||
|
||||
if (slot instanceof FakeSlot) {
|
||||
@@ -510,7 +511,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
|
||||
protected int getSlotIndex(Slot slot) {
|
||||
return ((SlotMixin)slot).getIndex();
|
||||
return ((SlotMixin) slot).getIndex();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
} else if (!this.isPowered()) {
|
||||
@@ -786,7 +796,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
for (IGuiEventListener child : children) {
|
||||
for (Element child : children) {
|
||||
if (child instanceof ITickingWidget) {
|
||||
((ITickingWidget) child).tick();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ package appeng.client.gui.implementations;
|
||||
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
|
||||
this::onLevelChange);
|
||||
this.level.setTextFieldBounds(25, 44, 75);
|
||||
this.level.addButtons(children::add, this::addButton);
|
||||
container.setTextField(this.level);
|
||||
handler.setTextField(this.level);
|
||||
}
|
||||
|
||||
private void onLevelChange(long level) {
|
||||
@@ -100,7 +100,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
|
||||
|
||||
if (notCraftingMode) {
|
||||
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.LongConsumer;
|
||||
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.client.gui.NumberEntryType;
|
||||
import appeng.client.gui.widgets.ITickingWidget;
|
||||
import appeng.client.gui.widgets.NumberBox;
|
||||
import appeng.core.AEConfig;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
|
||||
/**
|
||||
* 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 NumberEntryType type;
|
||||
private Button plus1;
|
||||
private Button plus10;
|
||||
private Button plus100;
|
||||
private Button plus1000;
|
||||
private Button minus1;
|
||||
private Button minus10;
|
||||
private Button minus100;
|
||||
private Button minus1000;
|
||||
private ButtonWidget plus1;
|
||||
private ButtonWidget plus10;
|
||||
private ButtonWidget plus100;
|
||||
private ButtonWidget plus1000;
|
||||
private ButtonWidget minus1;
|
||||
private ButtonWidget minus10;
|
||||
private ButtonWidget minus100;
|
||||
private ButtonWidget minus1000;
|
||||
|
||||
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
|
||||
LongConsumer changeListener) {
|
||||
@@ -42,20 +44,19 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
|
||||
FontRenderer font = parent.getMinecraft().fontRenderer;
|
||||
int inputX = parent.getGuiLeft() + x;
|
||||
int inputY = parent.getGuiTop() + y;
|
||||
this.level = new NumberBox(font, inputX, inputY, width, font.FONT_HEIGHT, type.getInputType(), changeListener);
|
||||
this.level.setEnableBackgroundDrawing(false);
|
||||
this.level.setMaxStringLength(16);
|
||||
this.level.setTextColor(0xFFFFFF);
|
||||
TextRenderer font = parent.getClient().textRenderer;
|
||||
int inputX = parent.getX() + x;
|
||||
int inputY = parent.getY() + y;
|
||||
this.level = new NumberBox(font, inputX, inputY, width, font.fontHeight, type.getInputType(), changeListener);
|
||||
this.level.setHasBorder(false);
|
||||
this.level.setMaxLength(16);
|
||||
this.level.setEditableColor(0xFFFFFF);
|
||||
this.level.setVisible(true);
|
||||
this.level.setFocused2(true);
|
||||
parent.setFocusedDefault(this.level);
|
||||
parent.setInitialFocus(this.level);
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.level.setEnabled(active);
|
||||
this.level.active = active;
|
||||
this.plus1.active = active;
|
||||
this.plus10.active = active;
|
||||
this.plus100.active = active;
|
||||
@@ -67,8 +68,8 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
}
|
||||
|
||||
public void setTextFieldBounds(int x, int y, int width) {
|
||||
this.level.x = parent.getGuiLeft() + x;
|
||||
this.level.y = parent.getGuiTop() + y;
|
||||
this.level.x = parent.getX() + x;
|
||||
this.level.y = parent.getY() + y;
|
||||
this.level.setWidth(width);
|
||||
}
|
||||
|
||||
@@ -76,28 +77,28 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
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);
|
||||
int a = steps[0];
|
||||
int b = steps[1];
|
||||
int c = steps[2];
|
||||
int d = steps[3];
|
||||
|
||||
int left = parent.getGuiLeft() + x;
|
||||
int top = parent.getGuiTop() + y;
|
||||
int left = parent.getX() + x;
|
||||
int top = parent.getY() + y;
|
||||
|
||||
addButton.accept(this.plus1 = new Button(left, top, 22, 20, "+" + a, btn -> addQty(a)));
|
||||
addButton.accept(this.plus10 = new Button(left + 28, top, 28, 20, "+" + b, btn -> addQty(b)));
|
||||
addButton.accept(this.plus100 = new Button(left + 62, top, 32, 20, "+" + c, btn -> addQty(c)));
|
||||
addButton.accept(this.plus1000 = new Button(left + 100, top, 38, 20, "+" + d, btn -> addQty(d)));
|
||||
addButton.accept(this.plus1 = new ButtonWidget(left, top, 22, 20, new LiteralText("+" + a), btn -> addQty(a)));
|
||||
addButton.accept(this.plus10 = new ButtonWidget(left + 28, top, 28, 20, new LiteralText("+" + b), btn -> addQty(b)));
|
||||
addButton.accept(this.plus100 = new ButtonWidget(left + 62, top, 32, 20, new LiteralText("+" + c), btn -> addQty(c)));
|
||||
addButton.accept(this.plus1000 = new ButtonWidget(left + 100, top, 38, 20, new LiteralText("+" + d), btn -> addQty(d)));
|
||||
|
||||
// Placing this here will give a sensible tab order
|
||||
addChildren.accept(this.level);
|
||||
|
||||
addButton.accept(this.minus1 = new Button(left, top + 42, 22, 20, "-" + a, btn -> addQty(-a)));
|
||||
addButton.accept(this.minus10 = new Button(left + 28, top + 42, 28, 20, "-" + b, btn -> addQty(-b)));
|
||||
addButton.accept(this.minus100 = new Button(left + 62, top + 42, 32, 20, "-" + c, btn -> addQty(-c)));
|
||||
addButton.accept(this.minus1000 = new Button(left + 100, top + 42, 38, 20, "-" + d, btn -> addQty(-d)));
|
||||
addButton.accept(this.minus1 = new ButtonWidget(left, top + 42, 22, 20, new LiteralText("-" + a), btn -> addQty(-a)));
|
||||
addButton.accept(this.minus10 = new ButtonWidget(left + 28, top + 42, 28, 20, new LiteralText("-" + b), btn -> addQty(-b)));
|
||||
addButton.accept(this.minus100 = new ButtonWidget(left + 62, top + 42, 32, 20, new LiteralText("-" + c), btn -> addQty(-c)));
|
||||
addButton.accept(this.minus1000 = new ButtonWidget(left + 100, top + 42, 38, 20, new LiteralText("-" + d), btn -> addQty(-d)));
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
this.level.render(mouseX, mouseY, partialTicks);
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
|
||||
this.level.render(matrices, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
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.setTextFieldBounds(62, 57, 50);
|
||||
this.priority.setMinValue(Integer.MIN_VALUE);
|
||||
container.setTextField(this.priority);
|
||||
handler.setTextField(this.priority);
|
||||
this.priority.addButtons(children::add, this::addButton);
|
||||
|
||||
this.subGui.addBackButton(this::addButton, 154, 0);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package appeng.client.gui.widgets;
|
||||
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
/**
|
||||
* Indicates that a widget (anything that is in the {@link Screen#children()}
|
||||
* list) should receive callbacks every tick.
|
||||
*/
|
||||
public interface ITickingWidget {
|
||||
public interface ITickingWidget extends Element {
|
||||
|
||||
void tick();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class NumberBox extends TextFieldWidget {
|
||||
final Class<?> type, LongConsumer changeListener) {
|
||||
super(fontRenderer, x, y, width, height, new LiteralText("0"));
|
||||
this.setText("0");
|
||||
setResponder(this::onTextChanged);
|
||||
setChangedListener(this::onTextChanged);
|
||||
this.lastValue = 0;
|
||||
this.changeListener = changeListener;
|
||||
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 "";
|
||||
return LiteralText.EMPTY;
|
||||
}
|
||||
|
||||
public String getFillVar() {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ToggleButton extends ButtonWidget implements ITooltip {
|
||||
|
||||
return new LiteralText(name + '\n' + sb);
|
||||
}
|
||||
return "";
|
||||
return LiteralText.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, 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 alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
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 java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author DrummerMC
|
||||
* @version rv6 - 2018-01-22
|
||||
* @since rv6 2018-01-22
|
||||
*/
|
||||
public class DummyFluidBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private final FluidVolume volume;
|
||||
|
||||
public DummyFluidBakedModel(FluidVolume volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
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
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, 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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.render.RenderContext;
|
||||
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.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
|
||||
import appeng.client.render.cablebus.FacadeBuilder;
|
||||
|
||||
/**
|
||||
* This model used the provided FacadeBuilder to "slice" the item quads for the
|
||||
* facade provided.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBakedItemModel extends ForwardingBakedModel implements FabricBakedModel {
|
||||
|
||||
private final ItemStack textureStack;
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
private List<BakedQuad> quads = null;
|
||||
|
||||
protected FacadeBakedItemModel(BakedModel base, ItemStack textureStack, FacadeBuilder facadeBuilder) {
|
||||
this.wrapped = base;
|
||||
this.textureStack = textureStack;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
super.emitItemQuads(stack, randomSupplier, context);
|
||||
|
||||
if (quads == null) {
|
||||
quads = new ArrayList<>();
|
||||
quads.addAll(this.facadeBuilder.buildFacadeItemQuads(this.textureStack, Direction.NORTH));
|
||||
quads = Collections.unmodifiableList(quads);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 appeng.client.render.cablebus.FacadeBuilder;
|
||||
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
|
||||
* the *real* model that should be used based on the item stack. A custom Item
|
||||
* Override List is used to accomplish this.
|
||||
*/
|
||||
public class FacadeDispatcherBakedModel extends ForwardingBakedModel {
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
private final Int2ObjectMap<FacadeBakedItemModel> cache = new Int2ObjectArrayMap<>();
|
||||
|
||||
public FacadeDispatcherBakedModel(BakedModel baseModel, FacadeBuilder facadeBuilder) {
|
||||
this.wrapped = baseModel;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
if (!(stack.getItem() instanceof FacadeItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FacadeItem itemFacade = (FacadeItem) stack.getItem();
|
||||
|
||||
ItemStack textureItem = itemFacade.getTextureItem(stack);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 appeng.client.render.cablebus.FacadeBuilder;
|
||||
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.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
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
|
||||
* declare any dependencies here other than the cable anchor.
|
||||
*/
|
||||
public class FacadeItemModel implements BasicUnbakedModel {
|
||||
|
||||
// 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");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
BakedModel bakedBaseModel = loader.bake(MODEL_BASE, rotationContainer);
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder(loader);
|
||||
|
||||
return new FacadeDispatcherBakedModel(bakedBaseModel, facadeBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return Collections.singleton(MODEL_BASE);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.api.parts.IDynamicPartBakedModel;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
@@ -25,17 +26,13 @@ import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
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.MeshBuilder;
|
||||
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.render.RenderContext;
|
||||
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.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
@@ -49,8 +46,14 @@ import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
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.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@@ -125,7 +128,11 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
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
|
||||
|
||||
@@ -67,7 +67,7 @@ public class CableBusModel implements BasicUnbakedModel {
|
||||
Map<Identifier, BakedModel> partModels = this.loadPartModels(loader, rotationContainer);
|
||||
|
||||
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
|
||||
// or otherwise damage models will
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, 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.cablebus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.chunk.light.LightingProvider;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
|
||||
/**
|
||||
* This is used to retrieve the ExtendedState of a block for facade rendering.
|
||||
* It fakes the block at BlockPos provided as the BlockState provided.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBlockAccess implements BlockRenderView {
|
||||
|
||||
private final BlockRenderView world;
|
||||
private final BlockPos pos;
|
||||
private final Direction side;
|
||||
private final BlockState state;
|
||||
|
||||
public FacadeBlockAccess(BlockRenderView world, BlockPos pos, Direction side, BlockState state) {
|
||||
this.world = world;
|
||||
this.pos = pos;
|
||||
this.side = side;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||
return this.world.getBlockEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
if (this.pos == pos) {
|
||||
return this.state;
|
||||
}
|
||||
return this.world.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
return world.getFluidState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightingProvider getLightingProvider() {
|
||||
return world.getLightingProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBrightness(Direction direction, boolean shaded) {
|
||||
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;
|
||||
|
||||
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.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -28,31 +62,6 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
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..
|
||||
*
|
||||
@@ -60,43 +69,93 @@ import appeng.parts.misc.CableAnchorPart;
|
||||
*/
|
||||
public class FacadeBuilder {
|
||||
|
||||
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
|
||||
public static final double THICK_THICKNESS = 2D / 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, 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, 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(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, 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, 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(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()
|
||||
//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);
|
||||
private final Map<Direction, Mesh> cableAnchorStilts;
|
||||
|
||||
public void buildFacadeQuads(RenderLayer layer, CableBusRenderState renderState, Supplier<Random> rand,
|
||||
RenderContext context, Function<Identifier, BakedModel> modelLookup) {
|
||||
public FacadeBuilder(ModelLoader modelLoader) {
|
||||
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 Quad collectorQuad = this.collectors.get();
|
||||
boolean transparent = Api.instance().partHelper().getCableRenderMode().transparentFacades;
|
||||
@@ -108,32 +167,29 @@ public class FacadeBuilder {
|
||||
BlockColors blockColors = MinecraftClient.getInstance().getBlockColors();
|
||||
boolean thinFacades = isUseThinFacades(partBoxes);
|
||||
|
||||
MeshBuilder meshBuilder = renderer.meshBuilder();
|
||||
QuadEmitter emitter = meshBuilder.getEmitter();
|
||||
|
||||
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
|
||||
Direction side = entry.getKey();
|
||||
int sideIndex = side.ordinal();
|
||||
FacadeRenderState facadeRenderState = entry.getValue();
|
||||
boolean renderStilt = !sidesWithParts.contains(side);
|
||||
if (layer == RenderLayer.getCutout() && renderStilt) {
|
||||
context.pushTransform(QuadRotator.get(side, Direction.UP));
|
||||
for (Identifier part : CableAnchorPart.FACADE_MODELS.getModels()) {
|
||||
BakedModel partModel = modelLookup.apply(part);
|
||||
context.fallbackConsumer().accept(partModel);
|
||||
}
|
||||
context.popTransform();
|
||||
}
|
||||
// If we are forcing transparency and this isn't the Translucent layer.
|
||||
if (transparent && layer != RenderLayer.getTranslucent()) {
|
||||
continue;
|
||||
if (renderStilt) {
|
||||
cableAnchorStilts.get(entry.getKey()).forEach(quad -> {
|
||||
quad.copyTo(emitter);
|
||||
emitter.emit();
|
||||
});
|
||||
}
|
||||
|
||||
BlockState blockState = facadeRenderState.getSourceBlock();
|
||||
// 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 if (!RenderLayers.canRenderInLayer(blockState, layer)) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
}
|
||||
// FIXME FABRIC }
|
||||
|
||||
Box fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
|
||||
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);
|
||||
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();
|
||||
// FIXME FABRIC BakedModel model = dispatcher.getModel(blockState);
|
||||
// FIXME FABRIC IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// FIXME FABRIC // If we are forcing transparent facades, fake the render layer, and grab all
|
||||
// FIXME FABRIC // quads.
|
||||
// FIXME FABRIC if (transparent || layer == null) {
|
||||
// FIXME FABRIC for (RenderLayer forcedLayer : RenderLayer.getBlockRenderTypes()) {
|
||||
// FIXME FABRIC // Check if the block renders on the layer we want to force.
|
||||
// FIXME FABRIC if (RenderLayers.canRenderInLayer(blockState, forcedLayer)) {
|
||||
// FIXME FABRIC // Force the layer and gather quads.
|
||||
// FIXME FABRIC ForgeHooksClient.setRenderLayer(forcedLayer);
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Reset.
|
||||
// FIXME FABRIC ForgeHooksClient.setRenderLayer(layer);
|
||||
// FIXME FABRIC } else {
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // No quads.. Cool, next!
|
||||
// FIXME FABRIC if (modelQuads.isEmpty()) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Grab out pipeline elements.
|
||||
// FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
// FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
|
||||
// FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
// FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Set global element states.
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // calculate the side mask.
|
||||
// FIXME FABRIC int facadeMask = 0;
|
||||
// FIXME FABRIC for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
|
||||
// FIXME FABRIC Direction s = ent.getKey();
|
||||
// FIXME FABRIC if (s.getAxis() != side.getAxis()) {
|
||||
// FIXME FABRIC FacadeRenderState otherState = ent.getValue();
|
||||
// FIXME FABRIC if (!otherState.isTransparent()) {
|
||||
// FIXME FABRIC facadeMask |= 1 << s.ordinal();
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC // Setup the edge stripper.
|
||||
// FIXME FABRIC edgeStripper.setBounds(fullBounds);
|
||||
// FIXME FABRIC edgeStripper.setMask(facadeMask);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Setup the kicker.
|
||||
// FIXME FABRIC kicker.setSide(sideIndex);
|
||||
// FIXME FABRIC kicker.setFacadeMask(facadeMask);
|
||||
// FIXME FABRIC kicker.setBox(fullBounds);
|
||||
// FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
// FIXME FABRIC
|
||||
// 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 tinter.setTint(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC for (Box box : holeStrips) {
|
||||
// FIXME FABRIC // setup the clamper for this box
|
||||
// FIXME FABRIC clamper.setClampBounds(box);
|
||||
// FIXME FABRIC // Reset the pipeline, clears all enabled/disabled states.
|
||||
// FIXME FABRIC pipeline.reset(format);
|
||||
// FIXME FABRIC // Reset out collector.
|
||||
// FIXME FABRIC collectorQuad.reset(format);
|
||||
// FIXME FABRIC // Enable / disable the optional elements
|
||||
// FIXME FABRIC pipeline.setElementState("tinter", quad.hasTintIndex());
|
||||
// FIXME FABRIC pipeline.setElementState("transparent", transparent);
|
||||
// FIXME FABRIC // Prepare the pipeline for a quad.
|
||||
// FIXME FABRIC pipeline.prepare(collectorQuad);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Pipe our quad into the pipeline.
|
||||
// FIXME FABRIC quad.pipe(pipeline);
|
||||
// FIXME FABRIC // Check if the collector got any data.
|
||||
// FIXME FABRIC if (collectorQuad.full) {
|
||||
// FIXME FABRIC // Add the result.
|
||||
// FIXME FABRIC quads.add(collectorQuad.bake());
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
|
||||
BakedModel model = dispatcher.getModel(blockState);
|
||||
|
||||
QuadFaceStripper faceStripper = new QuadFaceStripper(fullBounds, facadeMask);
|
||||
// Setup the kicker.
|
||||
QuadCornerKicker kicker = new QuadCornerKicker();
|
||||
kicker.setSide(sideIndex);
|
||||
kicker.setFacadeMask(facadeMask);
|
||||
kicker.setBox(fullBounds);
|
||||
kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
|
||||
QuadReInterpolator interpolator = new QuadReInterpolator();
|
||||
|
||||
for (int cullFaceIdx = 0; cullFaceIdx <= ModelHelper.NULL_FACE_ID; cullFaceIdx++) {
|
||||
Direction cullFace = ModelHelper.faceFromIndex(cullFaceIdx);
|
||||
List<BakedQuad> quads = model.getQuads(blockState, cullFace, rand.get());
|
||||
|
||||
for (BakedQuad quad : quads) {
|
||||
QuadTinter quadTinter = null;
|
||||
|
||||
// Prebake the color tint into the quad
|
||||
if (quad.getColorIndex() != -1) {
|
||||
quadTinter = new QuadTinter(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
|
||||
}
|
||||
|
||||
for (Box box : holeStrips) {
|
||||
emitter.fromVanilla(quad.getVertexData(), 0, false);
|
||||
emitter.cullFace(cullFace);
|
||||
emitter.nominalFace(quad.getFace());
|
||||
interpolator.setInputQuad(emitter);
|
||||
|
||||
QuadClamper clamper = new QuadClamper(box);
|
||||
if (!clamper.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Strips faces if they match a mask.
|
||||
if (!faceStripper.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Kicks the edge inner corners in, solves Z fighting
|
||||
if (!kicker.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
interpolator.transform(emitter);
|
||||
|
||||
// Tints the quad if we need it to. Disabled by default.
|
||||
if (quadTinter != null) {
|
||||
quadTinter.transform(emitter);
|
||||
}
|
||||
|
||||
// // Overrides the quad's alpha if we are forcing transparent facades.
|
||||
// .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
|
||||
|
||||
emitter.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand));
|
||||
|
||||
// FIXME FABRIC // No quads.. Cool, next!
|
||||
// FIXME FABRIC if (modelQuads.isEmpty()) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Grab out pipeline elements.
|
||||
// FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
// FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
|
||||
// FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
// FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Set global element states.
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Setup the kicker.
|
||||
// FIXME FABRIC kicker.setSide(sideIndex);
|
||||
// FIXME FABRIC kicker.setFacadeMask(facadeMask);
|
||||
// FIXME FABRIC kicker.setBox(fullBounds);
|
||||
// FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
// FIXME FABRIC
|
||||
// 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 }
|
||||
}
|
||||
|
||||
return meshBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,7 +435,6 @@ public class FacadeBuilder {
|
||||
* @param fb The Facade's box.
|
||||
* @param hole The hole to 'cut'.
|
||||
* @param axis The axis the facade is on.
|
||||
*
|
||||
* @return The box segments.
|
||||
*/
|
||||
private static List<Box> getBoxes(Box fb, AEAxisAlignedBB hole, Axis axis) {
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.api.parts.IDynamicPartBakedModel;
|
||||
import appeng.api.util.AEColor;
|
||||
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;
|
||||
|
||||
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 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}};
|
||||
|
||||
public P2PTunnelFrequencyBakedModel(final Sprite texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context,
|
||||
Direction partSide, @Nullable Object modelData) {
|
||||
if (!(modelData instanceof Long)) {
|
||||
return;
|
||||
}
|
||||
long frequency = (long) modelData;
|
||||
|
||||
Mesh frequencyMesh = getFrequencyModel(frequency);
|
||||
if (frequencyMesh != null) {
|
||||
context.meshConsumer().accept(frequencyMesh);
|
||||
}
|
||||
}
|
||||
|
||||
@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 CubeBuilder cb = new CubeBuilder(meshBuilder.getEmitter());
|
||||
|
||||
cb.setTexture(this.texture);
|
||||
cb.useStandardUV();
|
||||
cb.setRenderFullBright(active);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
final int[] offs = QUAD_OFFSETS[i];
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
final float[] cv = colors[j].dye.getColorComponents();
|
||||
if (active) {
|
||||
cb.setColorRGB(cv[0], cv[1], cv[2]);
|
||||
} else {
|
||||
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
|
||||
}
|
||||
|
||||
final int startx = j % 2;
|
||||
final int starty = 1 - j / 2;
|
||||
|
||||
cb.addCube(offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1,
|
||||
offs[2] + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return meshBuilder.build();
|
||||
}
|
||||
|
||||
private Mesh getFrequencyModel(long partFlags) {
|
||||
try {
|
||||
return modelCache.get(partFlags, () -> {
|
||||
short frequency = (short) (partFlags & 0xffffL);
|
||||
boolean active = (partFlags & 0x10000L) != 0;
|
||||
return this.createFrequencyMesh(frequency, active);
|
||||
});
|
||||
} catch (ExecutionException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
this.setCPU(((CraftingTileEntity) te).getCluster());
|
||||
this.setCPU(((CraftingBlockEntity) te).getCluster());
|
||||
}
|
||||
|
||||
if (this.getNetwork() == null && Platform.isServer()) {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
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.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.crafting.ICraftingGrid;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
@@ -17,28 +23,82 @@ import appeng.bootstrap.components.ITileEntityRegistrationComponent;
|
||||
import appeng.client.render.effects.ParticleTypes;
|
||||
import appeng.container.AEBaseContainer;
|
||||
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.BasicItemCellGuiHandler;
|
||||
import appeng.core.features.registries.cell.CreativeCellHandler;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.core.stats.AdvancementTriggers;
|
||||
import appeng.core.stats.AeStats;
|
||||
import appeng.core.sync.BasePacket;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
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.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.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.spatial.SpatialDimensionManager;
|
||||
import appeng.spatial.StorageCellBiome;
|
||||
import appeng.spatial.StorageChunkGenerator;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
import appeng.worldgen.ChargedQuartzOreConfig;
|
||||
import appeng.worldgen.ChargedQuartzOreFeature;
|
||||
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.loader.api.FabricLoader;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BannerBlockEntity;
|
||||
import net.minecraft.block.entity.BeaconBlockEntity;
|
||||
import net.minecraft.block.entity.BrewingStandBlockEntity;
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.block.entity.CommandBlockBlockEntity;
|
||||
import net.minecraft.block.entity.ComparatorBlockEntity;
|
||||
import net.minecraft.block.entity.DaylightDetectorBlockEntity;
|
||||
import net.minecraft.block.entity.DispenserBlockEntity;
|
||||
import net.minecraft.block.entity.DropperBlockEntity;
|
||||
import net.minecraft.block.entity.EnchantingTableBlockEntity;
|
||||
import net.minecraft.block.entity.EndPortalBlockEntity;
|
||||
import net.minecraft.block.entity.EnderChestBlockEntity;
|
||||
import net.minecraft.block.entity.FurnaceBlockEntity;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.block.entity.MobSpawnerBlockEntity;
|
||||
import net.minecraft.block.entity.PistonBlockEntity;
|
||||
import net.minecraft.block.entity.ShulkerBoxBlockEntity;
|
||||
import net.minecraft.block.entity.SignBlockEntity;
|
||||
import net.minecraft.block.entity.SkullBlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -55,6 +134,7 @@ import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
@@ -136,6 +216,177 @@ public abstract class AppEngBase implements AppEng {
|
||||
registries.cell().addCellGuiHandler(new BasicFluidCellGuiHandler());
|
||||
|
||||
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() {
|
||||
@@ -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("grinder"), GrinderRecipeSerializer.INSTANCE);
|
||||
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("inscriber"), InscriberRecipeSerializer.INSTANCE);
|
||||
|
||||
// FIXME FABRIC FacadeItem facadeItem = (FacadeItem) Api.INSTANCE.definitions().items().facade().item();
|
||||
// FIXME FABRIC r.registerAll(DisassembleRecipe.SERIALIZER,
|
||||
// FIXME FABRIC FacadeRecipe.getSerializer(facadeItem));
|
||||
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("disassemble"), DisassembleRecipe.SERIALIZER);
|
||||
FacadeItem facadeItem = (FacadeItem) Api.INSTANCE.definitions().items().facade().item();
|
||||
Registry.register(Registry.RECIPE_SERIALIZER, AppEng.makeId("facade"), FacadeRecipe.getSerializer(facadeItem));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class CreativeTab {
|
||||
.icon(() -> {
|
||||
final IDefinitions definitions = Api.instance().definitions();
|
||||
final IBlocks blocks = definitions.blocks();
|
||||
return blocks.quartzOre().stack(1); // FIXME FABRIC blocks.controller().stack(1);
|
||||
return blocks.controller().stack(1);
|
||||
})
|
||||
.appendItems(CreativeTab::fill)
|
||||
.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.amount.FluidAmount;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import appeng.crafting.CraftingLink;
|
||||
import appeng.fluids.util.FluidList;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
@@ -99,8 +100,7 @@ public class ApiStorage implements IStorageHelper {
|
||||
Preconditions.checkNotNull(data);
|
||||
Preconditions.checkNotNull(req);
|
||||
|
||||
// FIXME FABRIC return new CraftingLink(data, req);
|
||||
throw new IllegalStateException();
|
||||
return new CraftingLink(data, req);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -173,7 +173,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
.sounds(BlockSoundGroup.GLASS)
|
||||
.nonOpaque()
|
||||
.allowsSpawning((state, world, pos, type) -> false)
|
||||
.solidBlock((state, world, pos) -> false)
|
||||
.nonOpaque()
|
||||
.suffocates((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)
|
||||
.strength(50, 150)
|
||||
.solidBlock((state, world, pos) -> false);
|
||||
.nonOpaque();
|
||||
|
||||
TileEntityDefinition skyChestTile = registry
|
||||
.tileEntity("sky_chest", SkyChestBlockEntity.class, SkyChestBlockEntity::new)
|
||||
@@ -281,7 +281,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
this.crank = registry
|
||||
.block("crank",
|
||||
() -> 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)
|
||||
.tileEntity(registry.tileEntity("crank", CrankBlockEntity.class, CrankBlockEntity::new)
|
||||
.rendering(new TileEntityRenderingCustomizer<CrankBlockEntity>() {
|
||||
@@ -292,7 +292,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
}
|
||||
}).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)
|
||||
.tileEntity(registry.tileEntity("inscriber", InscriberBlockEntity.class, InscriberBlockEntity::new)
|
||||
.rendering(new InscriberRendering()).build())
|
||||
@@ -486,7 +486,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
}).build();
|
||||
|
||||
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() {
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Override
|
||||
|
||||
@@ -97,8 +97,7 @@ public final class WirelessRegistry implements IWirelessTermRegistry {
|
||||
}
|
||||
|
||||
if (handler.hasPower(player, 0.5, item)) {
|
||||
// FIXME FABRIC ContainerOpener.openContainer(WirelessTermContainer.TYPE, player, ContainerLocator.forHand(player, hand));
|
||||
throw new IllegalStateException();
|
||||
ContainerOpener.openContainer(WirelessTermContainer.TYPE, player, ContainerLocator.forHand(player, hand));
|
||||
} else {
|
||||
player.sendSystemMessage(PlayerMessages.DeviceNotPowered.get(), Util.NIL_UUID);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
package appeng.entity;
|
||||
|
||||
import appeng.client.EffectType;
|
||||
import appeng.items.misc.CrystalSeedItem;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
@@ -116,8 +118,8 @@ public final class GrowingCrystalEntity extends AEBaseItemEntity {
|
||||
|
||||
if (this.progress_1000 >= len) {
|
||||
this.progress_1000 = 0;
|
||||
// FIXME FABRIC AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2,
|
||||
// FIXME FABRIC this.getZ(), null);
|
||||
AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2,
|
||||
this.getZ(), null);
|
||||
}
|
||||
} else {
|
||||
if (this.progress_1000 > 1000) {
|
||||
@@ -174,11 +176,10 @@ public final class GrowingCrystalEntity extends AEBaseItemEntity {
|
||||
@Override
|
||||
public void applyBuoyancy() {
|
||||
ItemStack item = getStack();
|
||||
throw new IllegalStateException();
|
||||
// FIXME FABRIC if (item.getItem() instanceof CrystalSeedItem) {
|
||||
// FIXME FABRIC return;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC super.applyBuoyancy();
|
||||
if (item.getItem() instanceof CrystalSeedItem) {
|
||||
return;
|
||||
}
|
||||
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::onLevelChange);
|
||||
this.level.setTextFieldBounds(25, 44, 75);
|
||||
container.setTextField(this.level);
|
||||
handler.setTextField(this.level);
|
||||
this.level.addButtons(children::add, this::addButton);
|
||||
|
||||
final int y = 40;
|
||||
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
|
||||
@@ -57,10 +57,10 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) {
|
||||
super.drawFG(offsetX, offsetY, mouseX, mouseY);
|
||||
public void drawFG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int 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
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
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.FluidExtractable;
|
||||
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
|
||||
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.GroupedFluidInvView;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidKey;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.client.gui.widgets.CustomSlotWidget;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.FluidSlotPacket;
|
||||
import appeng.fluids.util.AEFluidStack;
|
||||
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 {
|
||||
private final IAEFluidTank fluids;
|
||||
@@ -50,9 +49,11 @@ public class FluidSlotWidget extends CustomSlotWidget {
|
||||
if (clickStack.isEmpty() || mouseButton == 1) {
|
||||
this.setFluidStack(null);
|
||||
} else if (mouseButton == 0) {
|
||||
FluidExtractable extractable = FluidAttributes.EXTRACTABLE.getFirstOrNull(clickStack);
|
||||
if (extractable != null && extractable.couldExtractAnything()) {
|
||||
FluidVolume volume = extractable.attemptAnyExtraction(FluidAmount.MAX_VALUE, Simulation.ACTION);
|
||||
GroupedFluidInvView groupView = FluidAttributes.GROUPED_INV_VIEW.get(clickStack);
|
||||
Set<FluidKey> fluids = groupView.getStoredFluids();
|
||||
if (!fluids.isEmpty()) {
|
||||
FluidKey firstFluid = groupView.getStoredFluids().iterator().next();
|
||||
FluidVolume volume = firstFluid.withAmount(groupView.getAmount_F(firstFluid));
|
||||
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 "";
|
||||
return LiteralText.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,9 +25,12 @@ import java.nio.BufferOverflowException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
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.FluidExtractable;
|
||||
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.filter.ExactFluidFilter;
|
||||
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
|
||||
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) {
|
||||
return; // Might be nothing allowed...
|
||||
}
|
||||
@@ -342,13 +346,13 @@ public class FluidTerminalContainer extends AEBaseContainer
|
||||
}
|
||||
|
||||
// How much could fit into the container
|
||||
volumeAllowed = insertable.attemptInsertion(canPull.getFluidStack(), Simulation.SIMULATE);
|
||||
if (volumeAllowed.isEmpty()) {
|
||||
volumeOverflow = insertable.attemptInsertion(canPull.getFluidStack(), Simulation.SIMULATE);
|
||||
if (!volumeOverflow.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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,
|
||||
this.getActionSource());
|
||||
if (pulled == null || pulled.getStackSize() < 1) {
|
||||
@@ -358,11 +362,11 @@ public class FluidTerminalContainer extends AEBaseContainer
|
||||
}
|
||||
|
||||
// Actually fill
|
||||
final FluidVolume reallyFilled = insertable.attemptInsertion(pulled.getFluidStack(), Simulation.ACTION);
|
||||
volumeOverflow = insertable.attemptInsertion(pulled.getFluidStack(), Simulation.ACTION);
|
||||
|
||||
if (!reallyFilled.amount().equals(volumeAllowed.amount())) {
|
||||
AELog.error("Fluid item [%s] reported a different possible amount than it actually accepted.",
|
||||
held.getName());
|
||||
if (!volumeOverflow.isEmpty()) {
|
||||
AELog.error("Fluid item [%s] reported a different possible amount than it actually accepted. Overflow: %s.",
|
||||
held, volumeOverflow);
|
||||
}
|
||||
|
||||
player.inventory.setCursorStack(container.get());
|
||||
|
||||
@@ -4,7 +4,7 @@ package appeng.fluids.parts;
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
|
||||
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.Actionable;
|
||||
import appeng.api.config.IncludeExclude;
|
||||
@@ -42,16 +42,14 @@ import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.FluidFillable;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.math.RoundingMode;
|
||||
@@ -116,7 +114,7 @@ public class FluidFormationPlanePart extends AbstractFormationPlanePart<IAEFluid
|
||||
final BlockPos pos = te.getPos().offset(side.getFacing());
|
||||
|
||||
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())) {
|
||||
// calculate the effective amount consumed
|
||||
// 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
|
||||
public void onFluidInventoryChanged(IAEFluidTank inv, int slot) {
|
||||
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
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package appeng.fluids.util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
|
||||
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_CRAFTABLE = "craft";
|
||||
private static final String NBT_FLUID_ID = "f";
|
||||
private static final String NBT_FLUID_TAG = "ft";
|
||||
|
||||
private final FluidKey fluid;
|
||||
private CompoundTag tagCompound;
|
||||
|
||||
private AEFluidStack(final AEFluidStack fluidStack) {
|
||||
this.fluid = fluidStack.fluid;
|
||||
@@ -60,18 +57,13 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
// priority = is.priority;
|
||||
this.setCraftable(fluidStack.isCraftable());
|
||||
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.setStackSize(amount);
|
||||
this.setCraftable(false);
|
||||
this.setCountRequestable(0);
|
||||
this.tagCompound = tag;
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
CompoundTag tag = input.toTag();
|
||||
if (tag.isEmpty()) {
|
||||
tag = null;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -101,14 +88,9 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
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);
|
||||
|
||||
AEFluidStack fluidStack = new AEFluidStack(fluid, amount, tag);
|
||||
AEFluidStack fluidStack = new AEFluidStack(fluid, amount);
|
||||
fluidStack.setCountRequestable(data.getLong(NBT_REQUESTABLE));
|
||||
fluidStack.setCraftable(data.getBoolean(NBT_CRAFTABLE));
|
||||
return fluidStack;
|
||||
@@ -127,9 +109,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
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_REQUESTABLE, this.getCountRequestable());
|
||||
data.putBoolean(NBT_CRAFTABLE, this.isCraftable());
|
||||
@@ -162,12 +141,7 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
if (this.fluid != other.fluid) {
|
||||
return this.fluid.entry.getId().compareTo(other.fluid.entry.getId());
|
||||
}
|
||||
|
||||
if (Platform.itemComparisons().isNbtTagEqual(this.tagCompound, other.tagCompound)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.tagCompound.hashCode() - other.tagCompound.hashCode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -175,7 +149,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.fluid == null) ? 0 : this.fluid.hashCode());
|
||||
result = prime * result + ((this.tagCompound == null) ? 0 : this.tagCompound.hashCode());
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -184,29 +157,28 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
public boolean equals(final Object other) {
|
||||
if (other instanceof AEFluidStack) {
|
||||
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) {
|
||||
final FluidVolume is = (FluidVolume) other;
|
||||
return is.getFluidKey() == this.fluid
|
||||
&& Platform.itemComparisons().isNbtTagEqual(this.tagCompound, is.toTag());
|
||||
return is.getFluidKey() == this.fluid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getStackSize() + "x" + this.getFluidStack().getFluidKey().entry.getId() + " " + this.tagCompound;
|
||||
return this.getStackSize() + "x" + this.getFluidStack().getFluidKey().entry.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTagCompound() {
|
||||
return this.tagCompound != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidVolume getFluidStack() {
|
||||
FluidAmount amount = FluidAmount.of(this.getStackSize(), 1000);
|
||||
return this.fluid.readVolume(tagCompound).withAmount(amount);
|
||||
return this.fluid.withAmount(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -234,11 +206,10 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
final boolean isCraftable = buffer.readBoolean();
|
||||
|
||||
FluidKey fluid = FluidKey.fromTag(buffer.readCompoundTag());
|
||||
CompoundTag compoundTag = buffer.readCompoundTag();
|
||||
final long amount = 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.setCraftable(isCraftable);
|
||||
return fluidStack;
|
||||
@@ -248,7 +219,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
public void writeToPacket(final PacketByteBuf buffer) {
|
||||
buffer.writeBoolean(this.isCraftable());
|
||||
buffer.writeCompoundTag(fluid.toTag());
|
||||
buffer.writeCompoundTag(tagCompound);
|
||||
buffer.writeVarLong(this.getStackSize());
|
||||
buffer.writeVarLong(this.getCountRequestable());
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
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.mixins.ItemRendererAccessor;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
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.fluid.Fluids;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public final class ItemRendererHooks {
|
||||
|
||||
@@ -22,7 +33,11 @@ public final class ItemRendererHooks {
|
||||
* if shift is held.
|
||||
*/
|
||||
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();
|
||||
ClientWorld world = MinecraftClient.getInstance().world;
|
||||
if (shiftHeld && world != null) {
|
||||
@@ -31,18 +46,28 @@ public final class ItemRendererHooks {
|
||||
if (!output.isEmpty()) {
|
||||
BakedModel realModel = MinecraftClient.getInstance().getItemRenderer().getModels()
|
||||
.getModel(output);
|
||||
ItemRendererAccessor self = (ItemRendererAccessor) renderer;
|
||||
OVERRIDING_FOR.set(stack);
|
||||
try {
|
||||
self.callRenderGuiItemModel(stack, x, y, realModel);
|
||||
} finally {
|
||||
OVERRIDING_FOR.remove();
|
||||
}
|
||||
renderInstead(renderer, stack, x, y, realModel);
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,23 +18,7 @@
|
||||
|
||||
package appeng.hooks;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
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.networking.IGridNode;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.AELog;
|
||||
@@ -44,14 +28,32 @@ import appeng.me.Grid;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
import appeng.util.IWorldCallable;
|
||||
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.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
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 {
|
||||
|
||||
private static final TickHandler INSTANCE = new TickHandler();
|
||||
private static TickHandler INSTANCE;
|
||||
private final Queue<IWorldCallable<?>> serverQueue = new ArrayDeque<>();
|
||||
private final Multimap<World, CraftingJob> craftingJobs = LinkedListMultimap.create();
|
||||
private final Map<WorldAccess, Queue<IWorldCallable<?>>> callQueue = new WeakHashMap<>();
|
||||
@@ -60,11 +62,16 @@ public class TickHandler {
|
||||
private final HashMap<Integer, PlayerColor> srvPlayerColors = new HashMap<>();
|
||||
|
||||
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
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::onAfterServerTick);
|
||||
ServerTickEvents.START_WORLD_TICK.register(this::onBeforeWorldTick);
|
||||
ServerTickEvents.END_WORLD_TICK.register(this::onAfterWorldTick);
|
||||
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStopping);
|
||||
}
|
||||
|
||||
public static TickHandler instance() {
|
||||
@@ -147,6 +154,27 @@ public class TickHandler {
|
||||
// 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) {
|
||||
final Queue<IWorldCallable<?>> queue = this.callQueue.get(world);
|
||||
this.processQueue(queue, world);
|
||||
|
||||
@@ -20,7 +20,10 @@ package appeng.items.tools;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import appeng.block.AEBaseTileBlock;
|
||||
import appeng.hooks.AEToolItem;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -29,6 +32,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@@ -40,7 +44,7 @@ import appeng.core.localization.PlayerMessages;
|
||||
import appeng.items.AEBaseItem;
|
||||
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,
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
@@ -158,15 +162,21 @@ public class MemoryCardItem extends AEBaseItem implements IMemoryCard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
public ActionResult onItemUseFirst(ItemStack stack, ItemUsageContext context) {
|
||||
if (context.getPlayer().isInSneakingPose()) {
|
||||
// Bypass the memory card's own use handler and go straight to the block
|
||||
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;
|
||||
} else {
|
||||
return super.useOnBlock(context);
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,15 +190,10 @@ public class MemoryCardItem extends AEBaseItem implements IMemoryCard {
|
||||
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) {
|
||||
final IMemoryCard mem = (IMemoryCard) player.getStackInHand(hand).getItem();
|
||||
mem.notifyUser(player, MemoryCardMessages.SETTINGS_CLEARED);
|
||||
player.getStackInHand(hand).setTag(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench,
|
||||
}
|
||||
|
||||
// FIXME FABRIC: No direct equivalent
|
||||
// FIXME FABRIC: Might already be handled by onItemUseFirst though
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public boolean doesSneakBypassUse(ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player) {
|
||||
// FIXME FABRIC return true;
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
package appeng.items.tools.quartz;
|
||||
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.QuartzKnifeContainer;
|
||||
import appeng.items.contents.QuartzKnifeObj;
|
||||
import appeng.mixins.RemainderSetter;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
@@ -48,8 +51,7 @@ public class QuartzCuttingKnifeItem extends AEBaseItem implements IGuiItem {
|
||||
@Override
|
||||
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
|
||||
if (Platform.isServer()) {
|
||||
// FIXME FABRIC ContainerOpener.openContainer(QuartzKnifeContainer.TYPE, p, ContainerLocator.forHand(p, hand));
|
||||
throw new IllegalStateException();
|
||||
ContainerOpener.openContainer(QuartzKnifeContainer.TYPE, p, ContainerLocator.forHand(p, hand));
|
||||
}
|
||||
p.swingHand(hand);
|
||||
return new TypedActionResult<>(ActionResult.SUCCESS, p.getStackInHand(hand));
|
||||
@@ -58,7 +60,6 @@ public class QuartzCuttingKnifeItem extends AEBaseItem implements IGuiItem {
|
||||
@Override
|
||||
public IGuiItemObject getGuiObject(final ItemStack is, int playerInventorySlot, final World world,
|
||||
final BlockPos pos) {
|
||||
// FIXME FABRIC return new QuartzKnifeObj(is);
|
||||
throw new IllegalStateException();
|
||||
return new QuartzKnifeObj(is);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,10 @@ public class GridStorage implements IGridStorage {
|
||||
}
|
||||
|
||||
public void saveState() {
|
||||
throw new IllegalStateException();
|
||||
// FIXME FABRIC final Grid currentGrid = (Grid) this.getGrid();
|
||||
// FIXME FABRIC if (currentGrid != null) {
|
||||
// FIXME FABRIC currentGrid.saveState();
|
||||
// FIXME FABRIC }
|
||||
final Grid currentGrid = (Grid) this.getGrid();
|
||||
if (currentGrid != null) {
|
||||
currentGrid.saveState();
|
||||
}
|
||||
}
|
||||
|
||||
public IGrid getGrid() {
|
||||
|
||||
@@ -95,8 +95,8 @@ public abstract class MBCalculator<TTile extends IAEMultiBlock<TCluster>, TClust
|
||||
}
|
||||
|
||||
try {
|
||||
final BlockPos.Mutable min = new BlockPos.Mutable(loc);
|
||||
final BlockPos.Mutable max = new BlockPos.Mutable(loc);
|
||||
final BlockPos.Mutable min = loc.mutableCopy();
|
||||
final BlockPos.Mutable max = loc.mutableCopy();
|
||||
|
||||
// find size of MB structure...
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (this.isValidTile(te)) {
|
||||
return true;
|
||||
|
||||
@@ -33,9 +33,9 @@ import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.MBCalculator;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
|
||||
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
|
||||
boolean storage = false;
|
||||
|
||||
for (BlockPos blockPos : BlockPos.getAllInBoxMutable(min, max)) {
|
||||
for (BlockPos blockPos : BlockPos.iterate(min, max)) {
|
||||
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(blockPos);
|
||||
|
||||
if (te == null || !te.isValid()) {
|
||||
@@ -82,7 +82,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
|
||||
|
||||
@Override
|
||||
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);
|
||||
te.updateStatus(c);
|
||||
c.addTile(te);
|
||||
@@ -90,7 +90,7 @@ public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, Craf
|
||||
|
||||
c.done();
|
||||
|
||||
final Iterator<CraftingTileEntity> i = c.getTiles();
|
||||
final Iterator<CraftingBlockEntity> i = c.getTiles();
|
||||
while (i.hasNext()) {
|
||||
final IGridHost gh = i.next();
|
||||
final IGridNode n = gh.getGridNode(AEPartLocation.INTERNAL);
|
||||
|
||||
@@ -183,7 +183,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<CraftingTileEntity> getTiles() {
|
||||
public Iterator<CraftingBlockEntity> getTiles() {
|
||||
return this.tiles.iterator();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.MBCalculator;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, Qua
|
||||
|
||||
byte num = 0;
|
||||
|
||||
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
|
||||
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p);
|
||||
for (BlockPos p : BlockPos.iterate(min, max)) {
|
||||
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(p);
|
||||
|
||||
if (te == null || !te.isValid()) {
|
||||
return false;
|
||||
@@ -87,7 +87,7 @@ public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, Qua
|
||||
byte num = 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);
|
||||
|
||||
num++;
|
||||
|
||||
@@ -20,6 +20,7 @@ package appeng.me.cluster.implementations;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -234,7 +235,7 @@ public class QuantumCluster implements ILocatable, IAECluster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<QuantumBridgeTileEntity> getTiles() {
|
||||
public Iterator<QuantumBridgeBlockEntity> getTiles() {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.MBCalculator;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity,
|
||||
@Override
|
||||
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
|
||||
|
||||
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
|
||||
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p);
|
||||
for (BlockPos p : BlockPos.iterate(min, max)) {
|
||||
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getBlockEntity(p);
|
||||
|
||||
if (te == null || !te.isValid()) {
|
||||
return false;
|
||||
@@ -60,8 +60,8 @@ public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity,
|
||||
|
||||
@Override
|
||||
public void updateTiles(final SpatialPylonCluster c, final World w, final BlockPos min, final BlockPos max) {
|
||||
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
|
||||
final SpatialPylonTileEntity te = (SpatialPylonTileEntity) w.getTileEntity(p);
|
||||
for (BlockPos p : BlockPos.iterate(min, max)) {
|
||||
final SpatialPylonBlockEntity te = (SpatialPylonBlockEntity) w.getBlockEntity(p);
|
||||
te.updateStatus(c);
|
||||
c.getLine().add(te);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class SpatialPylonCluster implements IAECluster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<SpatialPylonTileEntity> getTiles() {
|
||||
public Iterator<SpatialPylonBlockEntity> getTiles() {
|
||||
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());
|
||||
|
||||
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
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 1;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.parts.automation;
|
||||
|
||||
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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Built-in model for annihilation planes that supports connected textures.
|
||||
*/
|
||||
public class PlaneBakedModel implements BakedModel, IDynamicPartBakedModel {
|
||||
|
||||
private static final PlaneConnections DEFAULT_PERMUTATION = PlaneConnections.of(false, false, false, false);
|
||||
|
||||
private final Sprite frontTexture;
|
||||
|
||||
private final Map<PlaneConnections, Mesh> meshes;
|
||||
|
||||
PlaneBakedModel(Sprite frontTexture, Sprite sidesTexture, Sprite backTexture) {
|
||||
this.frontTexture = frontTexture;
|
||||
|
||||
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
|
||||
meshes = new HashMap<>(PlaneConnections.PERMUTATIONS.size());
|
||||
// Create all possible permutations (16)
|
||||
for (PlaneConnections permutation : PlaneConnections.PERMUTATIONS) {
|
||||
|
||||
MeshBuilder meshBuilder = renderer.meshBuilder();
|
||||
|
||||
CubeBuilder builder = new CubeBuilder(meshBuilder.getEmitter());
|
||||
|
||||
builder.setTextures(sidesTexture, sidesTexture, frontTexture, backTexture, sidesTexture, sidesTexture);
|
||||
|
||||
// Keep the orientation of the X axis in mind here. When looking at a quad
|
||||
// facing north from the front,
|
||||
// The X-axis points left
|
||||
int minX = permutation.isRight() ? 0 : 1;
|
||||
int maxX = permutation.isLeft() ? 16 : 15;
|
||||
int minY = permutation.isDown() ? 0 : 1;
|
||||
int maxY = permutation.isUp() ? 16 : 15;
|
||||
|
||||
builder.addCube(minX, minY, 0, maxX, maxY, 1);
|
||||
|
||||
this.meshes.put(permutation, meshBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context, Direction partSide, @Nullable Object modelData) {
|
||||
PlaneConnections connections = DEFAULT_PERMUTATION;
|
||||
|
||||
if (modelData instanceof PlaneConnections) {
|
||||
connections = (PlaneConnections) modelData;
|
||||
}
|
||||
|
||||
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
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.frontTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.parts.automation;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Built-in model for annihilation planes that supports connected textures.
|
||||
*/
|
||||
public class PlaneModel implements BasicUnbakedModel {
|
||||
|
||||
private final SpriteIdentifier frontTexture;
|
||||
private final SpriteIdentifier sidesTexture;
|
||||
private final SpriteIdentifier backTexture;
|
||||
|
||||
public PlaneModel(Identifier frontTexture, Identifier sidesTexture, Identifier backTexture) {
|
||||
this.frontTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, frontTexture);
|
||||
this.sidesTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, sidesTexture);
|
||||
this.backTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, backTexture);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
Sprite frontSprite = textureGetter.apply(this.frontTexture);
|
||||
Sprite sidesSprite = textureGetter.apply(this.sidesTexture);
|
||||
Sprite backSprite = textureGetter.apply(this.backTexture);
|
||||
|
||||
return new PlaneBakedModel(frontSprite, sidesSprite, backSprite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(frontTexture, sidesTexture, backTexture);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.recipes.game;
|
||||
|
||||
import appeng.api.definitions.IBlocks;
|
||||
import appeng.api.definitions.IDefinitions;
|
||||
import appeng.api.definitions.IItemDefinition;
|
||||
import appeng.api.definitions.IItems;
|
||||
import appeng.api.definitions.IMaterials;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.core.Api;
|
||||
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;
|
||||
|
||||
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<>(
|
||||
DisassembleRecipe::new);
|
||||
|
||||
private static final ItemStack MISMATCHED_STACK = ItemStack.EMPTY;
|
||||
|
||||
private final Map<IItemDefinition, IItemDefinition> cellMappings;
|
||||
private final Map<IItemDefinition, IItemDefinition> nonCellMappings;
|
||||
|
||||
public DisassembleRecipe(Identifier id) {
|
||||
super(id);
|
||||
|
||||
final IDefinitions definitions = Api.instance().definitions();
|
||||
final IBlocks blocks = definitions.blocks();
|
||||
final IItems items = definitions.items();
|
||||
final IMaterials mats = definitions.materials();
|
||||
|
||||
this.cellMappings = new HashMap<>(4);
|
||||
this.nonCellMappings = new HashMap<>(5);
|
||||
|
||||
this.cellMappings.put(items.cell1k(), mats.cell1kPart());
|
||||
this.cellMappings.put(items.cell4k(), mats.cell4kPart());
|
||||
this.cellMappings.put(items.cell16k(), mats.cell16kPart());
|
||||
this.cellMappings.put(items.cell64k(), mats.cell64kPart());
|
||||
|
||||
this.nonCellMappings.put(items.encodedPattern(), mats.blankPattern());
|
||||
this.nonCellMappings.put(blocks.craftingStorage1k(), mats.cell1kPart());
|
||||
this.nonCellMappings.put(blocks.craftingStorage4k(), mats.cell4kPart());
|
||||
this.nonCellMappings.put(blocks.craftingStorage16k(), mats.cell16kPart());
|
||||
this.nonCellMappings.put(blocks.craftingStorage64k(), mats.cell64kPart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(@Nonnull final CraftingInventory inv, @Nonnull final World w) {
|
||||
return !this.getOutput(inv).isEmpty();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private ItemStack getOutput(final Inventory inventory) {
|
||||
int itemCount = 0;
|
||||
ItemStack output = MISMATCHED_STACK;
|
||||
|
||||
for (int slotIndex = 0; slotIndex < inventory.size(); slotIndex++) {
|
||||
final ItemStack stackInSlot = inventory.getStack(slotIndex);
|
||||
if (!stackInSlot.isEmpty()) {
|
||||
// needs a single input in the recipe
|
||||
itemCount++;
|
||||
if (itemCount > 1) {
|
||||
return MISMATCHED_STACK;
|
||||
}
|
||||
|
||||
// handle storage cells
|
||||
Optional<ItemStack> maybeCellOutput = this.getCellOutput(stackInSlot);
|
||||
if (maybeCellOutput.isPresent()) {
|
||||
ItemStack storageCellStack = maybeCellOutput.get();
|
||||
// make sure the storage cell stackInSlot empty...
|
||||
final IMEInventory<IAEItemStack> cellInv = Api.instance().registries().cell().getCellInventory(
|
||||
stackInSlot, null, Api.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
if (cellInv != null) {
|
||||
final IItemList<IAEItemStack> list = cellInv.getAvailableItems(
|
||||
Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createList());
|
||||
if (!list.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
output = storageCellStack;
|
||||
}
|
||||
|
||||
// handle crafting storage blocks
|
||||
output = this.getNonCellOutput(stackInSlot).orElse(output);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Optional<ItemStack> getCellOutput(final ItemStack compared) {
|
||||
for (final Map.Entry<IItemDefinition, IItemDefinition> entry : this.cellMappings.entrySet()) {
|
||||
if (entry.getKey().isSameAs(compared)) {
|
||||
return entry.getValue().maybeStack(1);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Optional<ItemStack> getNonCellOutput(final ItemStack compared) {
|
||||
for (final Map.Entry<IItemDefinition, IItemDefinition> entry : this.nonCellMappings.entrySet()) {
|
||||
if (entry.getKey().isSameAs(compared)) {
|
||||
return entry.getValue().maybeStack(1);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack craft(@Nonnull final CraftingInventory inv) {
|
||||
return this.getOutput(inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int i, int i1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public RecipeSerializer<DisassembleRecipe> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.recipes.game;
|
||||
|
||||
import appeng.api.definitions.IComparableDefinition;
|
||||
import appeng.api.definitions.IDefinitions;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.AppEng;
|
||||
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;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class FacadeRecipe extends SpecialCraftingRecipe {
|
||||
public static SpecialRecipeSerializer<FacadeRecipe> SERIALIZER = null;
|
||||
|
||||
private final IComparableDefinition anchor;
|
||||
private final FacadeItem facade;
|
||||
|
||||
public FacadeRecipe(Identifier id, FacadeItem facade) {
|
||||
super(id);
|
||||
this.facade = facade;
|
||||
final IDefinitions definitions = Api.instance().definitions();
|
||||
|
||||
this.anchor = definitions.parts().cableAnchor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(@Nonnull final CraftingInventory inv, @Nonnull final World w) {
|
||||
return !this.getOutput(inv, false).isEmpty();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private ItemStack getOutput(final Inventory inv, final boolean createFacade) {
|
||||
if (inv.getStack(0).isEmpty() && inv.getStack(2).isEmpty() && inv.getStack(6).isEmpty()
|
||||
&& inv.getStack(8).isEmpty()) {
|
||||
if (this.anchor.isSameAs(inv.getStack(1)) && this.anchor.isSameAs(inv.getStack(3))
|
||||
&& this.anchor.isSameAs(inv.getStack(5)) && this.anchor.isSameAs(inv.getStack(7))) {
|
||||
final ItemStack facades = this.facade.createFacadeForItem(inv.getStack(4), !createFacade);
|
||||
if (!facades.isEmpty() && createFacade) {
|
||||
facades.setCount(4);
|
||||
}
|
||||
return facades;
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(@Nonnull final CraftingInventory inv) {
|
||||
return this.getOutput(inv, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int i, int i1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public RecipeSerializer<FacadeRecipe> getSerializer() {
|
||||
return getSerializer(facade);
|
||||
}
|
||||
|
||||
public static RecipeSerializer<FacadeRecipe> getSerializer(FacadeItem facade) {
|
||||
if (SERIALIZER == null) {
|
||||
SERIALIZER = new SpecialRecipeSerializer<>(id -> new FacadeRecipe(id, facade));
|
||||
}
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.math;
|
||||
|
||||
/**
|
||||
* @author covers1624
|
||||
*/
|
||||
public class InterpHelper {
|
||||
|
||||
private float[][] posCache = new float[4][2];
|
||||
private float[] valCache = new float[4];
|
||||
|
||||
private float x0;
|
||||
private float x1;
|
||||
private float y0;
|
||||
private float y1;
|
||||
|
||||
private float rX;
|
||||
private float rY;
|
||||
|
||||
private int p00;
|
||||
private int p10;
|
||||
private int p11;
|
||||
private int p01;
|
||||
|
||||
/**
|
||||
* Resets the interp helper with the given quad. Does not care what order the
|
||||
* vertices are in.
|
||||
*/
|
||||
public void reset(float dx0, float dy0, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) {
|
||||
|
||||
float[] vec0 = this.posCache[0];
|
||||
float[] vec1 = this.posCache[1];
|
||||
float[] vec2 = this.posCache[2];
|
||||
float[] vec3 = this.posCache[3];
|
||||
|
||||
vec0[0] = dx0;
|
||||
vec1[0] = dx1;
|
||||
vec2[0] = dx2;
|
||||
vec3[0] = dx3;
|
||||
|
||||
vec0[1] = dy0;
|
||||
vec1[1] = dy1;
|
||||
vec2[1] = dy2;
|
||||
vec3[1] = dy3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when you are ready to use the InterpHelper.
|
||||
*/
|
||||
public void setup() {
|
||||
this.p00 = 0;// Bottom Left is always first.
|
||||
this.x0 = this.posCache[this.p00][0];
|
||||
this.y0 = this.posCache[this.p00][1];
|
||||
for (int i = 1; i < 4; i++) {
|
||||
float x = this.posCache[i][0];
|
||||
float y = this.posCache[i][1];
|
||||
if (this.y0 == y) {
|
||||
this.p10 = i;// Bottom right.
|
||||
this.x1 = x;
|
||||
} else if (this.x0 == x) {
|
||||
this.p01 = i;// Top left.
|
||||
this.y1 = y;
|
||||
} else {
|
||||
// Top right.
|
||||
this.p11 = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the coefficients for the interpolation.
|
||||
*
|
||||
* @param x X interp location.
|
||||
* @param y Y interp location.
|
||||
*/
|
||||
public void locate(float x, float y) {
|
||||
this.rX = (x - this.x0) / (this.x1 - this.x0);
|
||||
this.rY = (y - this.y0) / (this.y1 - this.y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates using the already computed coefficients.
|
||||
*
|
||||
* @param q0 Value at dx0 dy0
|
||||
* @param q1 Value at dx1 dy1
|
||||
* @param q2 Value at dx2 dy2
|
||||
* @param q3 Value at dx3 dy3
|
||||
*
|
||||
* @return The result.
|
||||
*/
|
||||
public float interpolate(float q0, float q1, float q2, float q3) {
|
||||
this.valCache[0] = q0;
|
||||
this.valCache[1] = q1;
|
||||
this.valCache[2] = q2;
|
||||
this.valCache[3] = q3;
|
||||
float f0 = (this.valCache[this.p00] * (1 - this.rX)) + (this.valCache[this.p10] * this.rX);
|
||||
float f1 = (this.valCache[this.p01] * (1 - this.rX)) + (this.valCache[this.p11] * this.rX);
|
||||
|
||||
return (f0 * (1 - this.rY)) + (f1 * this.rY);
|
||||
}
|
||||
}
|
||||
Vendored
+47
@@ -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;
|
||||
}
|
||||
}
|
||||
Vendored
+107
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
import static net.minecraft.util.math.Direction.AxisDirection.NEGATIVE;
|
||||
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
|
||||
|
||||
/**
|
||||
* This transformer is a little complicated. Basically a Facade / Cover can use
|
||||
* this to 'kick' the edges in of quads to fix z-Fighting in the corners. Use it
|
||||
* by specifying the side of the block you are on, the bitmask for where the
|
||||
* other Facades / Cover's are, the bounding box of the facade, NOT the hole
|
||||
* piece, and the thickness of your Facade / Cover, this is used as the kick
|
||||
* amount.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class QuadCornerKicker implements RenderContext.QuadTransform {
|
||||
|
||||
public static final QuadCornerKicker INSTANCE = new QuadCornerKicker();
|
||||
|
||||
// Simple horizonal lookups.
|
||||
public static int[][] horizonals = new int[][]{
|
||||
// Around Y axis, NSWE.
|
||||
{2, 3, 4, 5}, //
|
||||
{2, 3, 4, 5}, //
|
||||
|
||||
// Around Z axis, DUWE.
|
||||
{0, 1, 4, 5}, //
|
||||
{0, 1, 4, 5}, //
|
||||
|
||||
// Around X axis, DUNS.
|
||||
{0, 1, 2, 3}, //
|
||||
{0, 1, 2, 3}};
|
||||
|
||||
private int mySide;
|
||||
private int facadeMask;
|
||||
private Box box;
|
||||
private double thickness;
|
||||
|
||||
public QuadCornerKicker() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set's the side this Facade / Cover is attached to.
|
||||
*
|
||||
* @param side The side.
|
||||
*/
|
||||
public void setSide(int side) {
|
||||
this.mySide = side;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bitmask of Facades / Covers in the blockspace. This is as simple as,
|
||||
* mask = (1 << side)
|
||||
*
|
||||
* @param mask The mask.
|
||||
*/
|
||||
public void setFacadeMask(int mask) {
|
||||
this.facadeMask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounding box of the Facade / Cover, this should be the full box, not
|
||||
* just a piece of the hole's 'ring'.
|
||||
*
|
||||
* @param box The BoundingBox.
|
||||
*/
|
||||
public void setBox(Box box) {
|
||||
this.box = box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount to kick the vertex in by, this is your facades thickness.
|
||||
*
|
||||
* @param thickness The thickness.
|
||||
*/
|
||||
public void setThickness(double thickness) {
|
||||
this.thickness = thickness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transform(MutableQuadView quad) {
|
||||
int side = quad.nominalFace().ordinal();
|
||||
if (side != this.mySide && side != (this.mySide ^ 1)) {
|
||||
for (int hoz : horizonals[this.mySide]) {
|
||||
if (side != hoz && side != (hoz ^ 1)) {
|
||||
if ((this.facadeMask & (1 << hoz)) != 0) {
|
||||
Corner corner = Corner.fromSides(this.mySide ^ 1, side, hoz);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float x = quad.posByIndex(i, 0);
|
||||
float y = quad.posByIndex(i, 1);
|
||||
float z = quad.posByIndex(i, 2);
|
||||
if (epsComp(x, corner.pX(this.box)) && epsComp(y, corner.pY(this.box))
|
||||
&& epsComp(z, corner.pZ(this.box))) {
|
||||
Vec3i vec = Direction.values()[hoz].getVector();
|
||||
x -= vec.getX() * this.thickness;
|
||||
y -= vec.getY() * this.thickness;
|
||||
z -= vec.getZ() * this.thickness;
|
||||
quad.pos(i, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public enum Corner {
|
||||
|
||||
MIN_X_MIN_Y_MIN_Z(NEGATIVE, NEGATIVE, NEGATIVE), MIN_X_MIN_Y_MAX_Z(NEGATIVE, NEGATIVE, POSITIVE),
|
||||
MIN_X_MAX_Y_MIN_Z(NEGATIVE, POSITIVE, NEGATIVE), MIN_X_MAX_Y_MAX_Z(NEGATIVE, POSITIVE, POSITIVE),
|
||||
|
||||
MAX_X_MIN_Y_MIN_Z(POSITIVE, NEGATIVE, NEGATIVE), MAX_X_MIN_Y_MAX_Z(POSITIVE, NEGATIVE, POSITIVE),
|
||||
MAX_X_MAX_Y_MIN_Z(POSITIVE, POSITIVE, NEGATIVE), MAX_X_MAX_Y_MAX_Z(POSITIVE, POSITIVE, POSITIVE);
|
||||
|
||||
private AxisDirection xAxis;
|
||||
private AxisDirection yAxis;
|
||||
private AxisDirection zAxis;
|
||||
|
||||
private static final int[] sideMask = {0, 2, 0, 1, 0, 4};
|
||||
|
||||
Corner(AxisDirection xAxis, AxisDirection yAxis, AxisDirection zAxis) {
|
||||
this.xAxis = xAxis;
|
||||
this.yAxis = yAxis;
|
||||
this.zAxis = zAxis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find what corner is at the 3 sides. This method assumes you pass in
|
||||
* the X axis side, Y axis side, and Z axis side, it will NOT complain about an
|
||||
* invalid side, you will just get garbage data. This method also does not care
|
||||
* what order the 3 axes are in.
|
||||
*
|
||||
* @param sideA Side one.
|
||||
* @param sideB Side two.
|
||||
* @param sideC Side three.
|
||||
* @return The corner at the 3 sides.
|
||||
*/
|
||||
public static Corner fromSides(int sideA, int sideB, int sideC) {
|
||||
// <3 Chicken-Bones.
|
||||
return values()[sideMask[sideA] | sideMask[sideB] | sideMask[sideC]];
|
||||
}
|
||||
|
||||
public float pX(Box box) {
|
||||
return (float) (this.xAxis == NEGATIVE ? box.minX : box.maxX);
|
||||
}
|
||||
|
||||
public float pY(Box box) {
|
||||
return (float) (this.yAxis == NEGATIVE ? box.minY : box.maxY);
|
||||
}
|
||||
|
||||
public float pZ(Box box) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+107
@@ -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.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.AxisDirection;
|
||||
|
||||
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
|
||||
|
||||
/**
|
||||
* This transformer strips quads that are on faces. Simply set the bounds for
|
||||
* the faces, and the strip mask.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class QuadFaceStripper implements RenderContext.QuadTransform {
|
||||
|
||||
private Box bounds;
|
||||
private int mask;
|
||||
|
||||
QuadFaceStripper() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QuadFaceStripper(Box bounds, int mask) {
|
||||
this.bounds = bounds;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bounds of the faces, used as the .. bounds, if all vertices of a quad lay
|
||||
* on the bounds, it is up for stripping.
|
||||
*
|
||||
* @param bounds The bounds.
|
||||
*/
|
||||
public void setBounds(Box bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* The mask to strip edges. This is an opt in system, the mask is simple 'mask =
|
||||
* (1 << side)'.
|
||||
*
|
||||
* @param mask The mask.
|
||||
*/
|
||||
public void setMask(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transform(MutableQuadView quad) {
|
||||
if (this.mask == 0) {
|
||||
return true;// No mask, nothing changes.
|
||||
}
|
||||
// If the bit for this quad is set, then check if we should strip.
|
||||
Direction face = quad.nominalFace();
|
||||
if ((this.mask & (1 << face.ordinal())) != 0) {
|
||||
AxisDirection dir = face.getDirection();
|
||||
switch (face.getAxis()) {
|
||||
case X: {
|
||||
float bound = (float) (dir == POSITIVE ? this.bounds.maxX : this.bounds.minX);
|
||||
float x1 = quad.posByIndex(0, 0);
|
||||
float x2 = quad.posByIndex(1, 0);
|
||||
float x3 = quad.posByIndex(2, 0);
|
||||
float x4 = quad.posByIndex(3, 0);
|
||||
return x1 != x2 || x2 != x3 || x3 != x4 || x4 != bound;
|
||||
}
|
||||
case Y: {
|
||||
float bound = (float) (dir == POSITIVE ? this.bounds.maxY : this.bounds.minY);
|
||||
float y1 = quad.posByIndex(0, 1);
|
||||
float y2 = quad.posByIndex(1, 1);
|
||||
float y3 = quad.posByIndex(2, 1);
|
||||
float y4 = quad.posByIndex(3, 1);
|
||||
return y1 != y2 || y2 != y3 || y3 != y4 || y4 != bound;
|
||||
}
|
||||
case Z: {
|
||||
float bound = (float) (dir == POSITIVE ? this.bounds.maxZ : this.bounds.minZ);
|
||||
float z1 = quad.posByIndex(0, 2);
|
||||
float z2 = quad.posByIndex(1, 2);
|
||||
float z3 = quad.posByIndex(2, 2);
|
||||
float z4 = quad.posByIndex(3, 2);
|
||||
return z1 != z2 || z2 != z3 || z3 != z4 || z4 != bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.client.util.math.Vector4f;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
|
||||
/**
|
||||
* Created by covers1624 on 2/6/20.
|
||||
*/
|
||||
public class QuadMatrixTransformer implements RenderContext.QuadTransform {
|
||||
private static final Matrix4f identity;
|
||||
|
||||
static {
|
||||
identity = new Matrix4f();
|
||||
identity.loadIdentity();
|
||||
}
|
||||
|
||||
private final Vector3f storage3 = new Vector3f();
|
||||
private final Vector4f storage = new Vector4f();
|
||||
private Matrix4f matrix;
|
||||
private boolean identityMatrix;
|
||||
|
||||
QuadMatrixTransformer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QuadMatrixTransformer(Matrix4f matrix) {
|
||||
this.matrix = matrix;
|
||||
this.identityMatrix = matrix.equals(identity);
|
||||
}
|
||||
|
||||
public void setMatrix(Matrix4f matrix) {
|
||||
this.matrix = matrix;
|
||||
this.identityMatrix = matrix.equals(identity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transform(MutableQuadView quad) {
|
||||
if (identityMatrix) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quad.copyPos(i, storage3);
|
||||
storage.set(storage3.getX(), storage3.getY(), storage3.getZ(), 1);
|
||||
storage.transform(matrix);
|
||||
quad.pos(i, storage.getX(), storage.getY(), storage.getZ());
|
||||
|
||||
if (quad.hasNormal(i)) {
|
||||
quad.copyNormal(i, storage3);
|
||||
storage.set(storage3.getX(), storage3.getY(), storage3.getZ(), 0);
|
||||
storage.transform(matrix);
|
||||
storage.normalize();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Vendored
+180
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
|
||||
|
||||
/**
|
||||
* This transformer tints quads.. Feed it the output of
|
||||
* BlockColors.colorMultiplier.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class QuadTinter implements RenderContext.QuadTransform {
|
||||
|
||||
private int tint;
|
||||
|
||||
QuadTinter() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QuadTinter(int tint) {
|
||||
this.tint = tint | 0xFF000000;
|
||||
}
|
||||
|
||||
public QuadTinter setTint(int tint) {
|
||||
this.tint = tint;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transform(MutableQuadView quad) {
|
||||
// Nuke tintIndex.
|
||||
quad.colorIndex(-1);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int color = quad.spriteColor(i, 0);
|
||||
color = ColorHelper.multiplyColor(color, tint);
|
||||
quad.spriteColor(i, 0, color);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Optional;
|
||||
|
||||
import appeng.util.BlockUpdateFlag;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
@@ -251,15 +249,15 @@ public class CraftingBlockEntity extends AENetworkBlockEntity
|
||||
|
||||
final LinkedList<BlockPos> places = new LinkedList<>();
|
||||
|
||||
final Iterator<CraftingTileEntity> i = this.cluster.getTiles();
|
||||
final Iterator<CraftingBlockEntity> i = this.cluster.getTiles();
|
||||
while (i.hasNext()) {
|
||||
final CraftingTileEntity h = i.next();
|
||||
final CraftingBlockEntity h = i.next();
|
||||
if (h == this) {
|
||||
places.add(pos);
|
||||
} else {
|
||||
for (Direction d : Direction.values()) {
|
||||
BlockPos p = h.pos.offset(d);
|
||||
if (this.world.isAirBlock(p)) {
|
||||
if (this.world.isAir(p)) {
|
||||
places.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ import appeng.core.AppEng;
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAssemblerBlockEntity> {
|
||||
|
||||
public static final Identifier LIGHTS_MODEL = new Identifier(AppEng.MOD_ID,
|
||||
"block/molecular_assembler_lights");
|
||||
public static final ModelIdentifier LIGHTS_MODEL = new ModelIdentifier(AppEng.makeId(
|
||||
"block/molecular_assembler_lights"), "");
|
||||
|
||||
private static final RenderLayer MC_161917_RENDERTYPE_FIX = createRenderType();
|
||||
|
||||
@@ -93,7 +93,7 @@ public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAss
|
||||
// even the fully transparent part)
|
||||
// https://bugs.mojang.com/browse/MC-161917
|
||||
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);
|
||||
|
||||
minecraft.getBlockRenderManager().getModelRenderer().render(ms.peek(), buffer, null,
|
||||
|
||||
@@ -53,6 +53,7 @@ import appeng.api.util.AEColor;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.core.Api;
|
||||
import appeng.fluids.container.FluidTerminalContainer;
|
||||
import appeng.fluids.util.AEFluidStack;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
@@ -782,8 +783,7 @@ public class ChestBlockEntity extends AENetworkPowerBlockEntity
|
||||
}
|
||||
if (this.cellHandler.getChannel() == Api.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class)) {
|
||||
throw new IllegalStateException();
|
||||
// FIXME FABRIC return FluidTerminalContainer.TYPE;
|
||||
return FluidTerminalContainer.TYPE;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -39,6 +39,9 @@ import net.minecraft.util.math.Direction;
|
||||
*/
|
||||
public abstract class InventoryAdaptor implements Iterable<ItemSlot> {
|
||||
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()));
|
||||
|
||||
if (inv == ItemAttributes.FIXED_INV.defaultValue) {
|
||||
|
||||
Reference in New Issue
Block a user