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; import nl.requios.effortlessbuilding.create.foundation.utility.Color;
public enum AllGuiTextures implements ScreenElement { public enum AllGuiTextures implements ScreenElement {
ARRAY_ENTRY("modifiers", 256, 60), ARRAY_ENTRY("modifiers", 226, 60),
MIRROR_ENTRY("modifiers", 0, 60, 256, 60), MIRROR_ENTRY("modifiers", 0, 60, 226, 60),
RADIAL_MIRROR_ENTRY("modifiers", 0, 120, 256, 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 final ResourceLocation location;
public int width, height; public int width, height;

View File

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

View File

@@ -13,6 +13,7 @@ import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.BlockEvent; import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import nl.requios.effortlessbuilding.systems.UndoRedo; import nl.requios.effortlessbuilding.systems.UndoRedo;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
@@ -32,8 +33,9 @@ public class CommonEvents {
@SubscribeEvent @SubscribeEvent
public static void onTick(TickEvent.LevelTickEvent event) { public static void onTick(TickEvent.LevelTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; 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 //Cancel event if necessary. Nothing more, rest is handled on mouseclick

View File

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

View File

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

View File

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

View File

@@ -1,33 +1,10 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag; 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.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.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.create.foundation.utility.NBTHelper; 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.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.ArrayList;
import java.util.Collections; import java.util.Collections;

View File

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

View File

@@ -73,6 +73,8 @@ public class RadialMirror extends BaseModifier {
//rotate block //rotate block
double angleToCenter = Mth.atan2(relNewVec.x, relNewVec.z); //between -PI and PI double angleToCenter = Mth.atan2(relNewVec.x, relNewVec.z); //between -PI and PI
rotateBlockEntry(newBlockEntry, angleToCenter, doAlternate); 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.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifiersScreenList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -146,9 +147,15 @@ public abstract class AbstractSimiScreen extends Screen {
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y; int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
renderComponentTooltip(ms, tooltip, ttx, tty); renderComponentTooltip(ms, tooltip, ttx, tty);
} }
//Added
if (widget instanceof ModifiersScreenList list) {
list.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
} }
} }
}
protected void endFrame() {} protected void endFrame() {}
@Deprecated @Deprecated

View File

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

View File

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

View File

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

View File

@@ -1,74 +1,47 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack; 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.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.AllGuiTextures; import nl.requios.effortlessbuilding.AllGuiTextures;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier; 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.gui.widget.ScrollInput;
import nl.requios.effortlessbuilding.create.foundation.utility.Components; import nl.requios.effortlessbuilding.gui.elements.LabeledScrollInput;
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.utilities.MathHelper; import nl.requios.effortlessbuilding.utilities.MathHelper;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector; import java.util.Vector;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ArrayEntry extends BaseModifierEntry<Array> { public class ArrayEntry extends BaseModifierEntry<Array> {
protected Vector<ScrollInput> offsetInputs = new Vector<>(3); protected Vector<ScrollInput> offsetInputs = new Vector<>(3);
protected Vector<Label> offsetLabels = new Vector<>(3);
protected ScrollInput countInput; protected ScrollInput countInput;
protected Label countLabel;
protected Label reachLabel;
public ArrayEntry(ModifiersScreen screen, BaseModifier array) { public ArrayEntry(ModifiersScreen screen, BaseModifier array) {
super(screen, (Array) array, Component.literal("Array"), AllGuiTextures.ARRAY_ENTRY); super(screen, (Array) array, Component.literal("Array"), AllGuiTextures.ARRAY_ENTRY);
offsetInputs.clear(); offsetInputs.clear();
offsetLabels.clear();
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
var label = new Label(0, 0, Components.immutableEmpty()).withShadow();
final int index = i; final int index = i;
var scrollInput = new ScrollInput(0, 0, 18, 18) var scrollInput = new LabeledScrollInput(0, 0, 18, 18)
.withRange(0, 100) .titled(Component.literal(i == 0 ? "X Offset" : i == 1 ? "Y Offset" : "Z Offset"))
.writingTo(label)
.titled(Component.literal("Offset"))
.calling(value -> { .calling(value -> {
modifier.offset = MathHelper.with(modifier.offset, index, value); modifier.offset = MathHelper.with(modifier.offset, index, value);
// label.x = x + 65 + 20 * index - font.width(label.text) / 2;
onValueChanged(); onValueChanged();
}); });
scrollInput.setState(MathHelper.get(modifier.offset, index)); scrollInput.setState(MathHelper.get(modifier.offset, index));
offsetInputs.add(scrollInput); offsetInputs.add(scrollInput);
offsetLabels.add(label);
} }
listeners.addAll(offsetInputs); listeners.addAll(offsetInputs);
listeners.addAll(offsetLabels);
countLabel = new Label(0, 0, Components.immutableEmpty()).withShadow(); countInput = new LabeledScrollInput(0, 0, 18, 18)
countInput = new ScrollInput(0, 0, 18, 18)
.withRange(1, 100) .withRange(1, 100)
.writingTo(countLabel)
.titled(Component.literal("Count")) .titled(Component.literal("Count"))
.calling(value -> { .calling(value -> {
modifier.count = value; modifier.count = value;
@@ -76,56 +49,34 @@ public class ArrayEntry extends BaseModifierEntry<Array> {
}); });
countInput.setState(modifier.count); countInput.setState(modifier.count);
listeners.add(countInput); listeners.add(countInput);
listeners.add(countLabel);
reachLabel = new Label(0, 0, Components.immutableEmpty()).withShadow();
listeners.add(reachLabel);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
offsetInputs.get(i).onChanged(); offsetInputs.get(i).onChanged();
} }
countInput.onChanged(); countInput.onChanged();
}
@Override onValueChanged();
public void tick() {
super.tick();
offsetInputs.forEach(ScrollInput::tick);
offsetLabels.forEach(Label::tick);
countInput.tick();
} }
@Override @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) { 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); 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 //draw offset inputs
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
offsetInputs.get(i).x = x + 65 + 20 * i; offsetInputs.get(i).x = left + 47 + 20 * i;
offsetInputs.get(i).y = y + 23; offsetInputs.get(i).y = top + 18;
offsetInputs.get(i).render(ms, mouseX, mouseY, partialTicks); 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 //draw count input
countInput.x = x + 65; countInput.x = left + 47;
countInput.y = y + 45; countInput.y = top + 38;
countInput.render(ms, mouseX, mouseY, partialTicks); countInput.render(ms, mouseX, mouseY, partialTicks);
//draw reach label //draw reach label
reachLabel.x = x + width - 125; reachLabel.x = right - 8 - getFont().width(reachLabel.text);
reachLabel.y = y + 23; reachLabel.y = top + 23;
reachLabel.render(ms, mouseX, mouseY, partialTicks); 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 com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import nl.requios.effortlessbuilding.AllGuiTextures; import nl.requios.effortlessbuilding.AllGuiTextures;
import nl.requios.effortlessbuilding.AllIcons;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier; import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen; 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.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.IconButton;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.Label; 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.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane; 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 abstract class BaseModifierEntry<T extends BaseModifier> extends ModifiersScreenList.Entry {
public T modifier; public T modifier;
protected AllGuiTextures background; protected AllGuiTextures background;
protected IconButton enableButton; protected MiniButton enableButton;
protected Label nameLabel; 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) { public BaseModifierEntry(ModifiersScreen screen, T modifier, Component name, AllGuiTextures background) {
super(screen); super(screen);
@@ -26,7 +40,8 @@ public abstract class BaseModifierEntry<T extends BaseModifier> extends Modifier
this.modifier = modifier; this.modifier = modifier;
this.background = background; this.background = background;
enableButton = new IconButton(35, 8, AllIcons.I_PLACE) enableButton = new MiniButton(0, 0, 100, 9)
.showing(AllGuiTextures.ENABLE_BUTTON_BACKGROUND)
.withCallback(() -> { .withCallback(() -> {
modifier.enabled = !modifier.enabled; modifier.enabled = !modifier.enabled;
onValueChanged(); onValueChanged();
@@ -36,40 +51,83 @@ public abstract class BaseModifierEntry<T extends BaseModifier> extends Modifier
nameLabel = new Label(65, 8, name); nameLabel = new Label(65, 8, name);
nameLabel.text = 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(() -> { .withCallback(() -> {
screen.removeModifier(this); screen.removeModifier(this);
}); });
removeButton.setToolTip(Components.literal("Remove"));
listeners.add(removeButton); listeners.add(removeButton);
reachLabel = new Label(0, 0, Components.immutableEmpty()).withShadow();
listeners.add(reachLabel);
} }
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
// enableButton.tick();
} }
@Override @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) { 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; background.render(ms, left, top, screen);
enableButton.y = y + 18;
enableButton.x = left + 4;
enableButton.y = top + 3;
enableButton.render(ms, mouseX, mouseY, partialTicks); enableButton.render(ms, mouseX, mouseY, partialTicks);
if (modifier.enabled)
AllGuiTextures.CHECKMARK.render(ms, left + 5, top + 1, screen);
nameLabel.x = x + 65; nameLabel.x = left + 18;
nameLabel.y = y + 4; nameLabel.y = top + 4;
nameLabel.render(ms, mouseX, mouseY, partialTicks); nameLabel.render(ms, mouseX, mouseY, partialTicks);
removeButton.x = x + width - 60; moveUpButton.x = right - 31;
removeButton.y = y + 38; 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); removeButton.render(ms, mouseX, mouseY, partialTicks);
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
} }
public void onValueChanged() { 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,35 +1,234 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.components.Widget; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.AllGuiTextures; 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.BaseModifier;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.create.foundation.gui.AbstractSimiScreen; import nl.requios.effortlessbuilding.create.foundation.gui.widget.IconButton;
import nl.requios.effortlessbuilding.gui.elements.*; 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 nl.requios.effortlessbuilding.utilities.ReachHelper;
import java.util.ArrayList; import java.text.DecimalFormat;
import java.util.Arrays; import java.util.Vector;
import java.util.List;
@SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class MirrorEntry extends BaseModifierEntry<Mirror> { public class MirrorEntry extends BaseModifierEntry<Mirror> {
public MirrorEntry(ModifiersScreen screen, BaseModifier modifier) { protected Vector<ScrollInput> positionInputs;
super(screen, (Mirror) modifier, Component.literal("Mirror"), AllGuiTextures.MIRROR_ENTRY); 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();
} }
@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 static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
// //

View File

@@ -21,6 +21,7 @@ import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -47,7 +48,7 @@ public class ModifiersScreen extends AbstractSimiScreen {
int listL = this.width / 2 - listWidth / 2; int listL = this.width / 2 - listWidth / 2;
int listR = 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); list.setLeftPos(this.width / 2 - list.getWidth() / 2);
addRenderableWidget(list); addRenderableWidget(list);
@@ -117,6 +118,32 @@ public class ModifiersScreen extends AbstractSimiScreen {
EffortlessBuildingClient.BUILD_MODIFIERS.removeModifierSettings(entry.modifier); 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 @Override
public void resize(@Nonnull Minecraft client, int width, int height) { public void resize(@Nonnull Minecraft client, int width, int height) {
double scroll = list.getScrollAmount(); double scroll = list.getScrollAmount();
@@ -144,5 +171,4 @@ public class ModifiersScreen extends AbstractSimiScreen {
return super.keyPressed(keyCode, p_96553_, p_96554_); 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.ObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.network.chat.Component; 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.TickableGuiEventListener;
import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper; import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper;
import nl.requios.effortlessbuilding.create.foundation.gui.widget.AbstractSimiWidget; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
//Based on Create's ConfigScreenList //Based on Create's ConfigScreenList
public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList.Entry> implements TickableGuiEventListener { public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList.Entry> implements TickableGuiEventListener {
@@ -49,6 +49,30 @@ public class ModifiersScreenList extends ObjectSelectionList<ModifiersScreenList
RenderSystem.disableScissor(); 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 @Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
if (children().stream().anyMatch(e -> e.mouseClicked(x, y, button))) if (children().stream().anyMatch(e -> e.mouseClicked(x, y, 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, 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); // 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) { for (var listener : listeners) {
if (listener instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused() if (listener instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()
&& simiWidget.visible) { && 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.minecraft.world.entity.player.Player;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet; import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@@ -16,20 +14,24 @@ import java.util.function.Supplier;
public class ServerPlaceBlocksPacket { public class ServerPlaceBlocksPacket {
private BlockSet blocks; private BlockSet blocks;
private long placeTime;
public ServerPlaceBlocksPacket() {} public ServerPlaceBlocksPacket() {}
public ServerPlaceBlocksPacket(BlockSet blocks) { public ServerPlaceBlocksPacket(BlockSet blocks, long placeTime) {
this.blocks = blocks; this.blocks = blocks;
this.placeTime = placeTime;
} }
public static void encode(ServerPlaceBlocksPacket message, FriendlyByteBuf buf) { public static void encode(ServerPlaceBlocksPacket message, FriendlyByteBuf buf) {
BlockSet.encode(buf, message.blocks); BlockSet.encode(buf, message.blocks);
buf.writeLong(message.placeTime);
} }
public static ServerPlaceBlocksPacket decode(FriendlyByteBuf buf) { public static ServerPlaceBlocksPacket decode(FriendlyByteBuf buf) {
ServerPlaceBlocksPacket message = new ServerPlaceBlocksPacket(); ServerPlaceBlocksPacket message = new ServerPlaceBlocksPacket();
message.blocks = BlockSet.decode(buf); message.blocks = BlockSet.decode(buf);
message.placeTime = buf.readLong();
return message; return message;
} }
@@ -38,7 +40,7 @@ public class ServerPlaceBlocksPacket {
ctx.get().enqueueWork(() -> { ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); 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); ctx.get().setPacketHandled(true);
} }

View File

@@ -56,13 +56,15 @@ public class BlockPreviews {
} }
public void drawLookAtPreview(Player player) { 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(); var blocks = EffortlessBuildingClient.BUILDER_CHAIN.getBlocks();
if (blocks.size() == 0) return; 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 coordinates = blocks.getCoordinates();
var state = EffortlessBuildingClient.BUILDER_CHAIN.getPretendBuildingState(); var state = EffortlessBuildingClient.BUILDER_CHAIN.getPretendBuildingState();

View File

@@ -43,6 +43,7 @@ public class BuilderChain {
private BlockPos startPosForBreaking; private BlockPos startPosForBreaking;
private BlockHitResult lookingAtNear; private BlockHitResult lookingAtNear;
//Can be near or far depending on abilities //Can be near or far depending on abilities
//Only updated when we are in IDLE state
private BlockHitResult lookingAt; private BlockHitResult lookingAt;
public enum BuildingState { public enum BuildingState {
@@ -85,10 +86,9 @@ public class BuilderChain {
BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), false); BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), false);
player.swing(InteractionHand.MAIN_HAND); player.swing(InteractionHand.MAIN_HAND);
//TODO place blocks delayed on server, calculate what tick they should be placed on blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
int delay = CommonConfig.visuals.appearAnimationLength.get() * 3 - 3; //DelayedBlockPlacer is 3 times faster than client tick? long placeTime = player.level.getGameTime() + CommonConfig.visuals.appearAnimationLength.get() - 3;
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks, placeTime));
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks));
} }
} }
} }
@@ -107,6 +107,7 @@ public class BuilderChain {
//Use new start position for breaking, because we assumed the player was gonna place //Use new start position for breaking, because we assumed the player was gonna place
blocks.setStartPos(new BlockEntry(startPosForBreaking)); blocks.setStartPos(new BlockEntry(startPosForBreaking));
EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player);
BuilderFilter.filterOnCoordinates(blocks, player); BuilderFilter.filterOnCoordinates(blocks, player);
findExistingBlockStates(player.level); findExistingBlockStates(player.level);
BuilderFilter.filterOnExistingBlockStates(blocks, player); BuilderFilter.filterOnExistingBlockStates(blocks, player);
@@ -122,6 +123,7 @@ public class BuilderChain {
EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksBroken(blocks); EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksBroken(blocks);
BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), true); BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), true);
player.swing(InteractionHand.MAIN_HAND); player.swing(InteractionHand.MAIN_HAND);
blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
PacketHandler.INSTANCE.sendToServer(new ServerBreakBlocksPacket(blocks)); PacketHandler.INSTANCE.sendToServer(new ServerBreakBlocksPacket(blocks));
} }
} }
@@ -133,7 +135,6 @@ public class BuilderChain {
startPosForPlacing = null; startPosForPlacing = null;
startPosForBreaking = null; startPosForBreaking = null;
lookingAtNear = null; lookingAtNear = null;
lookingAt = null;
var mc = Minecraft.getInstance(); var mc = Minecraft.getInstance();
var player = mc.player; 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,21 +18,38 @@ import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper; import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper;
import nl.requios.effortlessbuilding.utilities.BlockEntry; import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet; import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.List; import java.util.*;
// Receives block placement requests from the client and places them // Receives block placement requests from the client and places them
public class ServerBlockPlacer { public class ServerBlockPlacer {
private final Set<DelayedEntry> delayedEntries = Collections.synchronizedSet(new HashSet<>());
private final Set<DelayedEntry> delayedEntriesView = Collections.unmodifiableSet(delayedEntries);
private boolean isPlacingOrBreakingBlocks = false; 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) { public void placeBlocks(Player player, BlockSet blocks) {
// EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks"); // EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks");
for (BlockEntry block : blocks) { for (BlockEntry block : blocks) {
if (blocks.skipFirst && block.blockPos == blocks.firstPos) continue;
placeBlock(player, block); placeBlock(player, block);
} }
} }
@@ -50,6 +67,7 @@ public class ServerBlockPlacer {
// EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks"); // EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks");
for (BlockEntry block : blocks) { for (BlockEntry block : blocks) {
if (blocks.skipFirst && block.blockPos == blocks.firstPos) continue;
breakBlock(player, block); breakBlock(player, block);
} }
} }
@@ -67,10 +85,16 @@ public class ServerBlockPlacer {
isPlacingOrBreakingBlocks = false; isPlacingOrBreakingBlocks = false;
} }
public Set<DelayedEntry> getDelayedEntries() {
return delayedEntriesView;
}
public boolean isPlacingOrBreakingBlocks() { public boolean isPlacingOrBreakingBlocks() {
return isPlacingOrBreakingBlocks; return isPlacingOrBreakingBlocks;
} }
public record DelayedEntry(Player player, BlockSet blocks, long placeTime) {}
//ForgeHooks::onPlaceItemIntoWorld //ForgeHooks::onPlaceItemIntoWorld
private InteractionResult onPlaceItemIntoWorld(Player player, BlockEntry block) { private InteractionResult onPlaceItemIntoWorld(Player player, BlockEntry block) {
@@ -91,7 +115,9 @@ public class ServerBlockPlacer {
level.captureBlockSnapshots = true; level.captureBlockSnapshots = true;
ItemStack copy = itemstack.copy(); ItemStack copy = itemstack.copy();
////
BlockHelper.placeSchematicBlock(level, player, block.newBlockState, block.blockPos, block.itemStack, null); BlockHelper.placeSchematicBlock(level, player, block.newBlockState, block.blockPos, block.itemStack, null);
////
InteractionResult ret = InteractionResult.SUCCESS; InteractionResult ret = InteractionResult.SUCCESS;
if (itemstack.isEmpty()) if (itemstack.isEmpty())
ForgeEventFactory.onPlayerDestroyItem(player, copy, InteractionHand.MAIN_HAND); ForgeEventFactory.onPlayerDestroyItem(player, copy, InteractionHand.MAIN_HAND);

View File

@@ -39,7 +39,8 @@ public class BlockEntry {
this.itemStack = itemStack; this.itemStack = itemStack;
Block block = Block.byItem(itemStack.getItem()); Block block = Block.byItem(itemStack.getItem());
var direction = rotation.rotate(originalDirection); var direction = originalDirection;
if (rotation != null) direction = rotation.rotate(direction);
direction = applyMirror(direction); direction = applyMirror(direction);
//TODO mirror and rotate relativeHitVec? //TODO mirror and rotate relativeHitVec?
var blockPlaceContext = new MyPlaceContext(world, blockPos, direction, itemStack, clickedFace, relativeHitVec); var blockPlaceContext = new MyPlaceContext(world, blockPos, direction, itemStack, clickedFace, relativeHitVec);
@@ -47,9 +48,9 @@ public class BlockEntry {
} }
private Direction applyMirror(Direction direction) { 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 (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; return direction;
} }

View File

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

View File

@@ -1,6 +1,7 @@
package nl.requios.effortlessbuilding.utilities; package nl.requios.effortlessbuilding.utilities;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
public class MathHelper { public class MathHelper {
@@ -13,6 +14,15 @@ public class MathHelper {
}; };
} }
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) { public static int get(Vec3i vec, int index) {
return switch (index) { return switch (index) {
case 0 -> vec.getX(); case 0 -> vec.getX();
@@ -21,4 +31,13 @@ public class MathHelper {
default -> throw new IllegalArgumentException("Index must be between 0 and 2"); 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

@@ -59,6 +59,10 @@ public class ReachHelper {
}; };
} }
public static int getMaxMirrorRadius(Player player) {
return getMaxReach(player) / 2;
}
public static int getPlacementReach(Player player) { public static int getPlacementReach(Player player) {
return getMaxReach(player) / 4; return getMaxReach(player) / 4;
} }

View File

@@ -89,5 +89,6 @@
"effortlessbuilding.gui.scrollInput.scrollToModify": "Scroll to Modify", "effortlessbuilding.gui.scrollInput.scrollToModify": "Scroll to Modify",
"effortlessbuilding.gui.scrollInput.scrollToAdjustAmount": "Scroll to Adjust Amount", "effortlessbuilding.gui.scrollInput.scrollToAdjustAmount": "Scroll to Adjust Amount",
"effortlessbuilding.gui.scrollInput.scrollToSelect": "Scroll to Select", "effortlessbuilding.gui.scrollInput.scrollToSelect": "Scroll to Select",
"effortlessbuilding.gui.scrollInput.shiftScrollsFaster": "Shift to Scroll Faster" "effortlessbuilding.gui.scrollInput.shiftScrollsFaster": "Shift to Scroll Faster",
"effortlessbuilding.gui.scrollInput.controlScrollsSlower": "Control to Scroll Slower"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB