Lots of fixes

This commit is contained in:
Sebastian Hartte
2020-07-23 02:38:32 +02:00
parent 1933b4b10d
commit 9fcfbf31be
100 changed files with 1771 additions and 1866 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ dependencies {
modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}"
modImplementation "alexiil.mc.lib:libblockattributes-all:0.7.0"
modImplementation "alexiil.mc.lib:libblockattributes-all:0.7.1-pre.4"
modImplementation "me.shedaniel:RoughlyEnoughItems:4.6.6"
modImplementation "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75"
@@ -0,0 +1,48 @@
package appeng.api.parts;
import appeng.api.util.AEPartLocation;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
/**
* This interface can be implemented by baked models returned by {@link IPart#getStaticModels()} to indicate that
* they would like to use the model data returned by {@link IPart#getModelData()}.
*/
public interface IDynamicPartBakedModel extends BakedModel {
/**
* See {@link net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel#emitBlockQuads(BlockRenderView, BlockState, BlockPos, Supplier, RenderContext)}
* for context.
* <p>
* The given <code>context</code> will already have been transformed so that the model renders from the
* rotated location the part is attached to.
*
* @param partSide The side of the cable bus that the part is attached to.
* @param modelData The model data returned by {@link IPart#getModelData()}
*/
void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context,
Direction partSide, @Nullable Object modelData);
/**
* Unless you use your dynamic model for other purposes, this method will not be called.
*/
@Override
default List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return Collections.emptyList();
}
}
@@ -141,7 +141,7 @@ public class AEBaseBlockItem extends BlockItem {
}
if (tile instanceof IGridProxyable) {
// 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
+142 -15
View File
@@ -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
@@ -18,35 +18,57 @@
package appeng.client.render;
import java.util.List;
import java.util.Random;
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 com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
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 {
private final ImmutableList<BakedQuad> quads;
public class DummyFluidBakedModel implements BakedModel, FabricBakedModel {
public DummyFluidBakedModel(ImmutableList<BakedQuad> quads) {
this.quads = quads;
private final FluidVolume volume;
public DummyFluidBakedModel(FluidVolume volume) {
this.volume = volume;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return this.quads;
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
@@ -75,7 +97,13 @@ public class DummyFluidBakedModel implements BakedModel {
}
@Override
public ModelOverrideList getOverrides() {
public ModelTransformation getTransformation() {
return null;
}
@Override
public ModelOverrideList getOverrides() {
return ModelOverrideList.EMPTY;
}
}
@@ -24,18 +24,14 @@ import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
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.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.EmptyModelData;
import appeng.client.render.cablebus.FacadeBuilder;
@@ -18,58 +18,58 @@
package appeng.client.render;
import java.util.Objects;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import appeng.client.render.cablebus.FacadeBuilder;
import appeng.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 DelegateBakedModel {
public class FacadeDispatcherBakedModel extends ForwardingBakedModel {
private final FacadeBuilder facadeBuilder;
private final Int2ObjectMap<FacadeBakedItemModel> cache = new Int2ObjectArrayMap<>();
public FacadeDispatcherBakedModel(BakedModel baseModel, FacadeBuilder facadeBuilder) {
super(baseModel);
this.wrapped = baseModel;
this.facadeBuilder = facadeBuilder;
}
@Override
public ModelOverrideList getOverrides() {
return new ModelOverrideList() {
@Override
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
if (!(stack.getItem() instanceof FacadeItem)) {
return originalModel;
}
public boolean isVanillaAdapter() {
return false;
}
FacadeItem itemFacade = (FacadeItem) stack.getItem();
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
if (!(stack.getItem() instanceof FacadeItem)) {
return;
}
ItemStack textureItem = itemFacade.getTextureItem(stack);
FacadeItem itemFacade = (FacadeItem) stack.getItem();
int hash = Objects.hash(textureItem.getItem().getRegistryName(), textureItem.getTag());
FacadeBakedItemModel model = FacadeDispatcherBakedModel.this.cache.get(hash);
if (model == null) {
model = new FacadeBakedItemModel(FacadeDispatcherBakedModel.this.getBaseModel(), textureItem,
FacadeDispatcherBakedModel.this.facadeBuilder);
FacadeDispatcherBakedModel.this.cache.put(hash, model);
}
ItemStack textureItem = itemFacade.getTextureItem(stack);
return model;
}
};
int itemId = Item.getRawId(textureItem.getItem());
int hash = Objects.hash(itemId, textureItem.getTag());
FacadeBakedItemModel model = FacadeDispatcherBakedModel.this.cache.get(hash);
if (model == null) {
model = new FacadeBakedItemModel(FacadeDispatcherBakedModel.this.wrapped, textureItem,
FacadeDispatcherBakedModel.this.facadeBuilder);
FacadeDispatcherBakedModel.this.cache.put(hash, model);
}
context.fallbackConsumer().accept(model);
}
}
@@ -18,22 +18,19 @@
package appeng.client.render;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.ModelOverrideList;
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 net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.client.render.cablebus.FacadeBuilder;
import appeng.core.AppEng;
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
@@ -44,20 +41,17 @@ 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(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
BakedModel bakedBaseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder();
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<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return modelGetter.apply(MODEL_BASE).getTextures(modelGetter, missingTextureErrors);
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
@@ -26,8 +26,8 @@ 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;
import net.minecraft.world.lighting.WorldLightManager;
/**
* This is used to retrieve the ExtendedState of a block for facade rendering.
@@ -69,12 +69,17 @@ public class FacadeBlockAccess implements BlockRenderView {
}
@Override
public WorldLightManager getLightingProvider() {
public LightingProvider getLightingProvider() {
return world.getLightingProvider();
}
@Override
public int getBlockColor(BlockPos blockPosIn, ColorResolver colorResolverIn) {
return world.getBlockColor(blockPosIn, colorResolverIn);
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) {
@@ -1,50 +1,68 @@
package appeng.client.render.cablebus;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import appeng.api.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;
public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
import javax.annotation.Nullable;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
public class P2PTunnelFrequencyBakedModel implements IDynamicPartBakedModel {
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
private final Sprite texture;
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
private final static Cache<Long, Mesh> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
private static final int[][] QUAD_OFFSETS = new int[][] { { 4, 10, 2 }, { 10, 10, 2 }, { 4, 4, 2 }, { 10, 4, 2 } };
private static final int[][] QUAD_OFFSETS = new int[][]{{4, 10, 2}, {10, 10, 2}, {4, 4, 2}, {10, 4, 2}};
public P2PTunnelFrequencyBakedModel(final Sprite texture) {
this.texture = texture;
}
@Override
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData modelData) {
if (side != null || !(modelData instanceof P2PTunnelFrequencyModelData)) {
return Collections.emptyList();
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;
P2PTunnelFrequencyModelData freqModelData = (P2PTunnelFrequencyModelData) modelData;
return this.getPartQuads(freqModelData.getFrequency());
Mesh frequencyMesh = getFrequencyModel(frequency);
if (frequencyMesh != null) {
context.meshConsumer().accept(frequencyMesh);
}
}
private List<BakedQuad> getQuadsForFrequency(final short frequency, final boolean active) {
@Override
public ModelTransformation getTransformation() {
return ModelTransformation.NONE;
}
private Mesh createFrequencyMesh(final short frequency, final boolean active) {
MeshBuilder meshBuilder = renderer.meshBuilder();
final AEColor[] colors = Platform.p2p().toColors(frequency);
final CubeBuilder cb = new CubeBuilder();
final CubeBuilder cb = new CubeBuilder(meshBuilder.getEmitter());
cb.setTexture(this.texture);
cb.useStandardUV();
@@ -53,11 +71,10 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
for (int i = 0; i < 4; ++i) {
final int[] offs = QUAD_OFFSETS[i];
for (int j = 0; j < 4; ++j) {
final AEColor c = colors[j];
final float[] cv = colors[j].dye.getColorComponents();
if (active) {
cb.setColorRGB(c.dye.getColorValue());
cb.setColorRGB(cv[0], cv[1], cv[2]);
} else {
final float[] cv = c.dye.getColorComponentValues();
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
}
@@ -69,18 +86,19 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
}
}
return cb.getOutput();
return meshBuilder.build();
}
private List<BakedQuad> getPartQuads(long partFlags) {
private Mesh getFrequencyModel(long partFlags) {
try {
return modelCache.get(partFlags, () -> {
short frequency = (short) (partFlags & 0xffffL);
boolean active = (partFlags & 0x10000L) != 0;
return this.getQuadsForFrequency(frequency, active);
return this.createFrequencyMesh(frequency, active);
});
} catch (ExecutionException e) {
return Collections.emptyList();
return null;
}
}
@@ -96,7 +114,7 @@ public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
@Override
public boolean isSideLit() {
return false;// TODO
return false;
}
@Override
@@ -0,0 +1,34 @@
package appeng.client.render.cablebus;
import appeng.client.render.BasicUnbakedModel;
import appeng.core.AppEng;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import javax.annotation.Nullable;
import java.util.function.Function;
import java.util.stream.Stream;
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "part/p2p_tunnel_frequency"));
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
final Sprite texture = textureGetter.apply(TEXTURE);
return new P2PTunnelFrequencyBakedModel(texture);
}
@Override
public Stream<SpriteIdentifier> getAdditionalTextures() {
return Stream.of(TEXTURE);
}
}
@@ -81,7 +81,7 @@ public class CraftingCPUContainer extends AEBaseContainer
}
if (te instanceof CraftingBlockEntity) {
this.setCPU(((CraftingTileEntity) te).getCluster());
this.setCPU(((CraftingBlockEntity) te).getCluster());
}
if (this.getNetwork() == null && Platform.isServer()) {
+262 -12
View File
@@ -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
+1 -1
View File
@@ -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();
}
}
}
+47 -19
View File
@@ -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);
}
}
+4 -5
View File
@@ -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;
@@ -18,47 +18,54 @@
package appeng.parts.automation;
import java.util.ArrayList;
import appeng.api.parts.IDynamicPartBakedModel;
import appeng.client.render.cablebus.CubeBuilder;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.client.render.cablebus.CubeBuilder;
import java.util.function.Supplier;
/**
* Built-in model for annihilation planes that supports connected textures.
*/
public class PlaneBakedModel implements IDynamicBakedModel {
public class PlaneBakedModel implements BakedModel, IDynamicPartBakedModel {
private static final PlaneConnections DEFAULT_PERMUTATION = PlaneConnections.of(false, false, false, false);
private final Sprite frontTexture;
private final Map<PlaneConnections, List<BakedQuad>> quads;
private final Map<PlaneConnections, Mesh> meshes;
PlaneBakedModel(Sprite frontTexture, Sprite sidesTexture, Sprite backTexture) {
this.frontTexture = frontTexture;
quads = new HashMap<>(PlaneConnections.PERMUTATIONS.size());
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
meshes = new HashMap<>(PlaneConnections.PERMUTATIONS.size());
// Create all possible permutations (16)
for (PlaneConnections permutation : PlaneConnections.PERMUTATIONS) {
List<BakedQuad> quads = new ArrayList<>(4 * 6);
CubeBuilder builder = new CubeBuilder(quads);
MeshBuilder meshBuilder = renderer.meshBuilder();
CubeBuilder builder = new CubeBuilder(meshBuilder.getEmitter());
builder.setTextures(sidesTexture, sidesTexture, frontTexture, backTexture, sidesTexture, sidesTexture);
@@ -72,22 +79,29 @@ public class PlaneBakedModel implements IDynamicBakedModel {
builder.addCube(minX, minY, 0, maxX, maxY, 1);
this.quads.put(permutation, ImmutableList.copyOf(quads));
this.meshes.put(permutation, meshBuilder.build());
}
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData modelData) {
if (side == null) {
PlaneConnections connections = DEFAULT_PERMUTATION;
if (modelData instanceof PlaneModelData) {
connections = ((PlaneModelData) modelData).getConnections();
}
return this.quads.get(connections);
} else {
return Collections.emptyList();
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
@@ -102,7 +116,7 @@ public class PlaneBakedModel implements IDynamicBakedModel {
@Override
public boolean isSideLit() {
return false;// TODO
return false;
}
@Override
@@ -18,24 +18,18 @@
package appeng.parts.automation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import appeng.client.render.BasicUnbakedModel;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import javax.annotation.Nullable;
import java.util.function.Function;
import java.util.stream.Stream;
/**
* Built-in model for annihilation planes that supports connected textures.
@@ -52,21 +46,19 @@ public class PlaneModel implements BasicUnbakedModel {
this.backTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, backTexture);
}
@Nullable
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
Sprite frontSprite = spriteGetter.apply(this.frontTexture);
Sprite sidesSprite = spriteGetter.apply(this.sidesTexture);
Sprite backSprite = spriteGetter.apply(this.backTexture);
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 Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Arrays.asList(frontTexture, sidesTexture, backTexture);
public Stream<SpriteIdentifier> getAdditionalTextures() {
return Stream.of(frontTexture, sidesTexture, backTexture);
}
}
@@ -18,21 +18,6 @@
package appeng.recipes.game;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.item.crafting.SpecialRecipe;
import net.minecraft.item.crafting.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IItemDefinition;
@@ -43,16 +28,24 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.Api;
import appeng.core.AppEng;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
public final class DisassembleRecipe extends SpecialRecipe {
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public final class DisassembleRecipe extends SpecialCraftingRecipe {
public static final RecipeSerializer<DisassembleRecipe> SERIALIZER = new SpecialRecipeSerializer<>(
DisassembleRecipe::new);
static {
SERIALIZER.setRegistryName(new Identifier(AppEng.MOD_ID, "disassemble"));
}
private static final ItemStack MISMATCHED_STACK = ItemStack.EMPTY;
private final Map<IItemDefinition, IItemDefinition> cellMappings;
@@ -155,7 +148,7 @@ public final class DisassembleRecipe extends SpecialRecipe {
}
@Override
public boolean canFit(int i, int i1) {
public boolean fits(int i, int i1) {
return false;
}
@@ -18,24 +18,23 @@
package appeng.recipes.game;
import javax.annotation.Nonnull;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.item.crafting.SpecialRecipe;
import net.minecraft.item.crafting.SpecialRecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import appeng.api.definitions.IComparableDefinition;
import appeng.api.definitions.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;
public final class FacadeRecipe extends SpecialRecipe {
import javax.annotation.Nonnull;
public final class FacadeRecipe extends SpecialCraftingRecipe {
public static SpecialRecipeSerializer<FacadeRecipe> SERIALIZER = null;
private final IComparableDefinition anchor;
@@ -77,7 +76,7 @@ public final class FacadeRecipe extends SpecialRecipe {
}
@Override
public boolean canFit(int i, int i1) {
public boolean fits(int i, int i1) {
return false;
}
@@ -90,7 +89,6 @@ public final class FacadeRecipe extends SpecialRecipe {
public static RecipeSerializer<FacadeRecipe> getSerializer(FacadeItem facade) {
if (SERIALIZER == null) {
SERIALIZER = new SpecialRecipeSerializer<>(id -> new FacadeRecipe(id, facade));
SERIALIZER.setRegistryName(new Identifier(AppEng.MOD_ID, "facade"));
}
return SERIALIZER;
}
@@ -0,0 +1,47 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
/**
* This transformer simply overrides the alpha of the quad.
*
* @author covers1624
*/
public class QuadAlphaOverride implements RenderContext.QuadTransform {
private static final int INV_ALPHA_MASK = 0x00_FF_FF_FF;
private final int alphaOverride;
public QuadAlphaOverride(float alphaOverride) {
this.alphaOverride = (int) (alphaOverride * 255) << 24;
}
@Override
public boolean transform(MutableQuadView quad) {
for (int i = 0; i < 4; i++) {
int color = (quad.spriteColor(i, 0) & INV_ALPHA_MASK) | alphaOverride;
quad.spriteColor(i, 0, color);
}
return true;
}
}
@@ -0,0 +1,107 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
/**
* This transformer simply clamps the vertices inside the provided box. You
* probably want to Re-Interpolate the UV's, Color, and Lmap, see
* {@link QuadReInterpolator}
*
* @author covers1624
*/
public class QuadClamper implements RenderContext.QuadTransform {
private final Box clampBounds;
private final Vector3f pos = new Vector3f();
public QuadClamper(Box clampBounds) {
this.clampBounds = clampBounds;
}
@Override
public boolean transform(MutableQuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
clamp(quad, this.clampBounds);
// Check if the quad would be invisible and cull it.
float x1 = quad.posByIndex(0, dx(s));
float x2 = quad.posByIndex(1, dx(s));
float x3 = quad.posByIndex(2, dx(s));
float x4 = quad.posByIndex(3, dx(s));
float y1 = quad.posByIndex(0, dy(s));
float y2 = quad.posByIndex(1, dy(s));
float y3 = quad.posByIndex(2, dy(s));
float y4 = quad.posByIndex(3, dy(s));
// These comparisons are safe as we are comparing clamped values.
boolean flag1 = x1 == x2 && x2 == x3 && x3 == x4;
boolean flag2 = y1 == y2 && y2 == y3 && y3 == y4;
return !flag1 && !flag2;
}
private void clamp(MutableQuadView quad, Box bb) {
for (int i = 0; i < 4; i++) {
quad.copyPos(i, pos);
pos.set(
(float) MathHelper.clamp(pos.getX(), bb.minX, bb.maxX),
(float) MathHelper.clamp(pos.getY(), bb.minY, bb.maxY),
(float) MathHelper.clamp(pos.getZ(), bb.minZ, bb.maxZ)
);
quad.pos(i, pos);
}
}
/**
* Gets the 2d X coord for the given axis.
*
* @param s The axis. side >> 1
* @return The x coord.
*/
private static int dx(int s) {
if (s <= 1) {
return 0;
} else {
return 2;
}
}
/**
* Gets the 2d Y coord for the given axis.
*
* @param s The axis. side >> 1
* @return The y coord.
*/
private static int dy(int s) {
if (s > 0) {
return 1;
} else {
return 2;
}
}
}
@@ -18,17 +18,15 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import static net.minecraft.util.math.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.AxisDirection;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3i;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
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
@@ -40,31 +38,30 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
*
* @author covers1624
*/
public class QuadCornerKicker extends QuadTransformer {
public class QuadCornerKicker implements RenderContext.QuadTransform {
// The factory for pipeline creation.
public static final IPipelineElementFactory<QuadCornerKicker> FACTORY = QuadCornerKicker::new;
public static final QuadCornerKicker INSTANCE = new QuadCornerKicker();
// Simple horizonal lookups.
public static int[][] horizonals = new int[][] {
public static int[][] horizonals = new int[][]{
// Around Y axis, NSWE.
{ 2, 3, 4, 5 }, //
{ 2, 3, 4, 5 }, //
{2, 3, 4, 5}, //
{2, 3, 4, 5}, //
// Around Z axis, DUWE.
{ 0, 1, 4, 5 }, //
{ 0, 1, 4, 5 }, //
{0, 1, 4, 5}, //
{0, 1, 4, 5}, //
// Around X axis, DUNS.
{ 0, 1, 2, 3 }, //
{ 0, 1, 2, 3 } };
{0, 1, 2, 3}, //
{0, 1, 2, 3}};
private int mySide;
private int facadeMask;
private Box box;
private double thickness;
QuadCornerKicker() {
public QuadCornerKicker() {
super();
}
@@ -107,27 +104,24 @@ public class QuadCornerKicker extends QuadTransformer {
}
@Override
public boolean transform() {
int side = this.quad.orientation.ordinal();
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 (Vertex vertex : this.quad.vertices) {
float x = vertex.vec[0];
float y = vertex.vec[1];
float z = vertex.vec[2];
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;
vertex.vec[0] = x;
vertex.vec[1] = y;
vertex.vec[2] = z;
quad.pos(i, x, y, z);
}
}
}
@@ -150,7 +144,7 @@ public class QuadCornerKicker extends QuadTransformer {
private AxisDirection yAxis;
private AxisDirection zAxis;
private static final int[] sideMask = { 0, 2, 0, 1, 0, 4 };
private static final int[] sideMask = {0, 2, 0, 1, 0, 4};
Corner(AxisDirection xAxis, AxisDirection yAxis, AxisDirection zAxis) {
this.xAxis = xAxis;
@@ -167,7 +161,6 @@ public class QuadCornerKicker extends QuadTransformer {
* @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) {
@@ -187,4 +180,16 @@ public class QuadCornerKicker extends QuadTransformer {
return (float) (this.zAxis == NEGATIVE ? box.minZ : box.maxZ);
}
}
// Should be small enough.
private final static double EPSILON = 0.00001;
private static boolean epsComp(float a, float b) {
if (a == b) {
return true;
} else {
return Math.abs(a - b) < EPSILON;
}
}
}
@@ -18,15 +18,13 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
import net.minecraft.util.math.Direction.AxisDirection;
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.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.AxisDirection;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
import static net.minecraft.util.math.Direction.AxisDirection.POSITIVE;
/**
* This transformer strips quads that are on faces. Simply set the bounds for
@@ -34,9 +32,7 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
*
* @author covers1624
*/
public class QuadFaceStripper extends QuadTransformer {
public static final IPipelineElementFactory<QuadFaceStripper> FACTORY = QuadFaceStripper::new;
public class QuadFaceStripper implements RenderContext.QuadTransform {
private Box bounds;
private int mask;
@@ -45,8 +41,7 @@ public class QuadFaceStripper extends QuadTransformer {
super();
}
public QuadFaceStripper(IVertexConsumer parent, Box bounds, int mask) {
super(parent);
public QuadFaceStripper(Box bounds, int mask) {
this.bounds = bounds;
this.mask = mask;
}
@@ -72,37 +67,37 @@ public class QuadFaceStripper extends QuadTransformer {
}
@Override
public boolean transform() {
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.
if ((this.mask & (1 << this.quad.orientation.ordinal())) != 0) {
AxisDirection dir = this.quad.orientation.getAxisDirection();
Vertex[] vertices = this.quad.vertices;
switch (this.quad.orientation.getAxis()) {
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 = vertices[0].vec[0];
float x2 = vertices[1].vec[0];
float x3 = vertices[2].vec[0];
float x4 = vertices[3].vec[0];
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 = vertices[0].vec[1];
float y2 = vertices[1].vec[1];
float y3 = vertices[2].vec[1];
float y4 = vertices[3].vec[1];
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 = vertices[0].vec[2];
float z2 = vertices[1].vec[2];
float z3 = vertices[2].vec[2];
float z4 = vertices[3].vec[2];
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;
}
}
@@ -18,20 +18,17 @@
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.Matrix4f;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
import net.minecraft.util.math.Matrix4f;
/**
* Created by covers1624 on 2/6/20.
*/
public class QuadMatrixTransformer extends QuadTransformer {
public static IPipelineElementFactory<QuadMatrixTransformer> FACTORY = QuadMatrixTransformer::new;
public class QuadMatrixTransformer implements RenderContext.QuadTransform {
private static final Matrix4f identity;
static {
@@ -39,6 +36,7 @@ public class QuadMatrixTransformer extends QuadTransformer {
identity.loadIdentity();
}
private final Vector3f storage3 = new Vector3f();
private final Vector4f storage = new Vector4f();
private Matrix4f matrix;
private boolean identityMatrix;
@@ -47,8 +45,7 @@ public class QuadMatrixTransformer extends QuadTransformer {
super();
}
public QuadMatrixTransformer(IVertexConsumer parent, Matrix4f matrix) {
super(parent);
public QuadMatrixTransformer(Matrix4f matrix) {
this.matrix = matrix;
this.identityMatrix = matrix.equals(identity);
}
@@ -59,26 +56,30 @@ public class QuadMatrixTransformer extends QuadTransformer {
}
@Override
public boolean transform() {
public boolean transform(MutableQuadView quad) {
if (identityMatrix) {
return true;
}
for (Quad.Vertex vertex : this.quad.vertices) {
storage.set(vertex.vec[0], vertex.vec[1], vertex.vec[2], 1);
for (int i = 0; i < 4; i++) {
quad.copyPos(i, storage3);
storage.set(storage3.getX(), storage3.getY(), storage3.getZ(), 1);
storage.transform(matrix);
vertex.vec[0] = storage.getX();
vertex.vec[1] = storage.getY();
vertex.vec[2] = storage.getZ();
quad.pos(i, storage.getX(), storage.getY(), storage.getZ());
storage.set(vertex.normal[0], vertex.normal[1], vertex.normal[2], 0);
storage.transform(matrix);
storage.normalize();
vertex.normal[0] = storage.getX();
vertex.normal[1] = storage.getY();
vertex.normal[2] = 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);
}
}
}
Quad.Vertex v0 = quad.vertices[0];
quad.orientation = Direction.getFacing(v0.normal[0], v0.normal[1], v0.normal[2]);
return true;
}
}
@@ -0,0 +1,180 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import appeng.thirdparty.codechicken.lib.math.InterpHelper;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
/**
* This transformer Re-Interpolates the Color, UV's and LightMaps. Use this
* after all transformations that translate vertices in the pipeline.
* <p>
* This Transformation can only be used in the BakedPipeline.
*
* @author covers1624
*/
public class QuadReInterpolator implements RenderContext.QuadTransform {
private final InterpHelper interpHelper = new InterpHelper();
private final MutableQuadViewImpl bufferQuad = new MutableQuadViewImpl() {
{
data = new int[EncodingFormat.TOTAL_STRIDE];
}
@Override
public QuadEmitter emit() {
throw new UnsupportedOperationException();
}
};
public QuadReInterpolator() {
super();
}
public void setInputQuad(QuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
int xIdx = dx(s);
int yIdx = dy(s);
interpHelper.reset( //
quad.posByIndex(0, xIdx), quad.posByIndex(0, yIdx), //
quad.posByIndex(1, xIdx), quad.posByIndex(1, yIdx), //
quad.posByIndex(2, xIdx), quad.posByIndex(2, yIdx), //
quad.posByIndex(3, xIdx), quad.posByIndex(3, yIdx));
quad.copyTo(bufferQuad);
}
@Override
public boolean transform(MutableQuadView quad) {
int s = quad.nominalFace().ordinal() >> 1;
int xIdx = dx(s);
int yIdx = dy(s);
this.interpHelper.setup();
for (int i = 0; i < 4; i++) {
float x = quad.posByIndex(i, xIdx);
float y = quad.posByIndex(i, yIdx);
this.interpHelper.locate(x, y);
interpColorFrom(quad, i);
interpUVFrom(quad, i);
interpLightMapFrom(quad, i);
}
return true;
}
/**
* Interpolates the new color values for this Vertex using the others as a
* reference.
*/
public void interpColorFrom(MutableQuadView quad, int vertexIndex) {
int p1 = bufferQuad.spriteColor(0, 0);
int p2 = bufferQuad.spriteColor(1, 0);
int p3 = bufferQuad.spriteColor(2, 0);
int p4 = bufferQuad.spriteColor(3, 0);
if (p1 == p2 && p2 == p3 && p3 == p4) {
return; // Don't bother for uniformly colored quads
}
// Interpolate each color component separately
int color = 0;
int mask = 0xFF;
for (int i = 0; i < 4; i++) {
float p1c = (float) (p1 & mask);
float p2c = (float) (p2 & mask);
float p3c = (float) (p3 & mask);
float p4c = (float) (p4 & mask);
int interp = (int) interpHelper.interpolate(p1c, p2c, p3c, p4c);
color |= interp & mask;
mask <<= 8;
}
quad.spriteColor(vertexIndex, 0, color);
}
/**
* Interpolates the new UV values for this Vertex using the others as a
* reference.
*/
public void interpUVFrom(MutableQuadView quad, int vertexIndex) {
float p1 = bufferQuad.spriteU(0, 0);
float p2 = bufferQuad.spriteU(1, 0);
float p3 = bufferQuad.spriteU(2, 0);
float p4 = bufferQuad.spriteU(3, 0);
float u = interpHelper.interpolate(p1, p2, p3, p4);
p1 = bufferQuad.spriteV(0, 0);
p2 = bufferQuad.spriteV(1, 0);
p3 = bufferQuad.spriteV(2, 0);
p4 = bufferQuad.spriteV(3, 0);
float v = interpHelper.interpolate(p1, p2, p3, p4);
quad.sprite(vertexIndex, 0, u, v);
}
/**
* Interpolates the new LightMap values for this Vertex using the others as a
* reference.
*
* @return The same Vertex.
*/
public void interpLightMapFrom(MutableQuadView quad, int vertexIndex) {
for (int e = 0; e < 2; e++) {
// FIXME float p1 = others[0].lightmap[e];
// FIXME float p2 = others[1].lightmap[e];
// FIXME float p3 = others[2].lightmap[e];
// FIXME float p4 = others[3].lightmap[e];
// FIXME if (p1 != p2 || p2 != p3 || p3 != p4) {
// FIXME this.lightmap[e] = interpHelper.interpolate(p1, p2, p3, p4);
// FIXME }
}
}
/**
* Gets the 2d X coord for the given axis.
*
* @param s The axis. side >> 1
* @return The x coord.
*/
private static int dx(int s) {
if (s <= 1) {
return 0;
} else {
return 2;
}
}
/**
* Gets the 2d Y coord for the given axis.
*
* @param s The axis. side >> 1
* @return The y coord.
*/
private static int dy(int s) {
if (s > 0) {
return 1;
} else {
return 2;
}
}
}
@@ -18,11 +18,9 @@
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
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
@@ -30,9 +28,7 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
*
* @author covers1624
*/
public class QuadTinter extends QuadTransformer {
public static final IPipelineElementFactory<QuadTinter> FACTORY = QuadTinter::new;
public class QuadTinter implements RenderContext.QuadTransform {
private int tint;
@@ -40,9 +36,8 @@ public class QuadTinter extends QuadTransformer {
super();
}
public QuadTinter(IVertexConsumer consumer, int tint) {
super(consumer);
this.tint = tint;
public QuadTinter(int tint) {
this.tint = tint | 0xFF000000;
}
public QuadTinter setTint(int tint) {
@@ -51,18 +46,13 @@ public class QuadTinter extends QuadTransformer {
}
@Override
public boolean transform() {
public boolean transform(MutableQuadView quad) {
// Nuke tintIndex.
this.quad.tintIndex = -1;
if (this.format.hasColor) {
float r = (this.tint >> 0x10 & 0xFF) / 255F;
float g = (this.tint >> 0x08 & 0xFF) / 255F;
float b = (this.tint & 0xFF) / 255F;
for (Vertex v : this.quad.vertices) {
v.color[0] *= r;
v.color[1] *= g;
v.color[2] *= b;
}
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) {
@@ -671,7 +671,7 @@
"item.appliedenergistics2.yellow_paint_ball": "Yellow Paint Ball",
"item.appliedenergistics2.yellow_smart_cable": "Yellow ME Smart Cable",
"item.appliedenergistics2.yellow_smart_dense_cable": "Yellow ME Dense Smart Cable",
"itemGroup.appliedenergistics2": "Applied Energistics 2",
"itemGroup.appliedenergistics2.main": "Applied Energistics 2",
"itemGroup.appliedenergistics2.facades": "Applied Energistics 2 - Facades",
"key.appliedenergistics2.category": "Applied Energistics 2",
"key.toggle_focus.desc": "Toggle search box focus",
@@ -1,3 +0,0 @@
{
"loader": "appliedenergistics2:facade"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_formation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/fluid_formation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/formation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/formation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/identity_annihilation_plane",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,6 +0,0 @@
{
"loader": "appliedenergistics2:part_plane",
"front": "appliedenergistics2:part/identity_annihilation_plane_on",
"sides": "appliedenergistics2:part/plane_sides",
"back": "appliedenergistics2:part/transition_plane_back"
}
@@ -1,3 +0,0 @@
{
"loader": "appliedenergistics2:p2p_tunnel_frequency"
}
@@ -12,7 +12,7 @@
"item": "minecraft:stone"
},
"d": {
"item": "minecraft:cobblestone"
"tag": "minecraft:stone_tool_materials"
},
"b": {
"tag": "appliedenergistics2:gears/wooden"
@@ -1,93 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
public abstract class DelegateBakedModel implements BakedModel {
private final BakedModel baseModel;
protected DelegateBakedModel(BakedModel base) {
this.baseModel = base;
}
@Override
@Deprecated
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return baseModel.getQuads(state, side, rand);
}
@Override
public boolean isSideLit() {
return baseModel.isSideLit();
}
@Override
public ModelOverrideList getOverrides() {
return baseModel.getOverrides();
}
@Override
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
baseModel.handlePerspective(cameraTransformType, mat);
return this;
}
@Override
public Sprite getSprite() {
return this.baseModel.getSprite();
}
@Override
public ModelTransformation getTransformation() {
return this.baseModel.getTransformation();
}
@Override
public boolean useAmbientOcclusion() {
return this.baseModel.useAmbientOcclusion();
}
@Override
public boolean hasDepth() {
return this.baseModel.hasDepth();
}
@Override
public boolean isBuiltin() {
return this.baseModel.isBuiltin();
}
public BakedModel getBaseModel() {
return this.baseModel;
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import net.minecraftforge.client.model.ItemLayerModel;
import net.minecraftforge.fluids.FluidAttributes;
import appeng.fluids.items.FluidDummyItem;
/**
* This baked model class is used as a dispatcher to redirect the renderer to
* the *real* model that should be used based on the item stack. A custom Item
* Override List is used to accomplish this.
*/
public class DummyFluidDispatcherBakedModel extends DelegateBakedModel {
private final Function<SpriteIdentifier, Sprite> bakedTextureGetter;
public DummyFluidDispatcherBakedModel(BakedModel baseModel,
Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
super(baseModel);
this.bakedTextureGetter = bakedTextureGetter;
}
// This is never used. See the item override list below.
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return Collections.emptyList();
}
@Override
public boolean hasDepth() {
return this.getBaseModel().hasDepth();
}
@Override
public boolean isSideLit() {
return getBaseModel().isSideLit();
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public ModelOverrideList getOverrides() {
return new ModelOverrideList() {
@Override
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
if (!(stack.getItem() instanceof FluidDummyItem)) {
return originalModel;
}
FluidDummyItem itemFacade = (FluidDummyItem) stack.getItem();
FluidVolume fluidStack = itemFacade.getFluidStack(stack);
if (fluidStack.isEmpty()) {
fluidStack = new FluidVolume(Fluids.WATER, FluidAttributes.BUCKET_VOLUME);
}
FluidAttributes attributes = fluidStack.getFluidKey().getAttributes();
Identifier stillTexture = attributes.getStillTexture(fluidStack);
SpriteIdentifier stillMaterial = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, stillTexture);
Sprite sprite = DummyFluidDispatcherBakedModel.this.bakedTextureGetter.apply(stillMaterial);
if (sprite == null) {
return new DummyFluidBakedModel(ImmutableList.of());
}
return new DummyFluidBakedModel(
ItemLayerModel.getQuadsForSprite(0, sprite, AffineTransformation.identity()));
}
};
}
}
@@ -1,46 +0,0 @@
package appeng.client.render.cablebus;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "parts/p2p_tunnel_frequency"));
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
try {
final Sprite texture = spriteGetter.apply(TEXTURE);
return new P2PTunnelFrequencyBakedModel(texture);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.singleton(TEXTURE);
}
}
@@ -1,134 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.List;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
/**
* Applies an arbitrary transformation matrix to the vertices of a quad.
*/
final class MatrixVertexTransformer extends QuadGatheringTransformer {
private final Matrix4f transform;
public MatrixVertexTransformer(Matrix4f transform) {
this.transform = transform;
}
@Override
protected void processQuad() {
VertexFormat format = this.parent.getVertexFormat();
List<VertexFormatElement> elements = format.getElements();
int count = elements.size();
for (int v = 0; v < 4; v++) {
for (int e = 0; e < count; e++) {
VertexFormatElement element = elements.get(e);
if (element.getType() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v], element.getElementCount()));
} else if (element.getType() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
}
}
}
}
@Override
public void setQuadTint(int tint) {
this.parent.setQuadTint(tint);
}
@Override
public void setQuadOrientation(Direction orientation) {
this.parent.setQuadOrientation(orientation);
}
@Override
public void setApplyDiffuseLighting(boolean diffuse) {
this.parent.setApplyDiffuseLighting(diffuse);
}
@Override
public void setTexture(Sprite texture) {
this.parent.setTexture(texture);
}
private float[] transform(float[] fs, int elemCount) {
switch (fs.length) {
case 3:
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
// Otherwise all translation is lost
if (elemCount == 3) {
vecc.setW(1);
}
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.transform);
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
default:
return fs;
}
}
private float[] transformNormal(float[] fs) {
Vector4f normal;
switch (fs.length) {
case 3:
normal = new Vector4f(fs[0], fs[1], fs[2], 0);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ() };
case 4:
normal = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ(), normal.getW() };
default:
return fs;
}
}
}
@@ -1,302 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core;
import appeng.bootstrap.ModelsReloadCallback;
import appeng.client.render.model.*;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.*;
import net.minecraft.client.gui.ScreenManager;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import net.minecraft.world.gen.placement.CountRangeConfig;
import net.minecraft.world.gen.placement.IPlacementConfig;
import net.minecraft.world.gen.placement.Placement;
import appeng.core.Api;
import appeng.api.config.Upgrades;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IItems;
import appeng.api.definitions.IParts;
import appeng.api.features.AEFeature;
import appeng.api.features.IRegistryContainer;
import appeng.api.features.IWirelessTermHandler;
import appeng.api.features.IWorldGen;
import appeng.api.movable.IMovableRegistry;
import appeng.core.features.registries.P2PTunnelRegistry;
import appeng.core.localization.GuiText;
import appeng.core.stats.AdvancementTriggers;
import appeng.server.AECommand;
import appeng.spatial.StorageCellBiome;
import appeng.spatial.StorageCellModDimension;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.crafting.MolecularAssemblerRenderer;
import appeng.worldgen.ChargedQuartzOreConfig;
import appeng.worldgen.ChargedQuartzOreFeature;
import appeng.worldgen.meteorite.MeteoriteStructure;
final class Registration {
public Registration() {
}
AdvancementTriggers advancementTriggers;
@Environment(EnvType.CLIENT)
public void modelRegistryEvent(ModelRegistryEvent event) {
registerSpecialModels();
}
/**
* Registers any JSON model files with Minecraft that are not referenced via
* blockstates or item IDs
*/
@Environment(EnvType.CLIENT)
private void registerSpecialModels() {
SkyCompassModel.DEPENDENCIES.forEach(ModelLoader::addSpecialModel);
ModelLoader.addSpecialModel(BiometricCardModel.MODEL_BASE);
ModelLoader.addSpecialModel(MemoryCardModel.MODEL_BASE);
DriveModel.DEPENDENCIES.forEach(ModelLoader::addSpecialModel);
ModelLoader.addSpecialModel(MolecularAssemblerRenderer.LIGHTS_MODEL);
}
// FIXME LATER
public static void postInit() {
final IRegistryContainer registries = AEApi.instance().registries();
// TODO: Do not use the internal API
ApiDefinitions definitions = Api.INSTANCE.definitions();
final IParts parts = definitions.parts();
final IBlocks blocks = definitions.blocks();
final IItems items = definitions.items();
// Block and part interface have different translation keys, but support the
// same upgrades
Text interfaceGroup = parts.iface().asItem().getName();
Text itemIoBusGroup = GuiText.IOBuses.text();
Text fluidIoBusGroup = GuiText.IOBusesFluids.text();
Text storageCellGroup = GuiText.IOBusesFluids.text();
// default settings..
((P2PTunnelRegistry) registries.p2pTunnel()).configure();
// Interface
Upgrades.CRAFTING.registerItem(parts.iface(), 1, interfaceGroup);
Upgrades.CRAFTING.registerItem(blocks.iface(), 1, interfaceGroup);
// IO Port!
Upgrades.SPEED.registerItem(blocks.iOPort(), 3);
Upgrades.REDSTONE.registerItem(blocks.iOPort(), 1);
// Level Emitter!
Upgrades.FUZZY.registerItem(parts.levelEmitter(), 1);
Upgrades.CRAFTING.registerItem(parts.levelEmitter(), 1);
// Import Bus
Upgrades.FUZZY.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.importBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.importBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.importBus(), 4, itemIoBusGroup);
// Fluid Import Bus
Upgrades.CAPACITY.registerItem(parts.fluidImportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidImportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidImportBus(), 4, fluidIoBusGroup);
// Export Bus
Upgrades.FUZZY.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.exportBus(), 1, itemIoBusGroup);
Upgrades.CAPACITY.registerItem(parts.exportBus(), 2, itemIoBusGroup);
Upgrades.SPEED.registerItem(parts.exportBus(), 4, itemIoBusGroup);
Upgrades.CRAFTING.registerItem(parts.exportBus(), 1, itemIoBusGroup);
// Fluid Export Bus
Upgrades.CAPACITY.registerItem(parts.fluidExportBus(), 2, fluidIoBusGroup);
Upgrades.REDSTONE.registerItem(parts.fluidExportBus(), 1, fluidIoBusGroup);
Upgrades.SPEED.registerItem(parts.fluidExportBus(), 4, fluidIoBusGroup);
// Storage Cells
Upgrades.FUZZY.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell1k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell4k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell16k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.cell64k(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.INVERTER.registerItem(items.portableCell(), 1, storageCellGroup);
Upgrades.FUZZY.registerItem(items.viewCell(), 1);
Upgrades.INVERTER.registerItem(items.viewCell(), 1);
// Storage Bus
Upgrades.FUZZY.registerItem(parts.storageBus(), 1);
Upgrades.INVERTER.registerItem(parts.storageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.storageBus(), 5);
// Storage Bus Fluids
Upgrades.INVERTER.registerItem(parts.fluidStorageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.fluidStorageBus(), 5);
// Formation Plane
Upgrades.FUZZY.registerItem(parts.formationPlane(), 1);
Upgrades.INVERTER.registerItem(parts.formationPlane(), 1);
Upgrades.CAPACITY.registerItem(parts.formationPlane(), 5);
// Matter Cannon
Upgrades.FUZZY.registerItem(items.massCannon(), 1);
Upgrades.INVERTER.registerItem(items.massCannon(), 1);
Upgrades.SPEED.registerItem(items.massCannon(), 4);
// Molecular Assembler
Upgrades.SPEED.registerItem(blocks.molecularAssembler(), 5);
// Inscriber
Upgrades.SPEED.registerItem(blocks.inscriber(), 3);
// Wireless Terminal Handler
items.wirelessTerminal().maybeItem()
.ifPresent(terminal -> registries.wireless().registerWirelessHandler((IWirelessTermHandler) terminal));
// Charge Rates
items.chargedStaff().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 320d));
items.portableCell().maybeItem()
.ifPresent(chargedStaff -> registries.charger().addChargeRate(chargedStaff, 800d));
items.colorApplicator().maybeItem()
.ifPresent(colorApplicator -> registries.charger().addChargeRate(colorApplicator, 800d));
items.wirelessTerminal().maybeItem().ifPresent(terminal -> registries.charger().addChargeRate(terminal, 8000d));
items.entropyManipulator().maybeItem()
.ifPresent(entropyManipulator -> registries.charger().addChargeRate(entropyManipulator, 8000d));
items.massCannon().maybeItem().ifPresent(massCannon -> registries.charger().addChargeRate(massCannon, 8000d));
blocks.energyCell().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 8000d));
blocks.energyCellDense().maybeItem().ifPresent(cell -> registries.charger().addChargeRate(cell, 16000d));
// FIXME // add villager trading to black smiths for a few basic materials
// FIXME if( AEConfig.instance().isFeatureEnabled( AEFeature.VILLAGER_TRADING ) )
// FIXME {
// FIXME // TODO: VILLAGER TRADING
// FIXME // VillagerRegistry.instance().getRegisteredVillagers().registerVillageTradeHandler( 3, new AETrading() );
// FIXME }
final IMovableRegistry mr = registries.movable();
/*
* You can't move bed rock.
*/
mr.blacklistBlock(net.minecraft.block.Blocks.BEDROCK);
/*
* White List Vanilla...
*/
mr.whiteListBlockEntity(BannerBlockEntity.class);
mr.whiteListBlockEntity(BeaconBlockEntity.class);
mr.whiteListBlockEntity(BrewingStandBlockEntity.class);
mr.whiteListBlockEntity(ChestBlockEntity.class);
mr.whiteListBlockEntity(CommandBlockBlockEntity.class);
mr.whiteListBlockEntity(ComparatorBlockEntity.class);
mr.whiteListBlockEntity(DaylightDetectorBlockEntity.class);
mr.whiteListBlockEntity(DispenserBlockEntity.class);
mr.whiteListBlockEntity(DropperBlockEntity.class);
mr.whiteListBlockEntity(EnchantingTableBlockEntity.class);
mr.whiteListBlockEntity(EnderChestBlockEntity.class);
mr.whiteListBlockEntity(EndPortalBlockEntity.class);
mr.whiteListBlockEntity(FurnaceBlockEntity.class);
mr.whiteListBlockEntity(HopperBlockEntity.class);
mr.whiteListBlockEntity(MobSpawnerBlockEntity.class);
mr.whiteListBlockEntity(PistonBlockEntity.class);
mr.whiteListBlockEntity(ShulkerBoxBlockEntity.class);
mr.whiteListBlockEntity(SignBlockEntity.class);
mr.whiteListBlockEntity(SkullBlockEntity.class);
/*
* Whitelist AE2
*/
mr.whiteListBlockEntity(AEBaseBlockEntity.class);
/*
* world gen
*/
for (final IWorldGen.WorldGenType type : IWorldGen.WorldGenType.values()) {
// FIXME: registries.worldgen().disableWorldGenForProviderID( type,
// StorageWorldProvider.class );
registries.worldgen().disableWorldGenForDimension(type, DimensionType.THE_NETHER_REGISTRY_KEY.getValue());
}
// whitelist from config
for (final String dimension : AEConfig.instance().getMeteoriteDimensionWhitelist()) {
registries.worldgen().enableWorldGenForDimension(IWorldGen.WorldGenType.METEORITES,
new Identifier(dimension));
}
Biome.BIOMES.forEach(b -> {
addMeteoriteWorldGen(b);
addQuartzWorldGen(b);
});
}
public void registerWorldGen(RegistryEvent.Register<Feature<?>> evt) {
IForgeRegistry<Feature<?>> r = evt.getRegistry();
// r.register(MeteoriteWorldGen.INSTANCE);
r.register(MeteoriteStructure.INSTANCE);
r.register(ChargedQuartzOreFeature.INSTANCE);
}
public void registerBiomes(RegistryEvent.Register<Biome> evt) {
evt.getRegistry().register(StorageCellBiome.INSTANCE);
}
public void registerModDimension(RegistryEvent.Register<ModDimension> evt) {
evt.getRegistry().register(StorageCellModDimension.INSTANCE);
}
public void registerCommands(final FMLServerStartingEvent evt) {
new AECommand().register(evt.getCommandDispatcher());
}
@Environment(EnvType.CLIENT)
public void registerClientEvents() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::registerParticleFactories);
modEventBus.addListener(this::registerTextures);
modEventBus.addListener(this::modelRegistryEvent);
modEventBus.addListener(this::registerItemColors);
ModelsReloadCallback.EVENT.register(this::onModelsReloaded);
}
}
@@ -1,28 +0,0 @@
package appeng.parts.automation;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelLoader;
public class PlaneModelLoader implements IModelLoader<PlaneModel> {
public static final PlaneModelLoader INSTANCE = new PlaneModelLoader();
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
}
@Override
public PlaneModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
String frontTexture = modelContents.get("front").getAsString();
String sidesTexture = modelContents.get("sides").getAsString();
String backTexture = modelContents.get("back").getAsString();
return new PlaneModel(new Identifier(frontTexture), new Identifier(sidesTexture),
new Identifier(backTexture));
}
}
@@ -18,14 +18,14 @@
package appeng.thirdparty.codechicken.lib.model;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.pipeline.VertexConsumer;
/**
* Marks a standard IVertexConsumer as compatible with {@link Quad}.
*
* @author covers1624
*/
public interface ISmartVertexConsumer extends IVertexConsumer {
public interface ISmartVertexConsumer extends VertexConsumer {
/**
* Assumes the data is already completely unpacked. You must always copy the
@@ -18,6 +18,8 @@
package appeng.thirdparty.codechicken.lib.model;
import appeng.thirdparty.codechicken.lib.model.pipeline.VertexConsumer;
import appeng.thirdparty.codechicken.lib.model.pipeline.VertexProducer;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.BakedQuad;
@@ -26,9 +28,6 @@ import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.IVertexProducer;
import net.minecraftforge.client.model.pipeline.LightUtil;
import appeng.thirdparty.codechicken.lib.math.InterpHelper;
@@ -38,7 +37,7 @@ import appeng.thirdparty.codechicken.lib.math.InterpHelper;
*
* @author covers1624
*/
public class Quad implements IVertexProducer, ISmartVertexConsumer {
public class Quad implements VertexProducer, ISmartVertexConsumer {
public CachedFormat format;
@@ -127,7 +126,7 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
}
@Override
public void pipe(IVertexConsumer consumer) {
public void pipe(VertexConsumer consumer) {
if (consumer instanceof ISmartVertexConsumer) {
((ISmartVertexConsumer) consumer).put(this);
} else {
@@ -175,19 +174,23 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
this.calculateOrientation(true);
}
private static void setVector(Vector3f to, float[] from) {
to.set(from[0], from[1], from[2]);
}
/**
* Re-calculates the Orientation of this quad, optionally the normal vector.
*
* @param setNormal If the normal vector should be updated.
*/
public void calculateOrientation(boolean setNormal) {
this.v1.set(this.vertices[3].vec);
this.t.set(this.vertices[1].vec);
this.v1.sub(this.t);
setVector(this.v1, this.vertices[3].vec);
setVector(this.t, this.vertices[1].vec);
this.v1.subtract(this.t);
this.v2.set(this.vertices[2].vec);
this.t.set(this.vertices[0].vec);
this.v2.sub(this.t);
setVector(this.v2, this.vertices[2].vec);
setVector(this.t, this.vertices[0].vec);
this.v2.subtract(this.t);
this.normal.set(this.v2.getX(), this.v2.getY(), this.v2.getZ());
this.normal.cross(this.v1);
@@ -278,10 +281,10 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
if (format.format != VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL) {
throw new IllegalStateException("Unable to bake this quad to the specified format. " + format.format);
}
int[] packedData = new int[this.format.format.getSize()];
int[] packedData = new int[this.format.format.getVertexSizeInteger()];
for (int v = 0; v < 4; v++) {
for (int e = 0; e < this.format.elementCount; e++) {
LightUtil.pack(this.vertices[v].raw[e], packedData, this.format.format, v, e);
// FIXME FABRIC LightUtil.pack(this.vertices[v].raw[e], packedData, this.format.format, v, e);
}
}
return new BakedQuad(packedData, this.tintIndex, this.orientation, this.sprite, this.diffuseLighting);
@@ -0,0 +1,14 @@
package appeng.thirdparty.codechicken.lib.model.pipeline;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
public interface VertexConsumer {
VertexFormat getVertexFormat();
void setQuadTint(int tint);
void setQuadOrientation(Direction orientation);
void setApplyDiffuseLighting(boolean diffuse);
void setTexture(Sprite texture);
void put(int element, float... data);
}
@@ -0,0 +1,5 @@
package appeng.thirdparty.codechicken.lib.model.pipeline;
public interface VertexProducer {
void pipe(VertexConsumer consumer);
}
@@ -1,62 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer simply overrides the alpha of the quad. Only operates if the
* format has color.
*
* @author covers1624
*/
public class QuadAlphaOverride extends QuadTransformer {
public static final IPipelineElementFactory<QuadAlphaOverride> FACTORY = QuadAlphaOverride::new;
private float alphaOverride;
QuadAlphaOverride() {
super();
}
public QuadAlphaOverride(IVertexConsumer consumer, float alphaOverride) {
super(consumer);
this.alphaOverride = alphaOverride;
}
public QuadAlphaOverride setAlphaOverride(float alphaOverride) {
this.alphaOverride = alphaOverride;
return this;
}
@Override
public boolean transform() {
if (this.format.hasColor) {
for (Vertex v : this.quad.vertices) {
v.color[3] = this.alphaOverride;
}
}
return true;
}
}
@@ -1,77 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import net.minecraft.util.math.Box;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer simply clamps the vertices inside the provided box. You
* probably want to Re-Interpolate the UV's, Color, and Lmap, see
* {@link QuadReInterpolator}
*
* @author covers1624
*/
public class QuadClamper extends QuadTransformer {
public static IPipelineElementFactory<QuadClamper> FACTORY = QuadClamper::new;
private Box clampBounds;
QuadClamper() {
super();
}
public QuadClamper(IVertexConsumer parent, Box bounds) {
super(parent);
this.clampBounds = bounds;
}
public void setClampBounds(Box bounds) {
this.clampBounds = bounds;
}
@Override
public boolean transform() {
int s = this.quad.orientation.ordinal() >> 1;
this.quad.clamp(this.clampBounds);
// Check if the quad would be invisible and cull it.
Vertex[] vertices = this.quad.vertices;
float x1 = vertices[0].dx(s);
float x2 = vertices[1].dx(s);
float x3 = vertices[2].dx(s);
float x4 = vertices[3].dx(s);
float y1 = vertices[0].dy(s);
float y2 = vertices[1].dy(s);
float y3 = vertices[2].dy(s);
float y4 = vertices[3].dy(s);
// These comparisons are safe as we are comparing clamped values.
boolean flag1 = x1 == x2 && x2 == x3 && x3 == x4;
boolean flag2 = y1 == y2 && y2 == y3 && y3 == y4;
return !flag1 && !flag2;
}
}
@@ -1,80 +0,0 @@
/*
* This file is part of CodeChickenLib.
* Copyright (c) 2018, covers1624, All rights reserved.
*
* CodeChickenLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* CodeChickenLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CodeChickenLib. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.thirdparty.codechicken.lib.model.pipeline.transformers;
import appeng.thirdparty.codechicken.lib.math.InterpHelper;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.Quad.Vertex;
import appeng.thirdparty.codechicken.lib.model.pipeline.IPipelineElementFactory;
import appeng.thirdparty.codechicken.lib.model.pipeline.QuadTransformer;
/**
* This transformer Re-Interpolates the Color, UV's and LightMaps. Use this
* after all transformations that translate vertices in the pipeline.
*
* This Transformation can only be used in the BakedPipeline.
*
* @author covers1624
*/
public class QuadReInterpolator extends QuadTransformer {
public static final IPipelineElementFactory<QuadReInterpolator> FACTORY = QuadReInterpolator::new;
private Quad interpCache = new Quad();
private InterpHelper interpHelper = new InterpHelper();
QuadReInterpolator() {
super();
}
@Override
public void reset(CachedFormat format) {
super.reset(format);
this.interpCache.reset(format);
}
@Override
public void setInputQuad(Quad quad) {
super.setInputQuad(quad);
quad.resetInterp(this.interpHelper, quad.orientation.ordinal() >> 1);
}
@Override
public boolean transform() {
int s = this.quad.orientation.ordinal() >> 1;
if (this.format.hasColor || this.format.hasUV || this.format.hasLightMap) {
this.interpCache.copyFrom(this.quad);
this.interpHelper.setup();
for (Vertex v : this.quad.vertices) {
this.interpHelper.locate(v.dx(s), v.dy(s));
if (this.format.hasColor) {
v.interpColorFrom(this.interpHelper, this.interpCache.vertices);
}
if (this.format.hasUV) {
v.interpUVFrom(this.interpHelper, this.interpCache.vertices);
}
if (this.format.hasLightMap) {
v.interpLightMapFrom(this.interpHelper, this.interpCache.vertices);
}
}
}
return true;
}
}