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:
@@ -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;
|
||||
|
||||
@@ -91,7 +91,6 @@ public class ClientEvents {
|
||||
BuildModeEnum buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
if (mc.screen != null ||
|
||||
buildMode == BuildModeEnum.DISABLED ||
|
||||
RadialMenu.instance.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ public class Array extends BaseModifier {
|
||||
|
||||
var newBlockEntry = new BlockEntry(pos);
|
||||
newBlockEntry.copyRotationSettingsFrom(blockEntry);
|
||||
blocks.add(newBlockEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -132,7 +132,8 @@ public class ScrollInput extends AbstractSimiWidget {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
return priorState != state;
|
||||
// return priorState != state;
|
||||
return true; //Changed
|
||||
}
|
||||
|
||||
protected void clampState() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user