Lots of fixes
This commit is contained in:
@@ -8,16 +8,94 @@ import appeng.bootstrap.ModelsReloadCallback;
|
||||
import appeng.bootstrap.components.IClientSetupComponent;
|
||||
import appeng.bootstrap.components.IItemColorRegistrationComponent;
|
||||
import appeng.bootstrap.components.IModelBakeComponent;
|
||||
import appeng.client.gui.implementations.*;
|
||||
import appeng.client.gui.implementations.CellWorkbenchScreen;
|
||||
import appeng.client.gui.implementations.ChestScreen;
|
||||
import appeng.client.gui.implementations.CondenserScreen;
|
||||
import appeng.client.gui.implementations.CraftAmountScreen;
|
||||
import appeng.client.gui.implementations.CraftConfirmScreen;
|
||||
import appeng.client.gui.implementations.CraftingCPUScreen;
|
||||
import appeng.client.gui.implementations.CraftingStatusScreen;
|
||||
import appeng.client.gui.implementations.CraftingTermScreen;
|
||||
import appeng.client.gui.implementations.DriveScreen;
|
||||
import appeng.client.gui.implementations.FormationPlaneScreen;
|
||||
import appeng.client.gui.implementations.GrinderScreen;
|
||||
import appeng.client.gui.implementations.IOPortScreen;
|
||||
import appeng.client.gui.implementations.InscriberScreen;
|
||||
import appeng.client.gui.implementations.InterfaceScreen;
|
||||
import appeng.client.gui.implementations.InterfaceTerminalScreen;
|
||||
import appeng.client.gui.implementations.LevelEmitterScreen;
|
||||
import appeng.client.gui.implementations.MEMonitorableScreen;
|
||||
import appeng.client.gui.implementations.MEPortableCellScreen;
|
||||
import appeng.client.gui.implementations.MolecularAssemblerScreen;
|
||||
import appeng.client.gui.implementations.NetworkStatusScreen;
|
||||
import appeng.client.gui.implementations.NetworkToolScreen;
|
||||
import appeng.client.gui.implementations.PatternTermScreen;
|
||||
import appeng.client.gui.implementations.PriorityScreen;
|
||||
import appeng.client.gui.implementations.QNBScreen;
|
||||
import appeng.client.gui.implementations.QuartzKnifeScreen;
|
||||
import appeng.client.gui.implementations.SecurityStationScreen;
|
||||
import appeng.client.gui.implementations.SkyChestScreen;
|
||||
import appeng.client.gui.implementations.SpatialIOPortScreen;
|
||||
import appeng.client.gui.implementations.StorageBusScreen;
|
||||
import appeng.client.gui.implementations.UpgradeableScreen;
|
||||
import appeng.client.gui.implementations.VibrationChamberScreen;
|
||||
import appeng.client.gui.implementations.WirelessScreen;
|
||||
import appeng.client.gui.implementations.WirelessTermScreen;
|
||||
import appeng.client.render.FacadeItemModel;
|
||||
import appeng.client.render.SimpleModelLoader;
|
||||
import appeng.client.render.cablebus.CableBusModelLoader;
|
||||
import appeng.client.render.cablebus.P2PTunnelFrequencyModel;
|
||||
import appeng.client.render.crafting.CraftingCubeModel;
|
||||
import appeng.client.render.effects.*;
|
||||
import appeng.client.render.model.*;
|
||||
import appeng.client.render.effects.ChargedOreFX;
|
||||
import appeng.client.render.effects.CraftingFx;
|
||||
import appeng.client.render.effects.EnergyFx;
|
||||
import appeng.client.render.effects.LightningArcFX;
|
||||
import appeng.client.render.effects.LightningFX;
|
||||
import appeng.client.render.effects.MatterCannonFX;
|
||||
import appeng.client.render.effects.ParticleTypes;
|
||||
import appeng.client.render.effects.VibrantFX;
|
||||
import appeng.client.render.model.BiometricCardModel;
|
||||
import appeng.client.render.model.ColorApplicatorModel;
|
||||
import appeng.client.render.model.DriveModel;
|
||||
import appeng.client.render.model.GlassModel;
|
||||
import appeng.client.render.model.MemoryCardModel;
|
||||
import appeng.client.render.model.SkyCompassModel;
|
||||
import appeng.client.render.spatial.SpatialPylonModel;
|
||||
import appeng.client.render.tesr.InscriberTESR;
|
||||
import appeng.client.render.tesr.SkyChestTESR;
|
||||
import appeng.container.implementations.*;
|
||||
import appeng.container.implementations.CellWorkbenchContainer;
|
||||
import appeng.container.implementations.ChestContainer;
|
||||
import appeng.container.implementations.CondenserContainer;
|
||||
import appeng.container.implementations.CraftAmountContainer;
|
||||
import appeng.container.implementations.CraftConfirmContainer;
|
||||
import appeng.container.implementations.CraftingCPUContainer;
|
||||
import appeng.container.implementations.CraftingStatusContainer;
|
||||
import appeng.container.implementations.CraftingTermContainer;
|
||||
import appeng.container.implementations.DriveContainer;
|
||||
import appeng.container.implementations.FormationPlaneContainer;
|
||||
import appeng.container.implementations.GrinderContainer;
|
||||
import appeng.container.implementations.IOPortContainer;
|
||||
import appeng.container.implementations.InscriberContainer;
|
||||
import appeng.container.implementations.InterfaceContainer;
|
||||
import appeng.container.implementations.InterfaceTerminalContainer;
|
||||
import appeng.container.implementations.LevelEmitterContainer;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.container.implementations.MEPortableCellContainer;
|
||||
import appeng.container.implementations.MolecularAssemblerContainer;
|
||||
import appeng.container.implementations.NetworkStatusContainer;
|
||||
import appeng.container.implementations.NetworkToolContainer;
|
||||
import appeng.container.implementations.PatternTermContainer;
|
||||
import appeng.container.implementations.PriorityContainer;
|
||||
import appeng.container.implementations.QNBContainer;
|
||||
import appeng.container.implementations.QuartzKnifeContainer;
|
||||
import appeng.container.implementations.SecurityStationContainer;
|
||||
import appeng.container.implementations.SkyChestContainer;
|
||||
import appeng.container.implementations.SpatialIOPortContainer;
|
||||
import appeng.container.implementations.StorageBusContainer;
|
||||
import appeng.container.implementations.UpgradeableContainer;
|
||||
import appeng.container.implementations.VibrationChamberContainer;
|
||||
import appeng.container.implementations.WirelessContainer;
|
||||
import appeng.container.implementations.WirelessTermContainer;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.ApiDefinitions;
|
||||
import appeng.core.AppEng;
|
||||
@@ -25,10 +103,26 @@ import appeng.core.AppEngBase;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.core.sync.network.ClientNetworkHandler;
|
||||
import appeng.core.worlddata.WorldData;
|
||||
import appeng.entity.*;
|
||||
import appeng.fluids.client.gui.*;
|
||||
import appeng.fluids.container.*;
|
||||
import appeng.entity.ChargedQuartzEntity;
|
||||
import appeng.entity.GrowingCrystalEntity;
|
||||
import appeng.entity.SingularityEntity;
|
||||
import appeng.entity.TinyTNTPrimedEntity;
|
||||
import appeng.entity.TinyTNTPrimedRenderer;
|
||||
import appeng.fluids.client.gui.FluidFormationPlaneScreen;
|
||||
import appeng.fluids.client.gui.FluidIOScreen;
|
||||
import appeng.fluids.client.gui.FluidInterfaceScreen;
|
||||
import appeng.fluids.client.gui.FluidLevelEmitterScreen;
|
||||
import appeng.fluids.client.gui.FluidStorageBusScreen;
|
||||
import appeng.fluids.client.gui.FluidTerminalScreen;
|
||||
import appeng.fluids.container.FluidFormationPlaneContainer;
|
||||
import appeng.fluids.container.FluidIOContainer;
|
||||
import appeng.fluids.container.FluidInterfaceContainer;
|
||||
import appeng.fluids.container.FluidLevelEmitterContainer;
|
||||
import appeng.fluids.container.FluidStorageBusContainer;
|
||||
import appeng.fluids.container.FluidTerminalContainer;
|
||||
import appeng.hooks.ClientTickHandler;
|
||||
import appeng.parts.automation.PlaneModel;
|
||||
import appeng.tile.crafting.MolecularAssemblerRenderer;
|
||||
import appeng.util.Platform;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
@@ -53,7 +147,11 @@ import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -240,6 +338,18 @@ public final class AppEngClient extends AppEngBase {
|
||||
|
||||
private void registerModelProviders() {
|
||||
|
||||
ModelLoadingRegistry.INSTANCE.registerAppender((resourceManager, consumer) -> {
|
||||
consumer.accept(MolecularAssemblerRenderer.LIGHTS_MODEL);
|
||||
});
|
||||
ModelLoadingRegistry.INSTANCE.registerVariantProvider((resourceManager) -> {
|
||||
return (modelIdentifier, modelProviderContext) -> {
|
||||
if (MolecularAssemblerRenderer.LIGHTS_MODEL.equals(modelIdentifier)) {
|
||||
return modelProviderContext.loadModel(new Identifier(modelIdentifier.getNamespace(), modelIdentifier.getPath()));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
});
|
||||
|
||||
ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> new CableBusModelLoader((PartModels) Api.INSTANCE.registries().partModels()));
|
||||
|
||||
addBuiltInModel("block/quartz_glass", GlassModel::new);
|
||||
@@ -249,14 +359,24 @@ public final class AppEngClient extends AppEngBase {
|
||||
addBuiltInModel("item/memory_card", MemoryCardModel::new);
|
||||
addBuiltInModel("item/biometric_card", BiometricCardModel::new);
|
||||
addBuiltInModel("block/drive", DriveModel::new);
|
||||
addBuiltInModel("color_applicator", ColorApplicatorModel::new); // FIXME need to wire this up
|
||||
addBuiltInModel("color_applicator", ColorApplicatorModel::new); // FIXME need to wire this up (this might just not be needed)
|
||||
addBuiltInModel("block/spatial_pylon", SpatialPylonModel::new);
|
||||
addBuiltInModel("block/paint", PaintSplotchesModel::new);
|
||||
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("facade", FacadeItemModel::new);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "part_plane"),
|
||||
// FIXME FABRIC PlaneModelLoader.INSTANCE);
|
||||
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
|
||||
addBuiltInModel("part/p2p/p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
|
||||
addBuiltInModel("item/facade", FacadeItemModel::new);
|
||||
|
||||
addPlaneModel("part/annihilation_plane", "part/annihilation_plane");
|
||||
addPlaneModel("part/annihilation_plane_on", "part/annihilation_plane_on");
|
||||
addPlaneModel("part/identity_annihilation_plane", "part/identity_annihilation_plane");
|
||||
addPlaneModel("part/identity_annihilation_plane_on", "part/identity_annihilation_plane_on");
|
||||
addPlaneModel("part/fluid_annihilation_plane", "part/fluid_annihilation_plane");
|
||||
addPlaneModel("part/fluid_annihilation_plane_on", "part/fluid_annihilation_plane_on");
|
||||
addPlaneModel("part/fluid_formation_plane", "part/fluid_formation_plane");
|
||||
addPlaneModel("part/fluid_formation_plane_on", "part/fluid_formation_plane_on");
|
||||
addPlaneModel("part/formation_plane", "part/formation_plane");
|
||||
addPlaneModel("part/formation_plane_on", "part/formation_plane_on");
|
||||
|
||||
addBuiltInModel("block/crafting/1k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_1K));
|
||||
addBuiltInModel("block/crafting/4k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_4K));
|
||||
addBuiltInModel("block/crafting/16k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_16K));
|
||||
@@ -267,9 +387,16 @@ public final class AppEngClient extends AppEngBase {
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "uvlightmap"), UVLModelLoader.INSTANCE);
|
||||
}
|
||||
|
||||
private static void addPlaneModel(String planeName, String frontTexture) {
|
||||
Identifier frontTextureId = AppEng.makeId(frontTexture);
|
||||
Identifier sidesTextureId = AppEng.makeId("part/plane_sides");
|
||||
Identifier backTextureId = AppEng.makeId("part/transition_plane_back");
|
||||
addBuiltInModel(planeName, () -> new PlaneModel(frontTextureId, sidesTextureId, backTextureId));
|
||||
}
|
||||
|
||||
private static <T extends UnbakedModel> void addBuiltInModel(String id, Supplier<T> modelFactory) {
|
||||
ModelLoadingRegistry.INSTANCE.registerResourceProvider(
|
||||
resourceManager -> new SimpleModelLoader<T>(AppEng.makeId(id), modelFactory)
|
||||
resourceManager -> new SimpleModelLoader<>(AppEng.makeId(id), modelFactory)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,43 +18,9 @@
|
||||
|
||||
package appeng.client.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import appeng.mixins.SlotMixin;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.util.Formatting;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.render.FluidRenderFace;
|
||||
import alexiil.mc.lib.attributes.fluid.render.FluidVolumeRenderer;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.client.gui.widgets.CustomSlotWidget;
|
||||
@@ -85,6 +51,41 @@ import appeng.core.sync.packets.SwapSlotsPacket;
|
||||
import appeng.fluids.client.render.FluidStackSizeRenderer;
|
||||
import appeng.fluids.container.slots.IMEFluidSlot;
|
||||
import appeng.helpers.InventoryAction;
|
||||
import appeng.mixins.SlotMixin;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScreen<T> {
|
||||
|
||||
@@ -189,7 +190,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
|
||||
final Text msg = tooltip.getMessage();
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
if (msg != null && !msg.getString().isEmpty()) {
|
||||
this.drawTooltip(matrices, x + 11, y + 4, msg);
|
||||
}
|
||||
}
|
||||
@@ -328,7 +329,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
// TODO 1.9.4 aftermath - Whole SlotActionType thing, to be checked.
|
||||
@Override
|
||||
protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton,
|
||||
final SlotActionType clickType) {
|
||||
final SlotActionType clickType) {
|
||||
final PlayerEntity player = getPlayer();
|
||||
|
||||
if (slot instanceof FakeSlot) {
|
||||
@@ -510,7 +511,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
|
||||
protected int getSlotIndex(Slot slot) {
|
||||
return ((SlotMixin)slot).getIndex();
|
||||
return ((SlotMixin) slot).getIndex();
|
||||
}
|
||||
|
||||
protected boolean checkHotbarKeys(int keyCode, int scanCode) {
|
||||
@@ -652,7 +653,16 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
final IAEFluidStack fs = slot.getAEFluidStack();
|
||||
|
||||
if (fs != null && this.isPowered()) {
|
||||
fs.getFluidStack().renderGuiRect(s.x, s.y, s.x + 16, s.y + 16);
|
||||
List<FluidRenderFace> faces = new ArrayList<>();
|
||||
faces.add(FluidRenderFace.createFlatFaceZ(0, 0, 0, 16, 16, 0, 1 / 16., false, false));
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(s.x, s.y, 0);
|
||||
|
||||
FluidVolume fluidStack = fs.getFluidStack();
|
||||
fluidStack.render(faces, FluidVolumeRenderer.VCPS, matrices);
|
||||
RenderSystem.runAsFancy(FluidVolumeRenderer.VCPS::draw);
|
||||
matrices.pop();
|
||||
|
||||
this.fluidStackSizeRenderer.renderStackSize(this.textRenderer, fs, s.x, s.y);
|
||||
} else if (!this.isPowered()) {
|
||||
@@ -786,7 +796,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
for (IGuiEventListener child : children) {
|
||||
for (Element child : children) {
|
||||
if (child instanceof ITickingWidget) {
|
||||
((ITickingWidget) child).tick();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ package appeng.client.gui.implementations;
|
||||
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
|
||||
this::onLevelChange);
|
||||
this.level.setTextFieldBounds(25, 44, 75);
|
||||
this.level.addButtons(children::add, this::addButton);
|
||||
container.setTextField(this.level);
|
||||
handler.setTextField(this.level);
|
||||
}
|
||||
|
||||
private void onLevelChange(long level) {
|
||||
@@ -100,7 +100,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
|
||||
|
||||
if (notCraftingMode) {
|
||||
if (currentLevelMode == LevelType.ENERGY_LEVEL) {
|
||||
this.font.drawString(PowerUnits.AE.textComponent().getString(), 110, 44, COLOR_DARK_GRAY);
|
||||
this.textRenderer.draw(matrices, PowerUnits.AE.textComponent().getString(), 110, 44, COLOR_DARK_GRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,17 @@ package appeng.client.gui.implementations;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.client.gui.NumberEntryType;
|
||||
import appeng.client.gui.widgets.ITickingWidget;
|
||||
import appeng.client.gui.widgets.NumberBox;
|
||||
import appeng.core.AEConfig;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
|
||||
/**
|
||||
* A utility widget that consists of a text-field to enter a number with
|
||||
@@ -26,14 +28,14 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
|
||||
private final NumberBox level;
|
||||
private final NumberEntryType type;
|
||||
private Button plus1;
|
||||
private Button plus10;
|
||||
private Button plus100;
|
||||
private Button plus1000;
|
||||
private Button minus1;
|
||||
private Button minus10;
|
||||
private Button minus100;
|
||||
private Button minus1000;
|
||||
private ButtonWidget plus1;
|
||||
private ButtonWidget plus10;
|
||||
private ButtonWidget plus100;
|
||||
private ButtonWidget plus1000;
|
||||
private ButtonWidget minus1;
|
||||
private ButtonWidget minus10;
|
||||
private ButtonWidget minus100;
|
||||
private ButtonWidget minus1000;
|
||||
|
||||
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
|
||||
LongConsumer changeListener) {
|
||||
@@ -42,20 +44,19 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
|
||||
FontRenderer font = parent.getMinecraft().fontRenderer;
|
||||
int inputX = parent.getGuiLeft() + x;
|
||||
int inputY = parent.getGuiTop() + y;
|
||||
this.level = new NumberBox(font, inputX, inputY, width, font.FONT_HEIGHT, type.getInputType(), changeListener);
|
||||
this.level.setEnableBackgroundDrawing(false);
|
||||
this.level.setMaxStringLength(16);
|
||||
this.level.setTextColor(0xFFFFFF);
|
||||
TextRenderer font = parent.getClient().textRenderer;
|
||||
int inputX = parent.getX() + x;
|
||||
int inputY = parent.getY() + y;
|
||||
this.level = new NumberBox(font, inputX, inputY, width, font.fontHeight, type.getInputType(), changeListener);
|
||||
this.level.setHasBorder(false);
|
||||
this.level.setMaxLength(16);
|
||||
this.level.setEditableColor(0xFFFFFF);
|
||||
this.level.setVisible(true);
|
||||
this.level.setFocused2(true);
|
||||
parent.setFocusedDefault(this.level);
|
||||
parent.setInitialFocus(this.level);
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.level.setEnabled(active);
|
||||
this.level.active = active;
|
||||
this.plus1.active = active;
|
||||
this.plus10.active = active;
|
||||
this.plus100.active = active;
|
||||
@@ -67,8 +68,8 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
}
|
||||
|
||||
public void setTextFieldBounds(int x, int y, int width) {
|
||||
this.level.x = parent.getGuiLeft() + x;
|
||||
this.level.y = parent.getGuiTop() + y;
|
||||
this.level.x = parent.getX() + x;
|
||||
this.level.y = parent.getY() + y;
|
||||
this.level.setWidth(width);
|
||||
}
|
||||
|
||||
@@ -76,28 +77,28 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
this.level.setMinValue(minValue);
|
||||
}
|
||||
|
||||
public void addButtons(Consumer<IGuiEventListener> addChildren, Consumer<Button> addButton) {
|
||||
public void addButtons(Consumer<Element> addChildren, Consumer<ButtonWidget> addButton) {
|
||||
final int[] steps = AEConfig.instance().getNumberEntrySteps(type);
|
||||
int a = steps[0];
|
||||
int b = steps[1];
|
||||
int c = steps[2];
|
||||
int d = steps[3];
|
||||
|
||||
int left = parent.getGuiLeft() + x;
|
||||
int top = parent.getGuiTop() + y;
|
||||
int left = parent.getX() + x;
|
||||
int top = parent.getY() + y;
|
||||
|
||||
addButton.accept(this.plus1 = new Button(left, top, 22, 20, "+" + a, btn -> addQty(a)));
|
||||
addButton.accept(this.plus10 = new Button(left + 28, top, 28, 20, "+" + b, btn -> addQty(b)));
|
||||
addButton.accept(this.plus100 = new Button(left + 62, top, 32, 20, "+" + c, btn -> addQty(c)));
|
||||
addButton.accept(this.plus1000 = new Button(left + 100, top, 38, 20, "+" + d, btn -> addQty(d)));
|
||||
addButton.accept(this.plus1 = new ButtonWidget(left, top, 22, 20, new LiteralText("+" + a), btn -> addQty(a)));
|
||||
addButton.accept(this.plus10 = new ButtonWidget(left + 28, top, 28, 20, new LiteralText("+" + b), btn -> addQty(b)));
|
||||
addButton.accept(this.plus100 = new ButtonWidget(left + 62, top, 32, 20, new LiteralText("+" + c), btn -> addQty(c)));
|
||||
addButton.accept(this.plus1000 = new ButtonWidget(left + 100, top, 38, 20, new LiteralText("+" + d), btn -> addQty(d)));
|
||||
|
||||
// Placing this here will give a sensible tab order
|
||||
addChildren.accept(this.level);
|
||||
|
||||
addButton.accept(this.minus1 = new Button(left, top + 42, 22, 20, "-" + a, btn -> addQty(-a)));
|
||||
addButton.accept(this.minus10 = new Button(left + 28, top + 42, 28, 20, "-" + b, btn -> addQty(-b)));
|
||||
addButton.accept(this.minus100 = new Button(left + 62, top + 42, 32, 20, "-" + c, btn -> addQty(-c)));
|
||||
addButton.accept(this.minus1000 = new Button(left + 100, top + 42, 38, 20, "-" + d, btn -> addQty(-d)));
|
||||
addButton.accept(this.minus1 = new ButtonWidget(left, top + 42, 22, 20, new LiteralText("-" + a), btn -> addQty(-a)));
|
||||
addButton.accept(this.minus10 = new ButtonWidget(left + 28, top + 42, 28, 20, new LiteralText("-" + b), btn -> addQty(-b)));
|
||||
addButton.accept(this.minus100 = new ButtonWidget(left + 62, top + 42, 32, 20, new LiteralText("-" + c), btn -> addQty(-c)));
|
||||
addButton.accept(this.minus1000 = new ButtonWidget(left + 100, top + 42, 38, 20, new LiteralText("-" + d), btn -> addQty(-d)));
|
||||
}
|
||||
|
||||
private void addQty(final long i) {
|
||||
@@ -106,8 +107,8 @@ public class NumberEntryWidget implements ITickingWidget {
|
||||
this.level.setText(String.valueOf(Math.max(minValue, currentValue + i)));
|
||||
}
|
||||
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
this.level.render(mouseX, mouseY, partialTicks);
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
|
||||
this.level.render(matrices, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
public void setValue(long value, boolean skipNotify) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
|
||||
this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY, this::onPriorityChange);
|
||||
this.priority.setTextFieldBounds(62, 57, 50);
|
||||
this.priority.setMinValue(Integer.MIN_VALUE);
|
||||
container.setTextField(this.priority);
|
||||
handler.setTextField(this.priority);
|
||||
this.priority.addButtons(children::add, this::addButton);
|
||||
|
||||
this.subGui.addBackButton(this::addButton, 154, 0);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package appeng.client.gui.widgets;
|
||||
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
/**
|
||||
* Indicates that a widget (anything that is in the {@link Screen#children()}
|
||||
* list) should receive callbacks every tick.
|
||||
*/
|
||||
public interface ITickingWidget {
|
||||
public interface ITickingWidget extends Element {
|
||||
|
||||
void tick();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class NumberBox extends TextFieldWidget {
|
||||
final Class<?> type, LongConsumer changeListener) {
|
||||
super(fontRenderer, x, y, width, height, new LiteralText("0"));
|
||||
this.setText("0");
|
||||
setResponder(this::onTextChanged);
|
||||
setChangedListener(this::onTextChanged);
|
||||
this.lastValue = 0;
|
||||
this.changeListener = changeListener;
|
||||
if (type == int.class || type == Integer.class) {
|
||||
|
||||
@@ -315,7 +315,7 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
|
||||
|
||||
return new LiteralText(name + '\n' + sb);
|
||||
}
|
||||
return "";
|
||||
return LiteralText.EMPTY;
|
||||
}
|
||||
|
||||
public String getFillVar() {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ToggleButton extends ButtonWidget implements ITooltip {
|
||||
|
||||
return new LiteralText(name + '\n' + sb);
|
||||
}
|
||||
return "";
|
||||
return LiteralText.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.render;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author DrummerMC
|
||||
* @version rv6 - 2018-01-22
|
||||
* @since rv6 2018-01-22
|
||||
*/
|
||||
public class DummyFluidBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private final FluidVolume volume;
|
||||
|
||||
public DummyFluidBakedModel(FluidVolume volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
// Not used as an item model
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
volume.renderGuiRect(0, 0, 16, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
|
||||
import appeng.client.render.cablebus.FacadeBuilder;
|
||||
|
||||
/**
|
||||
* This model used the provided FacadeBuilder to "slice" the item quads for the
|
||||
* facade provided.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBakedItemModel extends ForwardingBakedModel implements FabricBakedModel {
|
||||
|
||||
private final ItemStack textureStack;
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
private List<BakedQuad> quads = null;
|
||||
|
||||
protected FacadeBakedItemModel(BakedModel base, ItemStack textureStack, FacadeBuilder facadeBuilder) {
|
||||
this.wrapped = base;
|
||||
this.textureStack = textureStack;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
super.emitItemQuads(stack, randomSupplier, context);
|
||||
|
||||
if (quads == null) {
|
||||
quads = new ArrayList<>();
|
||||
quads.addAll(this.facadeBuilder.buildFacadeItemQuads(this.textureStack, Direction.NORTH));
|
||||
quads = Collections.unmodifiableList(quads);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.render;
|
||||
|
||||
import appeng.client.render.cablebus.FacadeBuilder;
|
||||
import appeng.items.parts.FacadeItem;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* This baked model class is used as a dispatcher to redirect the renderer to
|
||||
* the *real* model that should be used based on the item stack. A custom Item
|
||||
* Override List is used to accomplish this.
|
||||
*/
|
||||
public class FacadeDispatcherBakedModel extends ForwardingBakedModel {
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
private final Int2ObjectMap<FacadeBakedItemModel> cache = new Int2ObjectArrayMap<>();
|
||||
|
||||
public FacadeDispatcherBakedModel(BakedModel baseModel, FacadeBuilder facadeBuilder) {
|
||||
this.wrapped = baseModel;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
if (!(stack.getItem() instanceof FacadeItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FacadeItem itemFacade = (FacadeItem) stack.getItem();
|
||||
|
||||
ItemStack textureItem = itemFacade.getTextureItem(stack);
|
||||
|
||||
int itemId = Item.getRawId(textureItem.getItem());
|
||||
int hash = Objects.hash(itemId, textureItem.getTag());
|
||||
FacadeBakedItemModel model = FacadeDispatcherBakedModel.this.cache.get(hash);
|
||||
if (model == null) {
|
||||
model = new FacadeBakedItemModel(FacadeDispatcherBakedModel.this.wrapped, textureItem,
|
||||
FacadeDispatcherBakedModel.this.facadeBuilder);
|
||||
FacadeDispatcherBakedModel.this.cache.put(hash, model);
|
||||
}
|
||||
|
||||
context.fallbackConsumer().accept(model);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.render;
|
||||
|
||||
import appeng.client.render.cablebus.FacadeBuilder;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* The model class for facades. Since facades wrap existing models, they don't
|
||||
* declare any dependencies here other than the cable anchor.
|
||||
*/
|
||||
public class FacadeItemModel implements BasicUnbakedModel {
|
||||
|
||||
// We use this to get the default item transforms and make our lives easier
|
||||
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/facade_base");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
BakedModel bakedBaseModel = loader.bake(MODEL_BASE, rotationContainer);
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder(loader);
|
||||
|
||||
return new FacadeDispatcherBakedModel(bakedBaseModel, facadeBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return Collections.singleton(MODEL_BASE);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.api.parts.IDynamicPartBakedModel;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
@@ -25,17 +26,13 @@ import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
@@ -49,8 +46,14 @@ import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@@ -125,7 +128,11 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
}
|
||||
|
||||
context.pushTransform(QuadRotator.get(facing, Direction.UP));
|
||||
if (bakedModel instanceof FabricBakedModel) {
|
||||
if (bakedModel instanceof IDynamicPartBakedModel) {
|
||||
((IDynamicPartBakedModel) bakedModel).emitQuads(blockView, state, pos, randomSupplier, context,
|
||||
facing, partModelData);
|
||||
}
|
||||
else if (bakedModel instanceof FabricBakedModel) {
|
||||
((FabricBakedModel) bakedModel).emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
||||
} else {
|
||||
context.fallbackConsumer().accept(bakedModel);
|
||||
@@ -134,7 +141,8 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME this.facadeBuilder.buildFacadeQuads(layer, renderState, randomSupplier, context, this.partModels::get);
|
||||
Mesh mesh = this.facadeBuilder.getFacadeMesh(renderState, randomSupplier, this.partModels::get);
|
||||
context.meshConsumer().accept(mesh);
|
||||
}
|
||||
|
||||
// Determines whether a cable is connected to exactly two sides that are
|
||||
|
||||
@@ -67,7 +67,7 @@ public class CableBusModel implements BasicUnbakedModel {
|
||||
Map<Identifier, BakedModel> partModels = this.loadPartModels(loader, rotationContainer);
|
||||
|
||||
CableBuilder cableBuilder = new CableBuilder(textureGetter);
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder();
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder(loader);
|
||||
|
||||
// This should normally not be used, but we *have* to provide a particle texture
|
||||
// or otherwise damage models will
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.chunk.light.LightingProvider;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
|
||||
/**
|
||||
* This is used to retrieve the ExtendedState of a block for facade rendering.
|
||||
* It fakes the block at BlockPos provided as the BlockState provided.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBlockAccess implements BlockRenderView {
|
||||
|
||||
private final BlockRenderView world;
|
||||
private final BlockPos pos;
|
||||
private final Direction side;
|
||||
private final BlockState state;
|
||||
|
||||
public FacadeBlockAccess(BlockRenderView world, BlockPos pos, Direction side, BlockState state) {
|
||||
this.world = world;
|
||||
this.pos = pos;
|
||||
this.side = side;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||
return this.world.getBlockEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
if (this.pos == pos) {
|
||||
return this.state;
|
||||
}
|
||||
return this.world.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
return world.getFluidState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightingProvider getLightingProvider() {
|
||||
return world.getLightingProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBrightness(Direction direction, boolean shaded) {
|
||||
return world.getBrightness(direction, shaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor(BlockPos pos, ColorResolver colorResolver) {
|
||||
return world.getColor(pos, colorResolver);
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,42 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.api.util.AEAxisAlignedBB;
|
||||
import appeng.core.Api;
|
||||
import appeng.parts.misc.CableAnchorPart;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadClamper;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadCornerKicker;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStripper;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.render.model.ModelRotation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.Axis;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -28,31 +62,6 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.Axis;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
|
||||
import appeng.api.util.AEAxisAlignedBB;
|
||||
import appeng.core.Api;
|
||||
import appeng.parts.misc.CableAnchorPart;
|
||||
/**
|
||||
* The FacadeBuilder builds for facades..
|
||||
*
|
||||
@@ -60,43 +69,93 @@ import appeng.parts.misc.CableAnchorPart;
|
||||
*/
|
||||
public class FacadeBuilder {
|
||||
|
||||
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
|
||||
public static final double THICK_THICKNESS = 2D / 16D;
|
||||
public static final double THIN_THICKNESS = 1D / 16D;
|
||||
|
||||
public static final Box[] THICK_FACADE_BOXES = new Box[] {
|
||||
public static final Box[] THICK_FACADE_BOXES = new Box[]{
|
||||
new Box(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0),
|
||||
new Box(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0),
|
||||
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS),
|
||||
new Box(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0),
|
||||
new Box(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0),
|
||||
new Box(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
|
||||
new Box(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)};
|
||||
|
||||
public static final Box[] THIN_FACADE_BOXES = new Box[] {
|
||||
public static final Box[] THIN_FACADE_BOXES = new Box[]{
|
||||
new Box(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0),
|
||||
new Box(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0),
|
||||
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS),
|
||||
new Box(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0),
|
||||
new Box(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
|
||||
new Box(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
|
||||
new Box(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)};
|
||||
|
||||
//FIXME private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
|
||||
//FIXME // Clamper is responsible for clamping the vertex to the bounds specified.
|
||||
//FIXME .addElement("clamper", QuadClamper.FACTORY)
|
||||
//FIXME // Strips faces if they match a mask.
|
||||
//FIXME .addElement("face_stripper", QuadFaceStripper.FACTORY)
|
||||
//FIXME // Kicks the edge inner corners in, solves Z fighting
|
||||
//FIXME .addElement("corner_kicker", QuadCornerKicker.FACTORY)
|
||||
//FIXME // Re-Interpolates the UV's for the quad.
|
||||
//FIXME .addElement("interp", QuadReInterpolator.FACTORY)
|
||||
//FIXME // Tints the quad if we need it to. Disabled by default.
|
||||
//FIXME .addElement("tinter", QuadTinter.FACTORY, false)
|
||||
//FIXME // Overrides the quad's alpha if we are forcing transparent facades.
|
||||
//FIXME .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
|
||||
//FIXME );
|
||||
//FIXME private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
|
||||
private final Map<Direction, Mesh> cableAnchorStilts;
|
||||
|
||||
public void buildFacadeQuads(RenderLayer layer, CableBusRenderState renderState, Supplier<Random> rand,
|
||||
RenderContext context, Function<Identifier, BakedModel> modelLookup) {
|
||||
public FacadeBuilder(ModelLoader modelLoader) {
|
||||
cableAnchorStilts = buildCableAnchorStems(modelLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a map of pre-rotated cable anchor stilts, which are the shortened cable anchors that
|
||||
* will still be visible for facades attached to a cable.
|
||||
*/
|
||||
private Map<Direction, Mesh> buildCableAnchorStems(ModelLoader modelLoader) {
|
||||
Map<Direction, Mesh> stems = new EnumMap<>(Direction.class);
|
||||
|
||||
List<BakedModel> cableAnchorParts = new ArrayList<>();
|
||||
for (Identifier model : CableAnchorPart.FACADE_MODELS.getModels()) {
|
||||
BakedModel cableAnchor = modelLoader.bake(model, ModelRotation.X0_Y0);
|
||||
cableAnchorParts.add(cableAnchor);
|
||||
}
|
||||
|
||||
// Create pre-rotated variants of the cable anchor stems
|
||||
for (Direction side : Direction.values()) {
|
||||
RenderContext.QuadTransform rotator = QuadRotator.get(side, Direction.UP);
|
||||
|
||||
MeshBuilder meshBuilder = renderer.meshBuilder();
|
||||
QuadEmitter emitter = meshBuilder.getEmitter();
|
||||
|
||||
for (BakedModel model : cableAnchorParts) {
|
||||
for (int cullFaceIdx = 0; cullFaceIdx <= ModelHelper.NULL_FACE_ID; cullFaceIdx++) {
|
||||
Direction cullFace = ModelHelper.faceFromIndex(cullFaceIdx);
|
||||
List<BakedQuad> quads = model.getQuads(null, cullFace, new Random());
|
||||
for (BakedQuad quad : quads) {
|
||||
emitter.fromVanilla(quad.getVertexData(), 0, false);
|
||||
emitter.cullFace(cullFace);
|
||||
emitter.nominalFace(quad.getFace());
|
||||
if (!rotator.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
emitter.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stems.put(side, meshBuilder.build());
|
||||
}
|
||||
|
||||
return stems;
|
||||
}
|
||||
|
||||
// private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
|
||||
// // Clamper is responsible for clamping the vertex to the bounds specified.
|
||||
// .addElement("clamper", QuadClamper.FACTORY)
|
||||
// // Strips faces if they match a mask.
|
||||
// .addElement("face_stripper", QuadFaceStripper.FACTORY)
|
||||
// // Kicks the edge inner corners in, solves Z fighting
|
||||
// .addElement("corner_kicker", QuadCornerKicker.FACTORY)
|
||||
// // Re-Interpolates the UV's for the quad.
|
||||
// .addElement("interp", QuadReInterpolator.FACTORY)
|
||||
// // Tints the quad if we need it to. Disabled by default.
|
||||
// .addElement("tinter", QuadTinter.FACTORY, false)
|
||||
// // Overrides the quad's alpha if we are forcing transparent facades.
|
||||
// .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
|
||||
// );
|
||||
|
||||
public Mesh getFacadeMesh(CableBusRenderState renderState,
|
||||
Supplier<Random> rand,
|
||||
Function<Identifier, BakedModel> modelLookup) {
|
||||
//FIXME BakedPipeline pipeline = this.pipelines.get();
|
||||
//FIXME Quad collectorQuad = this.collectors.get();
|
||||
boolean transparent = Api.instance().partHelper().getCableRenderMode().transparentFacades;
|
||||
@@ -108,32 +167,29 @@ public class FacadeBuilder {
|
||||
BlockColors blockColors = MinecraftClient.getInstance().getBlockColors();
|
||||
boolean thinFacades = isUseThinFacades(partBoxes);
|
||||
|
||||
MeshBuilder meshBuilder = renderer.meshBuilder();
|
||||
QuadEmitter emitter = meshBuilder.getEmitter();
|
||||
|
||||
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
|
||||
Direction side = entry.getKey();
|
||||
int sideIndex = side.ordinal();
|
||||
FacadeRenderState facadeRenderState = entry.getValue();
|
||||
boolean renderStilt = !sidesWithParts.contains(side);
|
||||
if (layer == RenderLayer.getCutout() && renderStilt) {
|
||||
context.pushTransform(QuadRotator.get(side, Direction.UP));
|
||||
for (Identifier part : CableAnchorPart.FACADE_MODELS.getModels()) {
|
||||
BakedModel partModel = modelLookup.apply(part);
|
||||
context.fallbackConsumer().accept(partModel);
|
||||
}
|
||||
context.popTransform();
|
||||
}
|
||||
// If we are forcing transparency and this isn't the Translucent layer.
|
||||
if (transparent && layer != RenderLayer.getTranslucent()) {
|
||||
continue;
|
||||
if (renderStilt) {
|
||||
cableAnchorStilts.get(entry.getKey()).forEach(quad -> {
|
||||
quad.copyTo(emitter);
|
||||
emitter.emit();
|
||||
});
|
||||
}
|
||||
|
||||
BlockState blockState = facadeRenderState.getSourceBlock();
|
||||
// If we aren't forcing transparency let the block decide if it should render.
|
||||
if (!transparent && layer != null) {
|
||||
// FIXME FABRIC if (!transparent && layer != null) {
|
||||
// FIXME FABRIC only one layer per block
|
||||
// FIXME FABRIC if (!RenderLayers.canRenderInLayer(blockState, layer)) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
}
|
||||
// FIXME FABRIC }
|
||||
|
||||
Box fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
|
||||
Box facadeBox = fullBounds;
|
||||
@@ -179,97 +235,114 @@ public class FacadeBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the side mask.
|
||||
int facadeMask = 0;
|
||||
for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
|
||||
Direction s = ent.getKey();
|
||||
if (s.getAxis() != side.getAxis()) {
|
||||
FacadeRenderState otherState = ent.getValue();
|
||||
if (!otherState.isTransparent()) {
|
||||
facadeMask |= 1 << s.ordinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
|
||||
List<Box> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
|
||||
// FIXME BlockRenderView facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
|
||||
BlockRenderView facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
|
||||
|
||||
// FIXME FABRIC BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
|
||||
// FIXME FABRIC BakedModel model = dispatcher.getModel(blockState);
|
||||
// FIXME FABRIC IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// FIXME FABRIC // If we are forcing transparent facades, fake the render layer, and grab all
|
||||
// FIXME FABRIC // quads.
|
||||
// FIXME FABRIC if (transparent || layer == null) {
|
||||
// FIXME FABRIC for (RenderLayer forcedLayer : RenderLayer.getBlockRenderTypes()) {
|
||||
// FIXME FABRIC // Check if the block renders on the layer we want to force.
|
||||
// FIXME FABRIC if (RenderLayers.canRenderInLayer(blockState, forcedLayer)) {
|
||||
// FIXME FABRIC // Force the layer and gather quads.
|
||||
// FIXME FABRIC ForgeHooksClient.setRenderLayer(forcedLayer);
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Reset.
|
||||
// FIXME FABRIC ForgeHooksClient.setRenderLayer(layer);
|
||||
// FIXME FABRIC } else {
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // No quads.. Cool, next!
|
||||
// FIXME FABRIC if (modelQuads.isEmpty()) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Grab out pipeline elements.
|
||||
// FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
// FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
|
||||
// FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
// FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Set global element states.
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // calculate the side mask.
|
||||
// FIXME FABRIC int facadeMask = 0;
|
||||
// FIXME FABRIC for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
|
||||
// FIXME FABRIC Direction s = ent.getKey();
|
||||
// FIXME FABRIC if (s.getAxis() != side.getAxis()) {
|
||||
// FIXME FABRIC FacadeRenderState otherState = ent.getValue();
|
||||
// FIXME FABRIC if (!otherState.isTransparent()) {
|
||||
// FIXME FABRIC facadeMask |= 1 << s.ordinal();
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC // Setup the edge stripper.
|
||||
// FIXME FABRIC edgeStripper.setBounds(fullBounds);
|
||||
// FIXME FABRIC edgeStripper.setMask(facadeMask);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Setup the kicker.
|
||||
// FIXME FABRIC kicker.setSide(sideIndex);
|
||||
// FIXME FABRIC kicker.setFacadeMask(facadeMask);
|
||||
// FIXME FABRIC kicker.setBox(fullBounds);
|
||||
// FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC for (BakedQuad quad : modelQuads) {
|
||||
// FIXME FABRIC // lookup the format in CachedFormat.
|
||||
// FIXME FABRIC CachedFormat format = CachedFormat.lookup(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL);
|
||||
// FIXME FABRIC // If this quad has a tint index, setup the tinter.
|
||||
// FIXME FABRIC if (quad.hasTintIndex()) {
|
||||
// FIXME FABRIC tinter.setTint(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC for (Box box : holeStrips) {
|
||||
// FIXME FABRIC // setup the clamper for this box
|
||||
// FIXME FABRIC clamper.setClampBounds(box);
|
||||
// FIXME FABRIC // Reset the pipeline, clears all enabled/disabled states.
|
||||
// FIXME FABRIC pipeline.reset(format);
|
||||
// FIXME FABRIC // Reset out collector.
|
||||
// FIXME FABRIC collectorQuad.reset(format);
|
||||
// FIXME FABRIC // Enable / disable the optional elements
|
||||
// FIXME FABRIC pipeline.setElementState("tinter", quad.hasTintIndex());
|
||||
// FIXME FABRIC pipeline.setElementState("transparent", transparent);
|
||||
// FIXME FABRIC // Prepare the pipeline for a quad.
|
||||
// FIXME FABRIC pipeline.prepare(collectorQuad);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Pipe our quad into the pipeline.
|
||||
// FIXME FABRIC quad.pipe(pipeline);
|
||||
// FIXME FABRIC // Check if the collector got any data.
|
||||
// FIXME FABRIC if (collectorQuad.full) {
|
||||
// FIXME FABRIC // Add the result.
|
||||
// FIXME FABRIC quads.add(collectorQuad.bake());
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
|
||||
BakedModel model = dispatcher.getModel(blockState);
|
||||
|
||||
QuadFaceStripper faceStripper = new QuadFaceStripper(fullBounds, facadeMask);
|
||||
// Setup the kicker.
|
||||
QuadCornerKicker kicker = new QuadCornerKicker();
|
||||
kicker.setSide(sideIndex);
|
||||
kicker.setFacadeMask(facadeMask);
|
||||
kicker.setBox(fullBounds);
|
||||
kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
|
||||
QuadReInterpolator interpolator = new QuadReInterpolator();
|
||||
|
||||
for (int cullFaceIdx = 0; cullFaceIdx <= ModelHelper.NULL_FACE_ID; cullFaceIdx++) {
|
||||
Direction cullFace = ModelHelper.faceFromIndex(cullFaceIdx);
|
||||
List<BakedQuad> quads = model.getQuads(blockState, cullFace, rand.get());
|
||||
|
||||
for (BakedQuad quad : quads) {
|
||||
QuadTinter quadTinter = null;
|
||||
|
||||
// Prebake the color tint into the quad
|
||||
if (quad.getColorIndex() != -1) {
|
||||
quadTinter = new QuadTinter(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
|
||||
}
|
||||
|
||||
for (Box box : holeStrips) {
|
||||
emitter.fromVanilla(quad.getVertexData(), 0, false);
|
||||
emitter.cullFace(cullFace);
|
||||
emitter.nominalFace(quad.getFace());
|
||||
interpolator.setInputQuad(emitter);
|
||||
|
||||
QuadClamper clamper = new QuadClamper(box);
|
||||
if (!clamper.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Strips faces if they match a mask.
|
||||
if (!faceStripper.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Kicks the edge inner corners in, solves Z fighting
|
||||
if (!kicker.transform(emitter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
interpolator.transform(emitter);
|
||||
|
||||
// Tints the quad if we need it to. Disabled by default.
|
||||
if (quadTinter != null) {
|
||||
quadTinter.transform(emitter);
|
||||
}
|
||||
|
||||
// // Overrides the quad's alpha if we are forcing transparent facades.
|
||||
// .addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
|
||||
|
||||
emitter.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME FABRIC List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// FIXME FABRIC modelQuads.addAll(gatherQuads(model, blockState, rand));
|
||||
|
||||
// FIXME FABRIC // No quads.. Cool, next!
|
||||
// FIXME FABRIC if (modelQuads.isEmpty()) {
|
||||
// FIXME FABRIC continue;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Grab out pipeline elements.
|
||||
// FIXME FABRIC QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
// FIXME FABRIC QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
|
||||
// FIXME FABRIC QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
// FIXME FABRIC QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Set global element states.
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // Setup the kicker.
|
||||
// FIXME FABRIC kicker.setSide(sideIndex);
|
||||
// FIXME FABRIC kicker.setFacadeMask(facadeMask);
|
||||
// FIXME FABRIC kicker.setBox(fullBounds);
|
||||
// FIXME FABRIC kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC for (BakedQuad quad : modelQuads) {
|
||||
// FIXME FABRIC // lookup the format in CachedFormat.
|
||||
// FIXME FABRIC CachedFormat format = CachedFormat.lookup(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL);
|
||||
|
||||
// FIXME FABRIC }
|
||||
}
|
||||
|
||||
return meshBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,7 +435,6 @@ public class FacadeBuilder {
|
||||
* @param fb The Facade's box.
|
||||
* @param hole The hole to 'cut'.
|
||||
* @param axis The axis the facade is on.
|
||||
*
|
||||
* @return The box segments.
|
||||
*/
|
||||
private static List<Box> getBoxes(Box fb, AEAxisAlignedBB hole, Axis axis) {
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.api.parts.IDynamicPartBakedModel;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.util.Platform;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class P2PTunnelFrequencyBakedModel implements IDynamicPartBakedModel {
|
||||
|
||||
private final Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
|
||||
private final Sprite texture;
|
||||
|
||||
private final static Cache<Long, Mesh> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
|
||||
private static final int[][] QUAD_OFFSETS = new int[][]{{4, 10, 2}, {10, 10, 2}, {4, 4, 2}, {10, 4, 2}};
|
||||
|
||||
public P2PTunnelFrequencyBakedModel(final Sprite texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context,
|
||||
Direction partSide, @Nullable Object modelData) {
|
||||
if (!(modelData instanceof Long)) {
|
||||
return;
|
||||
}
|
||||
long frequency = (long) modelData;
|
||||
|
||||
Mesh frequencyMesh = getFrequencyModel(frequency);
|
||||
if (frequencyMesh != null) {
|
||||
context.meshConsumer().accept(frequencyMesh);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return ModelTransformation.NONE;
|
||||
}
|
||||
|
||||
private Mesh createFrequencyMesh(final short frequency, final boolean active) {
|
||||
|
||||
MeshBuilder meshBuilder = renderer.meshBuilder();
|
||||
|
||||
final AEColor[] colors = Platform.p2p().toColors(frequency);
|
||||
final CubeBuilder cb = new CubeBuilder(meshBuilder.getEmitter());
|
||||
|
||||
cb.setTexture(this.texture);
|
||||
cb.useStandardUV();
|
||||
cb.setRenderFullBright(active);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
final int[] offs = QUAD_OFFSETS[i];
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
final float[] cv = colors[j].dye.getColorComponents();
|
||||
if (active) {
|
||||
cb.setColorRGB(cv[0], cv[1], cv[2]);
|
||||
} else {
|
||||
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
|
||||
}
|
||||
|
||||
final int startx = j % 2;
|
||||
final int starty = 1 - j / 2;
|
||||
|
||||
cb.addCube(offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1,
|
||||
offs[2] + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return meshBuilder.build();
|
||||
}
|
||||
|
||||
private Mesh getFrequencyModel(long partFlags) {
|
||||
try {
|
||||
return modelCache.get(partFlags, () -> {
|
||||
short frequency = (short) (partFlags & 0xffffL);
|
||||
boolean active = (partFlags & 0x10000L) != 0;
|
||||
return this.createFrequencyMesh(frequency, active);
|
||||
});
|
||||
} catch (ExecutionException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
|
||||
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "part/p2p_tunnel_frequency"));
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
final Sprite texture = textureGetter.apply(TEXTURE);
|
||||
return new P2PTunnelFrequencyBakedModel(texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(TEXTURE);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user