Modifier settings GUI for array and mirror, with header.

New parts in modifiers gui texture. 
Added reordering modifiers.
Replaced all icon rendering with AllIcons class.
Delayed blockset placing in server.
Modifiers now work when buildmode is DISABLED.
Modifiers now work with breaking when buildmode would break a single block.
Modifiers screen renders tooltip on top of everything.
New labeledScrollInput class, extension of Create's ScrollInput.
BlockPreviews ignores config settings to hide itself when placing more than 1 block.
Fixed mirroring wrong horizontal axis.
This commit is contained in:
Christian
2023-01-29 23:57:47 +01:00
parent c46ae91e99
commit 420b06d414
32 changed files with 651 additions and 314 deletions

View File

@@ -11,9 +11,14 @@ import nl.requios.effortlessbuilding.create.foundation.gui.element.ScreenElement
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
public enum AllGuiTextures implements ScreenElement {
ARRAY_ENTRY("modifiers", 256, 60),
MIRROR_ENTRY("modifiers", 0, 60, 256, 60),
RADIAL_MIRROR_ENTRY("modifiers", 0, 120, 256, 60),
ARRAY_ENTRY("modifiers", 226, 60),
MIRROR_ENTRY("modifiers", 0, 60, 226, 60),
RADIAL_MIRROR_ENTRY("modifiers", 0, 120, 226, 60),
ENABLE_BUTTON_BACKGROUND("modifiers", 234, 0, 9, 9),
CHECKMARK("modifiers", 243, 0, 10, 9),
ARROW_UP("modifiers", 234, 9, 9, 9),
ARROW_DOWN("modifiers", 243, 9, 9, 9),
TRASH("modifiers", 234, 18, 9, 9),
;
public final ResourceLocation location;
public int width, height;

View File

@@ -91,7 +91,6 @@ public class ClientEvents {
BuildModeEnum buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
if (mc.screen != null ||
buildMode == BuildModeEnum.DISABLED ||
RadialMenu.instance.isVisible()) {
return;
}

View File

@@ -13,6 +13,7 @@ import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import nl.requios.effortlessbuilding.systems.UndoRedo;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
@@ -32,8 +33,9 @@ public class CommonEvents {
@SubscribeEvent
public static void onTick(TickEvent.LevelTickEvent event) {
if (event.phase != TickEvent.Phase.START) return;
if (event.side == LogicalSide.CLIENT) return;
EffortlessBuilding.DELAYED_BLOCK_PLACER.tick();
EffortlessBuilding.SERVER_BLOCK_PLACER.tick();
}
//Cancel event if necessary. Nothing more, rest is handled on mouseclick
@@ -128,4 +130,4 @@ public class CommonEvents {
//TODO disable build mode and modifiers?
}
}
}

View File

@@ -22,7 +22,6 @@ import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.systems.DelayedBlockPlacer;
import nl.requios.effortlessbuilding.item.*;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
@@ -42,7 +41,6 @@ public class EffortlessBuilding {
public static IProxy proxy = DistExecutor.unsafeRunForDist(() -> ClientProxy::new, () -> ServerProxy::new);
public static final ServerBlockPlacer SERVER_BLOCK_PLACER = new ServerBlockPlacer();
public static final DelayedBlockPlacer DELAYED_BLOCK_PLACER = new DelayedBlockPlacer();
//Registration
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);

View File

@@ -1,20 +1,21 @@
package nl.requios.effortlessbuilding.buildmode;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.buildmode.buildmodes.*;
public enum BuildModeEnum {
DISABLED("normal", new Disabled(), BuildModeCategoryEnum.BASIC),
SINGLE("normal_plus", new Single(), BuildModeCategoryEnum.BASIC, ModeOptions.OptionEnum.BUILD_SPEED),
LINE("line", new Line(), BuildModeCategoryEnum.BASIC /*, OptionEnum.THICKNESS*/),
WALL("wall", new Wall(), BuildModeCategoryEnum.BASIC, ModeOptions.OptionEnum.FILL),
FLOOR("floor", new Floor(), BuildModeCategoryEnum.BASIC, ModeOptions.OptionEnum.FILL),
CUBE("cube", new Cube(), BuildModeCategoryEnum.BASIC, ModeOptions.OptionEnum.CUBE_FILL),
DIAGONAL_LINE("diagonal_line", new DiagonalLine(), BuildModeCategoryEnum.DIAGONAL /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("diagonal_wall", new DiagonalWall(), BuildModeCategoryEnum.DIAGONAL /*, OptionEnum.FILL*/),
SLOPE_FLOOR("slope_floor", new SlopeFloor(), BuildModeCategoryEnum.DIAGONAL, ModeOptions.OptionEnum.RAISED_EDGE),
CIRCLE("circle", new Circle(), BuildModeCategoryEnum.CIRCULAR, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL),
CYLINDER("cylinder", new Cylinder(), BuildModeCategoryEnum.CIRCULAR, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL),
SPHERE("sphere", new Sphere(), BuildModeCategoryEnum.CIRCULAR, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL);
DISABLED("normal", new Disabled(), BuildModeCategoryEnum.BASIC, AllIcons.I_DISABLE),
SINGLE("normal_plus", new Single(), BuildModeCategoryEnum.BASIC, AllIcons.I_SINGLE, ModeOptions.OptionEnum.BUILD_SPEED),
LINE("line", new Line(), BuildModeCategoryEnum.BASIC, AllIcons.I_LINE /*, OptionEnum.THICKNESS*/),
WALL("wall", new Wall(), BuildModeCategoryEnum.BASIC, AllIcons.I_WALL, ModeOptions.OptionEnum.FILL),
FLOOR("floor", new Floor(), BuildModeCategoryEnum.BASIC, AllIcons.I_FLOOR, ModeOptions.OptionEnum.FILL),
CUBE("cube", new Cube(), BuildModeCategoryEnum.BASIC, AllIcons.I_CUBE, ModeOptions.OptionEnum.CUBE_FILL),
DIAGONAL_LINE("diagonal_line", new DiagonalLine(), BuildModeCategoryEnum.DIAGONAL, AllIcons.I_DIAGONAL_LINE /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("diagonal_wall", new DiagonalWall(), BuildModeCategoryEnum.DIAGONAL, AllIcons.I_DIAGONAL_WALL /*, OptionEnum.FILL*/),
SLOPE_FLOOR("slope_floor", new SlopeFloor(), BuildModeCategoryEnum.DIAGONAL, AllIcons.I_SLOPED_FLOOR, ModeOptions.OptionEnum.RAISED_EDGE),
CIRCLE("circle", new Circle(), BuildModeCategoryEnum.CIRCULAR, AllIcons.I_CIRCLE, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL),
CYLINDER("cylinder", new Cylinder(), BuildModeCategoryEnum.CIRCULAR, AllIcons.I_CYLINDER, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL),
SPHERE("sphere", new Sphere(), BuildModeCategoryEnum.CIRCULAR, AllIcons.I_SPHERE, ModeOptions.OptionEnum.CIRCLE_START, ModeOptions.OptionEnum.FILL);
// PYRAMID("pyramid", new Pyramid(), BuildModeCategoryEnum.ROOF),
// CONE("cone", new Cone(), BuildModeCategoryEnum.ROOF),
// DOME("dome", new Dome(), BuildModeCategoryEnum.ROOF);
@@ -22,12 +23,14 @@ public enum BuildModeEnum {
private final String name;
public final IBuildMode instance;
public final BuildModeCategoryEnum category;
public final AllIcons icon;
public final ModeOptions.OptionEnum[] options;
BuildModeEnum(String name, IBuildMode instance, BuildModeCategoryEnum category, ModeOptions.OptionEnum... options) {
BuildModeEnum(String name, IBuildMode instance, BuildModeCategoryEnum category, AllIcons icon, ModeOptions.OptionEnum... options) {
this.name = name;
this.instance = instance;
this.category = category;
this.icon = icon;
this.options = options;
}

View File

@@ -3,6 +3,7 @@ package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.ClientEvents;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
@@ -104,46 +105,60 @@ public class ModeOptions {
action != ActionEnum.OPEN_MODIFIER_SETTINGS &&
action != ActionEnum.OPEN_PLAYER_SETTINGS) {
EffortlessBuilding.logTranslate(player, "", action.name, "", true);
EffortlessBuilding.logTranslate(player, "", action.getNameKey(), "", true);
}
}
public enum ActionEnum {
UNDO("effortlessbuilding.action.undo"),
REDO("effortlessbuilding.action.redo"),
OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"),
OPEN_PLAYER_SETTINGS("effortlessbuilding.action.open_player_settings"),
UNDO("undo", AllIcons.I_UNDO),
REDO("redo", AllIcons.I_REDO),
OPEN_MODIFIER_SETTINGS("open_modifier_settings", AllIcons.I_SETTINGS),
OPEN_PLAYER_SETTINGS("open_player_settings", AllIcons.I_SETTINGS),
REPLACE_ONLY_AIR("effortlessbuilding.action.replace_only_air"),
REPLACE_BLOCKS_AND_AIR("effortlessbuilding.action.replace_blocks_and_air"),
REPLACE_ONLY_BLOCKS("effortlessbuilding.action.replace_only_blocks"),
REPLACE_FILTERED_BY_OFFHAND("effortlessbuilding.action.replace_filtered_by_offhand"),
TOGGLE_PROTECT_TILE_ENTITIES("effortlessbuilding.action.toggle_protect_tile_entities"),
REPLACE_ONLY_AIR("replace_only_air", AllIcons.I_REPLACE),
REPLACE_BLOCKS_AND_AIR("replace_blocks_and_air", AllIcons.I_REPLACE),
REPLACE_ONLY_BLOCKS("replace_only_blocks", AllIcons.I_REPLACE),
REPLACE_FILTERED_BY_OFFHAND("replace_filtered_by_offhand", AllIcons.I_REPLACE),
TOGGLE_PROTECT_TILE_ENTITIES("toggle_protect_tile_entities", AllIcons.I_REPLACE),
NORMAL_SPEED("effortlessbuilding.action.normal_speed"),
FAST_SPEED("effortlessbuilding.action.fast_speed"),
NORMAL_SPEED("normal_speed", AllIcons.I_NORMAL_SPEED),
FAST_SPEED("fast_speed", AllIcons.I_FAST_SPEED),
FULL("effortlessbuilding.action.full"),
HOLLOW("effortlessbuilding.action.hollow"),
FULL("full", AllIcons.I_FILLED),
HOLLOW("hollow", AllIcons.I_HOLLOW),
CUBE_FULL("effortlessbuilding.action.full"),
CUBE_HOLLOW("effortlessbuilding.action.hollow"),
CUBE_SKELETON("effortlessbuilding.action.skeleton"),
CUBE_FULL("full", AllIcons.I_CUBE_FILLED),
CUBE_HOLLOW("hollow", AllIcons.I_CUBE_HOLLOW),
CUBE_SKELETON("skeleton", AllIcons.I_CUBE_SKELETON),
SHORT_EDGE("effortlessbuilding.action.short_edge"),
LONG_EDGE("effortlessbuilding.action.long_edge"),
SHORT_EDGE("short_edge", AllIcons.I_SHORT_EDGE),
LONG_EDGE("long_edge", AllIcons.I_LONG_EDGE),
THICKNESS_1("effortlessbuilding.action.thickness_1"),
THICKNESS_3("effortlessbuilding.action.thickness_3"),
THICKNESS_5("effortlessbuilding.action.thickness_5"),
THICKNESS_1("thickness_1", AllIcons.I_THICKNESS_1),
THICKNESS_3("thickness_3", AllIcons.I_THICKNESS_3),
THICKNESS_5("thickness_5", AllIcons.I_THICKNESS_5),
CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"),
CIRCLE_START_CENTER("effortlessbuilding.action.start_center");
CIRCLE_START_CORNER("start_corner", AllIcons.I_CIRCLE_START_CORNER),
CIRCLE_START_CENTER("start_center", AllIcons.I_CIRCLE_START_CENTER);
public String name;
public AllIcons icon;
ActionEnum(String name) {
ActionEnum(String name, AllIcons icon) {
this.name = name;
this.icon = icon;
}
public String getName() {
return name;
}
public String getNameKey() {
return "effortlessbuilding.action." + name;
}
public String getDescriptionKey() {
return "effortlessbuilding.action." + name + ".description";
}
}

View File

@@ -37,6 +37,7 @@ public class Array extends BaseModifier {
var newBlockEntry = new BlockEntry(pos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
blocks.add(newBlockEntry);
}
}
}

View File

@@ -1,33 +1,10 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.create.foundation.utility.NBTHelper;
import nl.requios.effortlessbuilding.systems.DelayedBlockPlacer;
import nl.requios.effortlessbuilding.systems.UndoRedo;
import nl.requios.effortlessbuilding.utilities.BlockSet;
import nl.requios.effortlessbuilding.utilities.ReachHelper;
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet;
import java.util.ArrayList;
import java.util.Collections;

View File

@@ -1,5 +1,6 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
@@ -19,6 +20,13 @@ public class Mirror extends BaseModifier {
public boolean drawLines = true;
public boolean drawPlanes = true;
public Mirror() {
super();
var player = Minecraft.getInstance().player;
if (player != null)
position = Vec3.atLowerCornerOf(Minecraft.getInstance().player.blockPosition());
}
@Override
public void findCoordinates(BlockSet blocks, Player player) {
if (!(enabled && (mirrorX || mirrorY || mirrorZ))) return;
@@ -43,6 +51,7 @@ public class Mirror extends BaseModifier {
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorX = !newBlockEntry.mirrorX;
blocks.add(newBlockEntry);
if (mirrorY) performMirrorY(blocks, newBlockEntry);
if (mirrorZ) performMirrorZ(blocks, newBlockEntry);
@@ -58,6 +67,7 @@ public class Mirror extends BaseModifier {
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorY = !newBlockEntry.mirrorY;
blocks.add(newBlockEntry);
if (mirrorZ) performMirrorZ(blocks, newBlockEntry);
}
@@ -72,6 +82,7 @@ public class Mirror extends BaseModifier {
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorZ = !newBlockEntry.mirrorZ;
blocks.add(newBlockEntry);
}
public boolean isWithinRange(BlockPos blockPos) {
@@ -83,6 +94,29 @@ public class Mirror extends BaseModifier {
public int getReach() {
return radius * 2; //Change ModifierSettings#setReachUpgrade too
}
public void toggleMirrorAxis(int index) {
switch (index) {
case 0 -> mirrorX = !mirrorX;
case 1 -> mirrorY = !mirrorY;
case 2 -> mirrorZ = !mirrorZ;
}
}
public boolean getMirrorAxis(int index) {
switch (index) {
case 0 -> {
return mirrorX;
}
case 1 -> {
return mirrorY;
}
case 2 -> {
return mirrorZ;
}
}
return false;
}
@Override
public CompoundTag serializeNBT() {

View File

@@ -73,6 +73,8 @@ public class RadialMirror extends BaseModifier {
//rotate block
double angleToCenter = Mth.atan2(relNewVec.x, relNewVec.z); //between -PI and PI
rotateBlockEntry(newBlockEntry, angleToCenter, doAlternate);
blocks.add(newBlockEntry);
}
}

View File

@@ -12,6 +12,7 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifiersScreenList;
import java.util.Collection;
import java.util.List;
@@ -146,7 +147,13 @@ public abstract class AbstractSimiScreen extends Screen {
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
renderComponentTooltip(ms, tooltip, ttx, tty);
}
//Added
if (widget instanceof ModifiersScreenList list) {
list.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
}
}
}
protected void endFrame() {}

View File

@@ -132,7 +132,8 @@ public class ScrollInput extends AbstractSimiWidget {
onChanged();
}
return priorState != state;
// return priorState != state;
return true; //Changed
}
protected void clampState() {

View File

@@ -154,7 +154,7 @@ public class Outliner {
public static class OutlineEntry {
static final int fadeTicks = 8;
static final int fadeTicks = 4;
private Outline outline;
private int ticksTillRemoval;

View File

@@ -19,6 +19,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.ClientEvents;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
@@ -296,9 +297,8 @@ public class RadialMenu extends Screen {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.55 + 0.45 * ringInnerEdge);
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.55 + 0.45 * ringInnerEdge);
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + menuRegion.mode.name().toLowerCase() + ".png"));
blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
menuRegion.mode.icon.render(ms, (int) (middleX + x - 8), (int) (middleY + y - 8));
}
//Draw action icons
@@ -307,8 +307,7 @@ public class RadialMenu extends Screen {
final double x = (button.x1 + button.x2) / 2 + 0.01;
final double y = (button.y1 + button.y2) / 2 + 0.01;
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + button.action.name().toLowerCase() + ".png"));
blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
button.action.icon.render(ms, (int) (middleX + x - 8), (int) (middleY + y - 8));
}
ms.popPose();
@@ -512,10 +511,10 @@ public class RadialMenu extends Screen {
public MenuButton(final ActionEnum action, final double x, final double y,
final Direction textSide) {
this.name = I18n.get(action.name);
this.name = I18n.get(action.getNameKey());
if (I18n.exists(action.name + ".description")) {
this.description = I18n.get(action.name + ".description");
if (I18n.exists(action.getDescriptionKey())) {
this.description = I18n.get(action.getDescriptionKey());
}
this.action = action;

View File

@@ -1,74 +1,47 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.AllGuiTextures;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.Label;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.ScrollInput;
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
import nl.requios.effortlessbuilding.create.foundation.utility.FontHelper;
import nl.requios.effortlessbuilding.gui.elements.GuiCheckBoxFixed;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.gui.elements.LabeledScrollInput;
import nl.requios.effortlessbuilding.utilities.MathHelper;
import nl.requios.effortlessbuilding.utilities.ReachHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
@OnlyIn(Dist.CLIENT)
public class ArrayEntry extends BaseModifierEntry<Array> {
protected Vector<ScrollInput> offsetInputs = new Vector<>(3);
protected Vector<Label> offsetLabels = new Vector<>(3);
protected ScrollInput countInput;
protected Label countLabel;
protected Label reachLabel;
public ArrayEntry(ModifiersScreen screen, BaseModifier array) {
super(screen, (Array) array, Component.literal("Array"), AllGuiTextures.ARRAY_ENTRY);
offsetInputs.clear();
offsetLabels.clear();
for (int i = 0; i < 3; i++) {
var label = new Label(0, 0, Components.immutableEmpty()).withShadow();
final int index = i;
var scrollInput = new ScrollInput(0, 0, 18, 18)
.withRange(0, 100)
.writingTo(label)
.titled(Component.literal("Offset"))
var scrollInput = new LabeledScrollInput(0, 0, 18, 18)
.titled(Component.literal(i == 0 ? "X Offset" : i == 1 ? "Y Offset" : "Z Offset"))
.calling(value -> {
modifier.offset = MathHelper.with(modifier.offset, index, value);
// label.x = x + 65 + 20 * index - font.width(label.text) / 2;
onValueChanged();
});
scrollInput.setState(MathHelper.get(modifier.offset, index));
offsetInputs.add(scrollInput);
offsetLabels.add(label);
}
listeners.addAll(offsetInputs);
listeners.addAll(offsetLabels);
countLabel = new Label(0, 0, Components.immutableEmpty()).withShadow();
countInput = new ScrollInput(0, 0, 18, 18)
countInput = new LabeledScrollInput(0, 0, 18, 18)
.withRange(1, 100)
.writingTo(countLabel)
.titled(Component.literal("Count"))
.calling(value -> {
modifier.count = value;
@@ -76,56 +49,34 @@ public class ArrayEntry extends BaseModifierEntry<Array> {
});
countInput.setState(modifier.count);
listeners.add(countInput);
listeners.add(countLabel);
reachLabel = new Label(0, 0, Components.immutableEmpty()).withShadow();
listeners.add(reachLabel);
for (int i = 0; i < 3; i++) {
offsetInputs.get(i).onChanged();
}
countInput.onChanged();
}
@Override
public void tick() {
super.tick();
offsetInputs.forEach(ScrollInput::tick);
offsetLabels.forEach(Label::tick);
countInput.tick();
onValueChanged();
}
@Override
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
//draw offset labels
for (int i = 0; i < 3; i++) {
offsetLabels.get(i).x = x + 65 + 20 * i - getFont().width(offsetLabels.get(i).text) / 2;
offsetLabels.get(i).y = y + 23;
offsetLabels.get(i).render(ms, mouseX, mouseY, partialTicks);
}
//draw offset inputs
for (int i = 0; i < 3; i++) {
offsetInputs.get(i).x = x + 65 + 20 * i;
offsetInputs.get(i).y = y + 23;
offsetInputs.get(i).x = left + 47 + 20 * i;
offsetInputs.get(i).y = top + 18;
offsetInputs.get(i).render(ms, mouseX, mouseY, partialTicks);
}
//draw count label
countLabel.x = x + 65;
countLabel.y = y + 45;
countLabel.render(ms, mouseX, mouseY, partialTicks);
//draw count input
countInput.x = x + 65;
countInput.y = y + 45;
countInput.x = left + 47;
countInput.y = top + 38;
countInput.render(ms, mouseX, mouseY, partialTicks);
//draw reach label
reachLabel.x = x + width - 125;
reachLabel.y = y + 23;
reachLabel.x = right - 8 - getFont().width(reachLabel.text);
reachLabel.y = top + 23;
reachLabel.render(ms, mouseX, mouseY, partialTicks);
}

View File

@@ -3,22 +3,36 @@ package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.network.chat.Component;
import nl.requios.effortlessbuilding.AllGuiTextures;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen;
import nl.requios.effortlessbuilding.create.foundation.gui.AllIcons;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.BoxWidget;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.ElementWidget;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.IconButton;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.Label;
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.gui.elements.MiniButton;
public abstract class BaseModifierEntry<T extends BaseModifier> extends ModifiersScreenList.Entry {
public T modifier;
protected AllGuiTextures background;
protected IconButton enableButton;
protected MiniButton enableButton;
protected Label nameLabel;
protected IconButton removeButton;
protected MiniButton moveUpButton;
protected MiniButton moveDownButton;
protected MiniButton removeButton;
protected Label reachLabel;
protected static final int BACKGROUND_WIDTH = 226;
protected static final int BACKGROUND_HEIGHT = 60;
protected int left = 0;
protected int right = 0;
protected int top = 0;
protected int bottom = 0;
public BaseModifierEntry(ModifiersScreen screen, T modifier, Component name, AllGuiTextures background) {
super(screen);
@@ -26,7 +40,8 @@ public abstract class BaseModifierEntry<T extends BaseModifier> extends Modifier
this.modifier = modifier;
this.background = background;
enableButton = new IconButton(35, 8, AllIcons.I_PLACE)
enableButton = new MiniButton(0, 0, 100, 9)
.showing(AllGuiTextures.ENABLE_BUTTON_BACKGROUND)
.withCallback(() -> {
modifier.enabled = !modifier.enabled;
onValueChanged();
@@ -36,40 +51,83 @@ public abstract class BaseModifierEntry<T extends BaseModifier> extends Modifier
nameLabel = new Label(65, 8, name);
nameLabel.text = name;
removeButton = new IconButton(0, 0, AllIcons.I_TRASH)
moveUpButton = new MiniButton(0, 0, 9, 9)
.showing(AllGuiTextures.ARROW_UP)
.withCallback(() -> {
screen.moveModifierUp(this);
onValueChanged();
});
moveUpButton.setToolTip(Components.literal("Move up"));
listeners.add(moveUpButton);
moveDownButton = new MiniButton(0, 0, 9, 9)
.showing(AllGuiTextures.ARROW_DOWN)
.withCallback(() -> {
screen.moveModifierDown(this);
onValueChanged();
});
moveDownButton.setToolTip(Components.literal("Move down"));
listeners.add(moveDownButton);
removeButton = new MiniButton(0, 0, 9, 9)
.showing(AllGuiTextures.TRASH)
.withCallback(() -> {
screen.removeModifier(this);
});
removeButton.setToolTip(Components.literal("Remove"));
listeners.add(removeButton);
reachLabel = new Label(0, 0, Components.immutableEmpty()).withShadow();
listeners.add(reachLabel);
}
@Override
public void tick() {
super.tick();
// enableButton.tick();
}
@Override
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
background.render(ms, x + 22, y, screen);
left = x + width / 2 - BACKGROUND_WIDTH / 2;
right = x + width / 2 + BACKGROUND_WIDTH / 2;
top = y;
bottom = y + BACKGROUND_HEIGHT;
enableButton.x = x + width - 60;
enableButton.y = y + 18;
background.render(ms, left, top, screen);
enableButton.x = left + 4;
enableButton.y = top + 3;
enableButton.render(ms, mouseX, mouseY, partialTicks);
if (modifier.enabled)
AllGuiTextures.CHECKMARK.render(ms, left + 5, top + 1, screen);
nameLabel.x = x + 65;
nameLabel.y = y + 4;
nameLabel.x = left + 18;
nameLabel.y = top + 4;
nameLabel.render(ms, mouseX, mouseY, partialTicks);
removeButton.x = x + width - 60;
removeButton.y = y + 38;
moveUpButton.x = right - 31;
moveUpButton.y = top + 3;
moveUpButton.render(ms, mouseX, mouseY, partialTicks);
moveDownButton.x = right - 22;
moveDownButton.y = top + 3;
moveDownButton.render(ms, mouseX, mouseY, partialTicks);
removeButton.x = right - 13;
removeButton.y = top + 3;
removeButton.render(ms, mouseX, mouseY, partialTicks);
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
}
public void onValueChanged() {
enableButton.setIcon(modifier.enabled ? AllIcons.I_PLACE : AllIcons.I_CLEAR);
if (modifier.enabled)
enableButton.setToolTip(Components.literal("Disable this modifier"));
else
enableButton.setToolTip(Components.literal("Enable this modifier"));
moveUpButton.visible = screen.canMoveUp(this);
moveDownButton.visible = screen.canMoveDown(this);
}
}

View File

@@ -1,37 +1,236 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.AllGuiTextures;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen;
import nl.requios.effortlessbuilding.gui.elements.*;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.IconButton;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.ScrollInput;
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
import nl.requios.effortlessbuilding.gui.elements.LabeledScrollInput;
import nl.requios.effortlessbuilding.utilities.MathHelper;
import nl.requios.effortlessbuilding.utilities.ReachHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.text.DecimalFormat;
import java.util.Vector;
@SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT)
public class MirrorEntry extends BaseModifierEntry<Mirror> {
public MirrorEntry(ModifiersScreen screen, BaseModifier modifier) {
super(screen, (Mirror) modifier, Component.literal("Mirror"), AllGuiTextures.MIRROR_ENTRY);
protected Vector<ScrollInput> positionInputs;
protected IconButton playerPositionButton;
protected IconButton toggleOffsetButton;
protected Vector<IconButton> axisButtons;
protected ScrollInput radiusInput;
protected IconButton showLinesButton;
protected IconButton showAreasButton;
protected DecimalFormat df = new DecimalFormat("#.#");
public MirrorEntry(ModifiersScreen screen, BaseModifier mirror) {
super(screen, (Mirror) mirror, Component.literal("Mirror"), AllGuiTextures.MIRROR_ENTRY);
positionInputs = new Vector<>();
axisButtons = new Vector<>();
//Position
//ScrollInput works with double the value, so we can have 0.5 increments
for (int i = 0; i < 3; i++) {
final int index = i;
var scrollInput = new LabeledScrollInput(0, 0, 27, 18)
.showControlScrollsSlowerTooltip()
.titled(Component.literal(i == 0 ? "X Position" : i == 1 ? "Y Position" : "Z Position"))
.format(integer -> Component.literal(df.format(integer / 2.0)))
.withStepFunction(stepContext -> stepContext.shift ? 20 : stepContext.control ? 1 : 2)
.calling(value -> {
modifier.position = MathHelper.with(modifier.position, index, value / 2.0);
onValueChanged();
});
scrollInput.setState((int) (MathHelper.get(modifier.position, index) * 2.0));
positionInputs.add(scrollInput);
}
listeners.addAll(positionInputs);
//Player position button
playerPositionButton = new IconButton(0, 0, AllIcons.I_PLAYER)
.withCallback(() -> {
modifier.position = Vec3.atLowerCornerOf(Minecraft.getInstance().player.blockPosition());
onValueChanged();
});
playerPositionButton.setToolTip(Components.literal("Set to player position"));
listeners.add(playerPositionButton);
//Toggle offset button
toggleOffsetButton = new IconButton(0, 0, AllIcons.I_BLOCK_CENTER)
.withCallback(() -> {
if (modifier.position.x == Math.floor(modifier.position.x)) {
modifier.position = new Vec3(
Math.floor(modifier.position.x) + 0.5,
Math.floor(modifier.position.y) + 0.5,
Math.floor(modifier.position.z) + 0.5
);
}
else {
modifier.position = new Vec3(
Math.floor(modifier.position.x),
Math.floor(modifier.position.y),
Math.floor(modifier.position.z)
);
}
onValueChanged();
});
listeners.add(toggleOffsetButton);
//Axis buttons
for (int i = 0; i < 3; i++) {
final int index = i;
IconButton button = new IconButton(0, 0, AllIcons.I_SHOW_LINES)
.withCallback(() -> {
modifier.toggleMirrorAxis(index);
onValueChanged();
});
button.setToolTip(Components.literal(i == 0 ? "X Axis" : i == 1 ? "Y Axis" : "Z Axis"));
axisButtons.add(button);
}
listeners.addAll(axisButtons);
//Radius
radiusInput = new LabeledScrollInput(0, 0, 27, 18)
.withRange(0, ReachHelper.getMaxMirrorRadius(Minecraft.getInstance().player))
.titled(Component.literal("Radius. Use Reach Upgrade items to increase maximum."))
.calling(value -> {
modifier.radius = value;
onValueChanged();
});
radiusInput.setState(modifier.radius);
listeners.add(radiusInput);
//Show lines button
showLinesButton = new IconButton(0, 0, AllIcons.I_SHOW_LINES)
.withCallback(() -> {
modifier.drawLines = !modifier.drawLines;
onValueChanged();
});
listeners.add(showLinesButton);
//Show areas button
showAreasButton = new IconButton(0, 0, AllIcons.I_SHOW_AREAS)
.withCallback(() -> {
modifier.drawPlanes = !modifier.drawPlanes;
onValueChanged();
});
listeners.add(showAreasButton);
for (ScrollInput positionInput : positionInputs) {
positionInput.onChanged();
}
radiusInput.onChanged();
}
// protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
@Override
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
//draw position inputs
for (int i = 0; i < 3; i++) {
ScrollInput input = positionInputs.get(i);
input.x = left + 47 + 29 * i;
input.y = top + 18;
input.render(ms, mouseX, mouseY, partialTicks);
}
//draw player position button
playerPositionButton.x = left + 134;
playerPositionButton.y = top + 18;
playerPositionButton.render(ms, mouseX, mouseY, partialTicks);
//draw toggle offset button
toggleOffsetButton.x = left + 154;
toggleOffsetButton.y = top + 18;
toggleOffsetButton.render(ms, mouseX, mouseY, partialTicks);
//draw axis buttons
for (int i = 0; i < 3; i++) {
IconButton button = axisButtons.get(i);
button.x = left + 47 + 18 * i;
button.y = top + 38;
button.render(ms, mouseX, mouseY, partialTicks);
}
//draw radius input
radiusInput.x = left + 145;
radiusInput.y = top + 38;
radiusInput.render(ms, mouseX, mouseY, partialTicks);
//draw show lines button
showLinesButton.x = right - 43;
showLinesButton.y = top + 38;
showLinesButton.render(ms, mouseX, mouseY, partialTicks);
//draw show areas button
showAreasButton.x = right - 23;
showAreasButton.y = top + 38;
showAreasButton.render(ms, mouseX, mouseY, partialTicks);
}
@Override
public void onValueChanged() {
super.onValueChanged();
//Position
for (int i = 0; i < 3; i++) {
ScrollInput input = positionInputs.get(i);
input.setState((int) (MathHelper.get(modifier.position, i) * 2.0));
}
//Toggle offset button
if (modifier.position.x == Math.floor(modifier.position.x)) {
toggleOffsetButton.setIcon(AllIcons.I_BLOCK_CENTER);
toggleOffsetButton.setToolTip(Components.literal("Set mirror position to center of block, for uneven numbered builds."));
}
else {
toggleOffsetButton.setIcon(AllIcons.I_BLOCK_CORNER);
toggleOffsetButton.setToolTip(Components.literal("Set mirror position to corner of block, for even numbered builds."));
}
//Axis buttons
for (int i = 0; i < 3; i++) {
IconButton button = axisButtons.get(i);
if (modifier.getMirrorAxis(i)) {
button.setIcon(AllIcons.I_SHOW_LINES);
}
else {
button.setIcon(AllIcons.I_HIDE_LINES);
}
}
//Show lines button
if (modifier.drawLines) {
showLinesButton.setIcon(AllIcons.I_SHOW_LINES);
showLinesButton.setToolTip(Components.literal("Hide mirror lines"));
}
else {
showLinesButton.setIcon(AllIcons.I_HIDE_LINES);
showLinesButton.setToolTip(Components.literal("Show mirror lines"));
}
//Show areas button
if (modifier.drawPlanes) {
showAreasButton.setIcon(AllIcons.I_SHOW_AREAS);
showAreasButton.setToolTip(Components.literal("Hide mirror areas"));
}
else {
showAreasButton.setIcon(AllIcons.I_HIDE_AREAS);
showAreasButton.setToolTip(Components.literal("Show mirror areas"));
}
}
// protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
//
// protected List<Button> mirrorButtonList = new ArrayList<>();
// protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();

View File

@@ -21,6 +21,7 @@ import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -47,7 +48,7 @@ public class ModifiersScreen extends AbstractSimiScreen {
int listL = this.width / 2 - listWidth / 2;
int listR = this.width / 2 + listWidth / 2;
list = new ModifiersScreenList(minecraft, listWidth, height - 80, 45, height - 45, 60);
list = new ModifiersScreenList(minecraft, listWidth, height - 80, 45, height - 45, 65);
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
addRenderableWidget(list);
@@ -111,30 +112,56 @@ public class ModifiersScreen extends AbstractSimiScreen {
list.children().add(entry);
EffortlessBuildingClient.BUILD_MODIFIERS.addModifierSettings(modifier);
}
public void removeModifier(BaseModifierEntry entry) {
list.children().remove(entry);
EffortlessBuildingClient.BUILD_MODIFIERS.removeModifierSettings(entry.modifier);
}
public boolean canMoveUp(BaseModifierEntry modifierEntry) {
int index = list.children().indexOf(modifierEntry);
return index > 0;
}
public boolean canMoveDown(BaseModifierEntry modifierEntry) {
int index = list.children().indexOf(modifierEntry);
return index < list.children().size() - 1;
}
public void moveModifierUp(BaseModifierEntry modifierEntry) {
int index = list.children().indexOf(modifierEntry);
if (index == 0) return;
Collections.swap(list.children(), index, index - 1);
EffortlessBuildingClient.BUILD_MODIFIERS.moveUp(modifierEntry.modifier);
}
public void moveModifierDown(BaseModifierEntry modifierEntry) {
int index = list.children().indexOf(modifierEntry);
if (index == list.children().size() - 1) return;
Collections.swap(list.children(), index, index + 1);
EffortlessBuildingClient.BUILD_MODIFIERS.moveDown(modifierEntry.modifier);
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
double scroll = list.getScrollAmount();
init(client, width, height);
list.setScrollAmount(scroll);
}
@Override
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
}
@Override
public void onClose() {
super.onClose();
EffortlessBuildingClient.BUILD_MODIFIERS.save(minecraft.player);
}
@Override
public boolean keyPressed(int keyCode, int p_96553_, int p_96554_) {
if (keyCode == ClientEvents.keyBindings[1].getKey().getValue()) {
@@ -144,5 +171,4 @@ public class ModifiersScreen extends AbstractSimiScreen {
return super.keyPressed(keyCode, p_96553_, p_96554_);
}
}

View File

@@ -8,7 +8,6 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.network.chat.Component;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen;
import nl.requios.effortlessbuilding.create.foundation.gui.TickableGuiEventListener;
import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.AbstractSimiWidget;
@@ -17,6 +16,7 @@ import nl.requios.effortlessbuilding.create.foundation.utility.Components;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
//Based on Create's ConfigScreenList
public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList.Entry> implements TickableGuiEventListener {
@@ -48,6 +48,30 @@ public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList
super.renderList(p_239228_, p_239229_, p_239230_, p_239231_);
RenderSystem.disableScissor();
}
public void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderListForeground(ms, mouseX, mouseY, partialTicks);
}
protected void renderListForeground(PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) {
int i = this.getRowLeft();
int j = this.getRowWidth();
int k = this.itemHeight - 4;
int l = this.getItemCount();
for(int i1 = 0; i1 < l; ++i1) {
int j1 = this.getRowTop(i1);
int k1 = j1 + itemHeight;
if (k1 >= this.y0 && j1 <= this.y1) {
renderItemForeground(pPoseStack, pMouseX, pMouseY, pPartialTick, i1, i, j1, j, k);
}
}
}
protected void renderItemForeground(PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick, int pIndex, int pLeft, int pTop, int pWidth, int pHeight) {
Entry e = this.getEntry(pIndex);
e.renderForeground(pPoseStack, pIndex, pTop, pLeft, pWidth, pHeight, pMouseX, pMouseY, Objects.equals(this.getHovered(), e), pPartialTick);
}
@Override
public boolean mouseClicked(double x, double y, int button) {
@@ -127,6 +151,10 @@ public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList
// UIRenderHelper.streak(ms, 0, x - 10, y + height / 2, height - 6, width, 0xdd_000000);
// UIRenderHelper.streak(ms, 180, x + (int) (width * 1.35f) + 10, y + height / 2, height - 6, width / 8 * 7, 0xdd_000000);
}
public void renderForeground(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
for (var listener : listeners) {
if (listener instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()
&& simiWidget.visible) {

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.Label;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.ScrollInput;
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
import nl.requios.effortlessbuilding.create.foundation.utility.Lang;
import org.jetbrains.annotations.NotNull;
public class LabeledScrollInput extends ScrollInput {
protected Label label;
protected final Component controlScrollsSlowerText = Lang.translateDirect("gui.scrollInput.controlScrollsSlower");
protected boolean controlScrollsSlower;
public LabeledScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
super(xIn, yIn, widthIn, heightIn);
min = Integer.MIN_VALUE;
max = Integer.MAX_VALUE;
label = new Label(0, 0, Components.immutableEmpty()).withShadow();
writingTo(label);
}
public LabeledScrollInput showControlScrollsSlowerTooltip() {
controlScrollsSlower = true;
return this;
}
@Override
public void renderButton(@NotNull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderButton(ms, mouseX, mouseY, partialTicks);
label.x = x + width / 2 - Minecraft.getInstance().font.width(label.text) / 2;
label.y = y + height / 2 - Minecraft.getInstance().font.lineHeight / 2;
label.renderButton(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void updateTooltip() {
super.updateTooltip();
if (title == null || !controlScrollsSlower)
return;
toolTip.add(controlScrollsSlowerText.plainCopy()
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
}
}

View File

@@ -0,0 +1,19 @@
package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.network.chat.Component;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.ElementWidget;
public class MiniButton extends ElementWidget {
public MiniButton(int x, int y) {
super(x, y);
}
public MiniButton(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void setToolTip(Component text) {
toolTip.clear();
toolTip.add(text);
}
}

View File

@@ -4,10 +4,8 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.List;
import java.util.function.Supplier;
/**
@@ -16,20 +14,24 @@ import java.util.function.Supplier;
public class ServerPlaceBlocksPacket {
private BlockSet blocks;
private long placeTime;
public ServerPlaceBlocksPacket() {}
public ServerPlaceBlocksPacket(BlockSet blocks) {
public ServerPlaceBlocksPacket(BlockSet blocks, long placeTime) {
this.blocks = blocks;
this.placeTime = placeTime;
}
public static void encode(ServerPlaceBlocksPacket message, FriendlyByteBuf buf) {
BlockSet.encode(buf, message.blocks);
buf.writeLong(message.placeTime);
}
public static ServerPlaceBlocksPacket decode(FriendlyByteBuf buf) {
ServerPlaceBlocksPacket message = new ServerPlaceBlocksPacket();
message.blocks = BlockSet.decode(buf);
message.placeTime = buf.readLong();
return message;
}
@@ -37,8 +39,8 @@ public class ServerPlaceBlocksPacket {
public static void handle(ServerPlaceBlocksPacket message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
EffortlessBuilding.SERVER_BLOCK_PLACER.placeBlocks(player, message.blocks);
EffortlessBuilding.SERVER_BLOCK_PLACER.placeBlocksDelayed(player, message.blocks, message.placeTime);
});
ctx.get().setPacketHandled(true);
}

View File

@@ -56,12 +56,14 @@ public class BlockPreviews {
}
public void drawLookAtPreview(Player player) {
if (EffortlessBuildingClient.BUILD_MODES.getBuildMode() == BuildModeEnum.DISABLED) return;
if (EffortlessBuildingClient.BUILDER_CHAIN.getBuildingState() == BuilderChain.BuildingState.IDLE &&
ClientConfig.visuals.onlyShowBlockPreviewsWhenBuilding.get()) return;
var blocks = EffortlessBuildingClient.BUILDER_CHAIN.getBlocks();
if (blocks.size() == 0) return;
if (EffortlessBuildingClient.BUILD_MODES.getBuildMode() == BuildModeEnum.DISABLED &&
blocks.size() == 1) return;
if (EffortlessBuildingClient.BUILDER_CHAIN.getBuildingState() == BuilderChain.BuildingState.IDLE &&
ClientConfig.visuals.onlyShowBlockPreviewsWhenBuilding.get() &&
blocks.size() == 1) return;
var coordinates = blocks.getCoordinates();
var state = EffortlessBuildingClient.BUILDER_CHAIN.getPretendBuildingState();

View File

@@ -43,6 +43,7 @@ public class BuilderChain {
private BlockPos startPosForBreaking;
private BlockHitResult lookingAtNear;
//Can be near or far depending on abilities
//Only updated when we are in IDLE state
private BlockHitResult lookingAt;
public enum BuildingState {
@@ -85,10 +86,9 @@ public class BuilderChain {
BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), false);
player.swing(InteractionHand.MAIN_HAND);
//TODO place blocks delayed on server, calculate what tick they should be placed on
int delay = CommonConfig.visuals.appearAnimationLength.get() * 3 - 3; //DelayedBlockPlacer is 3 times faster than client tick?
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks));
blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
long placeTime = player.level.getGameTime() + CommonConfig.visuals.appearAnimationLength.get() - 3;
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks, placeTime));
}
}
}
@@ -107,6 +107,7 @@ public class BuilderChain {
//Use new start position for breaking, because we assumed the player was gonna place
blocks.setStartPos(new BlockEntry(startPosForBreaking));
EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player);
BuilderFilter.filterOnCoordinates(blocks, player);
findExistingBlockStates(player.level);
BuilderFilter.filterOnExistingBlockStates(blocks, player);
@@ -122,6 +123,7 @@ public class BuilderChain {
EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksBroken(blocks);
BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), true);
player.swing(InteractionHand.MAIN_HAND);
blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
PacketHandler.INSTANCE.sendToServer(new ServerBreakBlocksPacket(blocks));
}
}
@@ -133,7 +135,6 @@ public class BuilderChain {
startPosForPlacing = null;
startPosForBreaking = null;
lookingAtNear = null;
lookingAt = null;
var mc = Minecraft.getInstance();
var player = mc.player;

View File

@@ -1,104 +0,0 @@
package nl.requios.effortlessbuilding.systems;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet;
import nl.requios.effortlessbuilding.utilities.InventoryHelper;
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
import java.util.*;
public class DelayedBlockPlacer {
private final Set<Entry> entries = Collections.synchronizedSet(new HashSet<>());
private final Set<Entry> entriesView = Collections.unmodifiableSet(entries);
public void placeBlocksDelayed(Entry entry) {
if (entry.world.isClientSide) return;
entries.add(entry);
}
public void tick() {
for (Entry entry : entries) {
entry.ticksTillPlacement--;
if (entry.ticksTillPlacement <= 0) {
entry.place();
entries.remove(entry);
}
}
}
public Set<Entry> getEntries() {
return entriesView;
}
public static class Entry {
private Level world;
private Player player;
private List<BlockPos> coordinates;
private List<BlockState> blockStates;
private List<ItemStack> itemStacks;
private boolean placeStartPos;
private int ticksTillPlacement;
public Entry(Level world, Player player, List<BlockPos> coordinates, List<BlockState> blockStates,
List<ItemStack> itemStacks, boolean placeStartPos, int ticksTillPlacement) {
this.world = world;
this.player = player;
this.coordinates = coordinates;
this.blockStates = blockStates;
this.itemStacks = itemStacks;
this.placeStartPos = placeStartPos;
this.ticksTillPlacement = ticksTillPlacement;
}
public void place() {
//remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
BlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isLoaded(blockPos)) {
//check itemstack empty
if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
if (itemStack.isEmpty()) continue;
}
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, false, false, false);
}
}
//find actual new blockstates for undo
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
//Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block is placed by the time it gets here, and unplaced after this)
if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.defaultBlockState());
//If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.defaultBlockState()) != newBlockStates.size()) {
//add to undo stack
BlockPos firstPos = coordinates.get(0);
BlockPos secondPos = coordinates.get(coordinates.size() - 1);
UndoRedo.addUndo(player, new UndoRedoBlockSet(coordinates, previousBlockStates, newBlockStates, firstPos, secondPos));
}
}
}
}

View File

@@ -18,25 +18,42 @@ import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper;
import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.List;
import java.util.*;
// Receives block placement requests from the client and places them
public class ServerBlockPlacer {
private final Set<DelayedEntry> delayedEntries = Collections.synchronizedSet(new HashSet<>());
private final Set<DelayedEntry> delayedEntriesView = Collections.unmodifiableSet(delayedEntries);
private boolean isPlacingOrBreakingBlocks = false;
public void placeBlocksDelayed(Player player, BlockSet blocks, long placeTime) {
delayedEntries.add(new DelayedEntry(player, blocks, placeTime));
}
public void tick() {
for (DelayedEntry entry : delayedEntries) {
long gameTime = entry.player.level.getGameTime();
if (gameTime >= entry.placeTime) {
placeBlocks(entry.player, entry.blocks);
delayedEntries.remove(entry);
}
}
}
public void placeBlocks(Player player, BlockSet blocks) {
// EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks");
for (BlockEntry block : blocks) {
if (blocks.skipFirst && block.blockPos == blocks.firstPos) continue;
placeBlock(player, block);
}
}
public void placeBlock(Player player, BlockEntry block) {
Level world = player.level;
if (!world.isLoaded(block.blockPos)) return;
@@ -45,15 +62,16 @@ public class ServerBlockPlacer {
boolean placedBlock = onPlaceItemIntoWorld(player, block) == InteractionResult.SUCCESS;
isPlacingOrBreakingBlocks = false;
}
public void breakBlocks(Player player, BlockSet blocks) {
// EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks");
for (BlockEntry block : blocks) {
if (blocks.skipFirst && block.blockPos == blocks.firstPos) continue;
breakBlock(player, block);
}
}
public void breakBlock(Player player, BlockEntry block) {
ServerLevel world = (ServerLevel) player.level;
if (!world.isLoaded(block.blockPos) || world.isEmptyBlock(block.blockPos)) return;
@@ -66,10 +84,16 @@ public class ServerBlockPlacer {
});
isPlacingOrBreakingBlocks = false;
}
public Set<DelayedEntry> getDelayedEntries() {
return delayedEntriesView;
}
public boolean isPlacingOrBreakingBlocks() {
return isPlacingOrBreakingBlocks;
}
public record DelayedEntry(Player player, BlockSet blocks, long placeTime) {}
//ForgeHooks::onPlaceItemIntoWorld
private InteractionResult onPlaceItemIntoWorld(Player player, BlockEntry block) {
@@ -91,7 +115,9 @@ public class ServerBlockPlacer {
level.captureBlockSnapshots = true;
ItemStack copy = itemstack.copy();
////
BlockHelper.placeSchematicBlock(level, player, block.newBlockState, block.blockPos, block.itemStack, null);
////
InteractionResult ret = InteractionResult.SUCCESS;
if (itemstack.isEmpty())
ForgeEventFactory.onPlayerDestroyItem(player, copy, InteractionHand.MAIN_HAND);

View File

@@ -39,7 +39,8 @@ public class BlockEntry {
this.itemStack = itemStack;
Block block = Block.byItem(itemStack.getItem());
var direction = rotation.rotate(originalDirection);
var direction = originalDirection;
if (rotation != null) direction = rotation.rotate(direction);
direction = applyMirror(direction);
//TODO mirror and rotate relativeHitVec?
var blockPlaceContext = new MyPlaceContext(world, blockPos, direction, itemStack, clickedFace, relativeHitVec);
@@ -47,9 +48,9 @@ public class BlockEntry {
}
private Direction applyMirror(Direction direction) {
if (mirrorX && direction.getAxis() == Direction.Axis.Z) direction = direction.getOpposite();
if (mirrorX && direction.getAxis() == Direction.Axis.X) direction = direction.getOpposite();
if (mirrorY && direction.getAxis() == Direction.Axis.Y) direction = direction.getOpposite();
if (mirrorZ && direction.getAxis() == Direction.Axis.X) direction = direction.getOpposite();
if (mirrorZ && direction.getAxis() == Direction.Axis.Z) direction = direction.getOpposite();
return direction;
}

View File

@@ -19,6 +19,7 @@ public class BlockSet extends HashMap<BlockPos, BlockEntry> implements Iterable<
public BlockPos firstPos;
public BlockPos lastPos;
public boolean skipFirst;
public BlockSet() {
super();
@@ -28,13 +29,17 @@ public class BlockSet extends HashMap<BlockPos, BlockEntry> implements Iterable<
super(blockSet);
this.firstPos = blockSet.firstPos;
this.lastPos = blockSet.lastPos;
this.skipFirst = blockSet.skipFirst;
}
public BlockSet(List<BlockEntry> blockEntries) {
public BlockSet(List<BlockEntry> blockEntries, BlockPos firstPos, BlockPos lastPos, boolean skipFirst) {
super();
for (BlockEntry blockEntry : blockEntries) {
add(blockEntry);
}
this.firstPos = firstPos;
this.lastPos = lastPos;
this.skipFirst = skipFirst;
}
public void setStartPos(BlockEntry startPos) {
@@ -74,10 +79,17 @@ public class BlockSet extends HashMap<BlockPos, BlockEntry> implements Iterable<
public static void encode(FriendlyByteBuf buf, BlockSet block) {
buf.writeCollection(block.values(), BlockEntry::encode);
buf.writeBlockPos(block.firstPos);
buf.writeBlockPos(block.lastPos);
buf.writeBoolean(block.skipFirst);
}
public static BlockSet decode(FriendlyByteBuf buf) {
return new BlockSet(buf.readList(BlockEntry::decode));
return new BlockSet(
buf.readList(BlockEntry::decode),
buf.readBlockPos(),
buf.readBlockPos(),
buf.readBoolean());
}
@OnlyIn(Dist.CLIENT)

View File

@@ -1,6 +1,7 @@
package nl.requios.effortlessbuilding.utilities;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
public class MathHelper {
@@ -12,6 +13,15 @@ public class MathHelper {
default -> throw new IllegalArgumentException("Index must be between 0 and 2");
};
}
public static Vec3 with(Vec3 vec, int index, double value) {
return switch (index) {
case 0 -> new Vec3(value, vec.y, vec.z);
case 1 -> new Vec3(vec.x, value, vec.z);
case 2 -> new Vec3(vec.x, vec.y, value);
default -> throw new IllegalArgumentException("Index must be between 0 and 2");
};
}
public static int get(Vec3i vec, int index) {
return switch (index) {
@@ -21,4 +31,13 @@ public class MathHelper {
default -> throw new IllegalArgumentException("Index must be between 0 and 2");
};
}
public static double get(Vec3 vec, int index) {
return switch (index) {
case 0 -> vec.x;
case 1 -> vec.y;
case 2 -> vec.z;
default -> throw new IllegalArgumentException("Index must be between 0 and 2");
};
}
}

View File

@@ -58,6 +58,10 @@ public class ReachHelper {
default -> CommonConfig.reach.maxReachLevel0.get();
};
}
public static int getMaxMirrorRadius(Player player) {
return getMaxReach(player) / 2;
}
public static int getPlacementReach(Player player) {
return getMaxReach(player) / 4;