Overhaul continues continuing.
Saving data and serverside state through persistent player data. Overhauled block previews. Removed mode capability. Added create item and network classes. Using create BlockHelper to place and break blocks.
This commit is contained in:
@@ -25,13 +25,14 @@ import net.minecraftforge.client.settings.KeyModifier;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.gui.buildmode.PlayerSettingsGui;
|
||||
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
|
||||
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
|
||||
import nl.requios.effortlessbuilding.render.BlockPreviews;
|
||||
import nl.requios.effortlessbuilding.render.RenderHandler;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
import nl.requios.effortlessbuilding.network.*;
|
||||
import nl.requios.effortlessbuilding.render.BuildRenderTypes;
|
||||
@@ -43,8 +44,6 @@ import java.io.IOException;
|
||||
public class ClientEvents {
|
||||
|
||||
public static KeyMapping[] keyBindings;
|
||||
public static HitResult previousLookAt;
|
||||
public static HitResult currentLookAt;
|
||||
public static int ticksInGame = 0;
|
||||
private static int placeCooldown = 0;
|
||||
private static int breakCooldown = 0;
|
||||
@@ -92,28 +91,8 @@ public class ClientEvents {
|
||||
|
||||
onMouseInput();
|
||||
|
||||
//Update previousLookAt
|
||||
HitResult objectMouseOver = Minecraft.getInstance().hitResult;
|
||||
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
|
||||
if (objectMouseOver == null) return;
|
||||
EffortlessBuildingClient.BLOCK_PREVIEWS.onTick();
|
||||
|
||||
if (currentLookAt == null) {
|
||||
currentLookAt = objectMouseOver;
|
||||
previousLookAt = objectMouseOver;
|
||||
return;
|
||||
}
|
||||
|
||||
if (objectMouseOver.getType() == HitResult.Type.BLOCK) {
|
||||
if (currentLookAt.getType() != HitResult.Type.BLOCK) {
|
||||
currentLookAt = objectMouseOver;
|
||||
previousLookAt = objectMouseOver;
|
||||
} else {
|
||||
if (((BlockHitResult) currentLookAt).getBlockPos() != ((BlockHitResult) objectMouseOver).getBlockPos()) {
|
||||
previousLookAt = currentLookAt;
|
||||
currentLookAt = objectMouseOver;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (event.phase == TickEvent.Phase.END) {
|
||||
Screen gui = Minecraft.getInstance().screen;
|
||||
if (gui == null || !gui.isPauseScreen()) {
|
||||
@@ -127,10 +106,10 @@ public class ClientEvents {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
LocalPlayer player = mc.player;
|
||||
if (player == null) return;
|
||||
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
BuildModeEnum buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
if (mc.screen != null ||
|
||||
buildMode == BuildModes.BuildModeEnum.DISABLED ||
|
||||
buildMode == BuildModeEnum.DISABLED ||
|
||||
RadialMenu.instance.isVisible()) {
|
||||
return;
|
||||
}
|
||||
@@ -142,7 +121,7 @@ public class ClientEvents {
|
||||
|
||||
EffortlessBuildingClient.BUILDER_CHAIN.onRightClick();
|
||||
|
||||
} else if (buildMode == BuildModes.BuildModeEnum.SINGLE) {
|
||||
} else if (buildMode == BuildModeEnum.SINGLE) {
|
||||
placeCooldown--;
|
||||
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
|
||||
}
|
||||
@@ -158,7 +137,7 @@ public class ClientEvents {
|
||||
|
||||
EffortlessBuildingClient.BUILDER_CHAIN.onLeftClick();
|
||||
|
||||
} else if (buildMode == BuildModes.BuildModeEnum.SINGLE) {
|
||||
} else if (buildMode == BuildModeEnum.SINGLE) {
|
||||
breakCooldown--;
|
||||
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
|
||||
}
|
||||
@@ -182,11 +161,7 @@ public class ClientEvents {
|
||||
|
||||
//QuickReplace toggle
|
||||
if (keyBindings[1].consumeClick()) {
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
|
||||
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
|
||||
modifierSettings.doQuickReplace() ? "on" : "off"));
|
||||
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
|
||||
EffortlessBuildingClient.QUICK_REPLACE.toggleQuickReplacing();
|
||||
}
|
||||
|
||||
//Radial menu
|
||||
@@ -217,7 +192,7 @@ public class ClientEvents {
|
||||
//Change placement mode
|
||||
if (keyBindings[5].consumeClick()) {
|
||||
//Toggle between first two actions of the first option of the current build mode
|
||||
BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
BuildModeEnum currentBuildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
if (currentBuildMode.options.length > 0) {
|
||||
ModeOptions.OptionEnum option = currentBuildMode.options[0];
|
||||
if (option.actions.length >= 2) {
|
||||
|
||||
@@ -17,11 +17,9 @@ import net.minecraftforge.event.level.BlockEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
|
||||
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
|
||||
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
|
||||
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
@@ -39,7 +37,6 @@ public class CommonEvents {
|
||||
@SubscribeEvent
|
||||
public void registerCapabilities(RegisterCapabilitiesEvent event){
|
||||
event.register(ModifierCapabilityManager.IModifierCapability.class);
|
||||
event.register(ModeCapabilityManager.IModeCapability.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +45,6 @@ public class CommonEvents {
|
||||
if (event.getObject() instanceof FakePlayer) return;
|
||||
if (event.getObject() instanceof Player) {
|
||||
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
|
||||
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +62,12 @@ public class CommonEvents {
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
if (event.getEntity() instanceof FakePlayer) return;
|
||||
|
||||
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
//Don't cancel event if our custom logic is breaking blocks
|
||||
if (EffortlessBuilding.SERVER_BLOCK_PLACER.isPlacingOrBreakingBlocks()) return;
|
||||
|
||||
if (buildMode != BuildModes.BuildModeEnum.DISABLED || modifierSettings.doQuickReplace()) {
|
||||
BuildModeEnum buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
if (buildMode != BuildModeEnum.DISABLED || EffortlessBuildingClient.QUICK_REPLACE.isQuickReplacing()) {
|
||||
|
||||
//Only cancel if itemblock in hand
|
||||
//Fixed issue with e.g. Create Wrench shift-rightclick disassembling being cancelled.
|
||||
@@ -91,15 +89,19 @@ public class CommonEvents {
|
||||
Player player = event.getPlayer();
|
||||
if (player instanceof FakePlayer) return;
|
||||
|
||||
//Don't cancel event if our custom logic is breaking blocks
|
||||
if (EffortlessBuilding.SERVER_BLOCK_PLACER.isPlacingOrBreakingBlocks()) return;
|
||||
|
||||
//Cancel event if necessary
|
||||
//If cant break far then dont cancel event ever
|
||||
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
if (buildMode != BuildModes.BuildModeEnum.DISABLED && ReachHelper.canBreakFar(player)) {
|
||||
BuildModeEnum buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
if (buildMode != BuildModeEnum.DISABLED && ReachHelper.canBreakFar(player)) {
|
||||
event.setCanceled(true);
|
||||
} else {
|
||||
//NORMAL mode, let vanilla handle block breaking
|
||||
|
||||
//Add to undo stack in client
|
||||
//TODO move UndoRedo to serverside only
|
||||
if (player instanceof ServerPlayer && event.getState() != null && event.getPos() != null) {
|
||||
PacketDistributor.PacketTarget packetTarget = PacketDistributor.PLAYER.with(() -> (ServerPlayer) player);
|
||||
if (packetTarget != null)
|
||||
@@ -119,7 +121,6 @@ public class CommonEvents {
|
||||
if (event.getEntity() instanceof FakePlayer) return;
|
||||
Player player = event.getEntity();
|
||||
ModifierSettingsManager.handleNewPlayer(player);
|
||||
ModeSettingsManager.handleNewPlayer(player);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -137,7 +138,6 @@ public class CommonEvents {
|
||||
if (event.getEntity() instanceof FakePlayer) return;
|
||||
Player player = event.getEntity();
|
||||
ModifierSettingsManager.handleNewPlayer(player);
|
||||
ModeSettingsManager.handleNewPlayer(player);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -146,11 +146,6 @@ public class CommonEvents {
|
||||
Player player = event.getEntity();
|
||||
if (player.getCommandSenderWorld().isClientSide) return;
|
||||
|
||||
//Set build mode to normal
|
||||
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
modeSettings.setBuildMode(BuildModes.BuildModeEnum.DISABLED);
|
||||
ModeSettingsManager.setModeSettings(player, modeSettings);
|
||||
|
||||
//Disable modifiers
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
modifierSettings.getMirrorSettings().enabled = false;
|
||||
@@ -159,7 +154,6 @@ public class CommonEvents {
|
||||
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
|
||||
|
||||
ModifierSettingsManager.handleNewPlayer(player);
|
||||
ModeSettingsManager.handleNewPlayer(player);
|
||||
|
||||
UndoRedo.clear(player);
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ClearUndoMessage());
|
||||
@@ -174,7 +168,6 @@ public class CommonEvents {
|
||||
|
||||
Player newPlayer = event.getEntity();
|
||||
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
|
||||
ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class EffortlessBuilding {
|
||||
public static final Logger logger = LogManager.getLogger();
|
||||
|
||||
public static EffortlessBuilding instance;
|
||||
public static IProxy proxy = DistExecutor.safeRunForDist(() -> 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 DelayedBlockPlacer DELAYED_BLOCK_PLACER = new DelayedBlockPlacer();
|
||||
|
||||
@@ -8,13 +8,17 @@ import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
|
||||
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagScreen;
|
||||
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagScreen;
|
||||
import nl.requios.effortlessbuilding.gui.RandomizerBagScreen;
|
||||
import nl.requios.effortlessbuilding.render.BlockPreviews;
|
||||
import nl.requios.effortlessbuilding.systems.BuilderChain;
|
||||
import nl.requios.effortlessbuilding.systems.QuickReplace;
|
||||
|
||||
public class EffortlessBuildingClient {
|
||||
|
||||
public static final BuilderChain BUILDER_CHAIN = new BuilderChain();
|
||||
public static final BuildModes BUILD_MODES = new BuildModes();
|
||||
public static final BuildModifiers BUILD_MODIFIERS = new BuildModifiers();
|
||||
public static final QuickReplace QUICK_REPLACE = new QuickReplace();
|
||||
public static final BlockPreviews BLOCK_PREVIEWS = new BlockPreviews();
|
||||
|
||||
public static void onConstructorClient(IEventBus modEventBus, IEventBus forgeEventBus) {
|
||||
modEventBus.addListener(EffortlessBuildingClient::clientSetup);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
import com.mojang.math.Vector4f;
|
||||
|
||||
public enum BuildModeCategoryEnum {
|
||||
BASIC(new Vector4f(0f, .5f, 1f, .8f)),
|
||||
DIAGONAL(new Vector4f(0.56f, 0.28f, 0.87f, .8f)),
|
||||
CIRCULAR(new Vector4f(0.29f, 0.76f, 0.3f, 1f)),
|
||||
ROOF(new Vector4f(0.83f, 0.87f, 0.23f, .8f));
|
||||
|
||||
public final Vector4f color;
|
||||
|
||||
BuildModeCategoryEnum(Vector4f color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
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);
|
||||
// PYRAMID("pyramid", new Pyramid(), BuildModeCategoryEnum.ROOF),
|
||||
// CONE("cone", new Cone(), BuildModeCategoryEnum.ROOF),
|
||||
// DOME("dome", new Dome(), BuildModeCategoryEnum.ROOF);
|
||||
|
||||
private final String name;
|
||||
public final IBuildMode instance;
|
||||
public final BuildModeCategoryEnum category;
|
||||
public final ModeOptions.OptionEnum[] options;
|
||||
|
||||
BuildModeEnum(String name, IBuildMode instance, BuildModeCategoryEnum category, ModeOptions.OptionEnum... options) {
|
||||
this.name = name;
|
||||
this.instance = instance;
|
||||
this.category = category;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public String getNameKey() {
|
||||
return "effortlessbuilding.mode." + name;
|
||||
}
|
||||
|
||||
public String getDescriptionKey() {
|
||||
return "effortlessbuilding.modedescription." + name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
import com.mojang.math.Vector4f;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import nl.requios.effortlessbuilding.buildmode.buildmodes.*;
|
||||
import nl.requios.effortlessbuilding.network.IsUsingBuildModePacket;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class BuildModes {
|
||||
private BuildModeEnum buildMode = BuildModeEnum.DISABLED;
|
||||
|
||||
public void findCoordinates(List<BlockEntry> blocks, Player player, BuildModeEnum buildMode) {
|
||||
buildMode.instance.findCoordinates(blocks);
|
||||
@@ -29,12 +27,18 @@ public class BuildModes {
|
||||
}
|
||||
}
|
||||
|
||||
public BuildModeEnum getBuildMode(Player player) {
|
||||
return ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
public BuildModeEnum getBuildMode() {
|
||||
return buildMode;
|
||||
}
|
||||
|
||||
public void onCancel(Player player) {
|
||||
getBuildMode(player).instance.initialize();
|
||||
public void setBuildMode(BuildModeEnum buildMode) {
|
||||
this.buildMode = buildMode;
|
||||
|
||||
PacketHandler.INSTANCE.sendToServer(new IsUsingBuildModePacket(this.buildMode != BuildModeEnum.DISABLED));
|
||||
}
|
||||
|
||||
public void onCancel() {
|
||||
getBuildMode().instance.initialize();
|
||||
}
|
||||
|
||||
//Find coordinates on a line bound by a plane
|
||||
@@ -102,54 +106,4 @@ public class BuildModes {
|
||||
!intersects;
|
||||
}
|
||||
|
||||
public enum BuildModeEnum {
|
||||
DISABLED("normal", new Disabled(), BuildModeCategoryEnum.BASIC),
|
||||
SINGLE("normal_plus", new Single(), BuildModeCategoryEnum.BASIC, OptionEnum.BUILD_SPEED),
|
||||
LINE("line", new Line(), BuildModeCategoryEnum.BASIC /*, OptionEnum.THICKNESS*/),
|
||||
WALL("wall", new Wall(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL),
|
||||
FLOOR("floor", new Floor(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL),
|
||||
CUBE("cube", new Cube(), BuildModeCategoryEnum.BASIC, 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, OptionEnum.RAISED_EDGE),
|
||||
CIRCLE("circle", new Circle(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL),
|
||||
CYLINDER("cylinder", new Cylinder(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL),
|
||||
SPHERE("sphere", new Sphere(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL);
|
||||
// PYRAMID("pyramid", new Pyramid(), BuildModeCategoryEnum.ROOF),
|
||||
// CONE("cone", new Cone(), BuildModeCategoryEnum.ROOF),
|
||||
// DOME("dome", new Dome(), BuildModeCategoryEnum.ROOF);
|
||||
|
||||
private final String name;
|
||||
public final IBuildMode instance;
|
||||
public final BuildModeCategoryEnum category;
|
||||
public final OptionEnum[] options;
|
||||
|
||||
BuildModeEnum(String name, IBuildMode instance, BuildModeCategoryEnum category, OptionEnum... options) {
|
||||
this.name = name;
|
||||
this.instance = instance;
|
||||
this.category = category;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public String getNameKey() {
|
||||
return "effortlessbuilding.mode." + name;
|
||||
}
|
||||
|
||||
public String getDescriptionKey() {
|
||||
return "effortlessbuilding.modedescription." + name;
|
||||
}
|
||||
}
|
||||
|
||||
public enum BuildModeCategoryEnum {
|
||||
BASIC(new Vector4f(0f, .5f, 1f, .8f)),
|
||||
DIAGONAL(new Vector4f(0.56f, 0.28f, 0.87f, .8f)),
|
||||
CIRCULAR(new Vector4f(0.29f, 0.76f, 0.3f, 1f)),
|
||||
ROOF(new Vector4f(0.83f, 0.87f, 0.23f, .8f));
|
||||
|
||||
public final Vector4f color;
|
||||
|
||||
BuildModeCategoryEnum(Vector4f color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import nl.requios.effortlessbuilding.ClientEvents;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
|
||||
import nl.requios.effortlessbuilding.proxy.ClientProxy;
|
||||
|
||||
public class ModeOptions {
|
||||
|
||||
@@ -72,10 +72,8 @@ public class ModeOptions {
|
||||
UndoRedo.redo(player);
|
||||
break;
|
||||
case REPLACE:
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
|
||||
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
|
||||
modifierSettings.doQuickReplace() ? "on" : "off"), true);
|
||||
if (player.level.isClientSide)
|
||||
EffortlessBuildingClient.QUICK_REPLACE.toggleQuickReplacing();
|
||||
break;
|
||||
case OPEN_MODIFIER_SETTINGS:
|
||||
if (player.level.isClientSide)
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class ModeSettingsManager {
|
||||
|
||||
//Retrieves the buildsettings of a player through the modeCapability capability
|
||||
//Never returns null
|
||||
@Nonnull
|
||||
public static ModeSettings getModeSettings(Player player) {
|
||||
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
|
||||
player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
|
||||
|
||||
if (modeCapability.isPresent()) {
|
||||
ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null);
|
||||
if (capability.getModeData() == null){
|
||||
capability.setModeData(new ModeSettings());
|
||||
}
|
||||
return capability.getModeData();
|
||||
}
|
||||
|
||||
EffortlessBuilding.logger.warn("Player does not have modeCapability: " + player);
|
||||
//Return dummy settings
|
||||
return new ModeSettings();
|
||||
}
|
||||
|
||||
public static void setModeSettings(Player player, ModeSettings modeSettings) {
|
||||
if (player == null) {
|
||||
EffortlessBuilding.log("Cannot set buildmode settings, player is null");
|
||||
return;
|
||||
}
|
||||
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
|
||||
player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
|
||||
|
||||
modeCapability.ifPresent((capability) -> {
|
||||
capability.setModeData(modeSettings);
|
||||
|
||||
if (player.level.isClientSide) {
|
||||
EffortlessBuildingClient.BUILDER_CHAIN.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
if (!modeCapability.isPresent()) {
|
||||
EffortlessBuilding.log(player, "Saving buildmode settings failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public static String sanitize(ModeSettings modeSettings, Player player) {
|
||||
String error = "";
|
||||
return error;
|
||||
}
|
||||
|
||||
public static void handleNewPlayer(Player player) {
|
||||
//Makes sure player has mode settings (if it doesnt it will create it)
|
||||
getModeSettings(player);
|
||||
|
||||
//Only on server
|
||||
if (!player.level.isClientSide) {
|
||||
//Send to client
|
||||
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModeSettings {
|
||||
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.DISABLED;
|
||||
|
||||
public ModeSettings() {
|
||||
}
|
||||
|
||||
public ModeSettings(BuildModes.BuildModeEnum buildMode) {
|
||||
this.buildMode = buildMode;
|
||||
}
|
||||
|
||||
public BuildModes.BuildModeEnum getBuildMode() {
|
||||
return this.buildMode;
|
||||
}
|
||||
|
||||
public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
|
||||
this.buildMode = buildMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ThreeClicksBuildMode extends BaseBuildMode {
|
||||
protected BlockEntry firstBlockEntry;
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
package nl.requios.effortlessbuilding.buildmode;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Dictionary;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class TwoClicksBuildMode extends BaseBuildMode {
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package nl.requios.effortlessbuilding.buildmode.buildmodes;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Disabled implements IBuildMode {
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package nl.requios.effortlessbuilding.buildmode.buildmodes;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Single implements IBuildMode {
|
||||
|
||||
@@ -52,7 +52,7 @@ public class BuildModifiers {
|
||||
|
||||
if (world.isClientSide) {
|
||||
|
||||
BlockPreviews.onBlocksPlaced();
|
||||
// BlockPreviews.onBlocksPlaced(blocks);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -79,7 +79,7 @@ public class BuildModifiers {
|
||||
}
|
||||
|
||||
if (world.isClientSide) {
|
||||
BlockPreviews.onBlocksBroken();
|
||||
// BlockPreviews.onBlocksBroken(blocks);
|
||||
|
||||
//list of air blockstates
|
||||
for (int i = 0; i < coordinates.size(); i++) {
|
||||
@@ -205,14 +205,6 @@ public class BuildModifiers {
|
||||
return blockStates;
|
||||
}
|
||||
|
||||
public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
|
||||
//startPos can be null
|
||||
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
|
||||
Array.isEnabled(modifierSettings.getArraySettings()) ||
|
||||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
|
||||
modifierSettings.doQuickReplace();
|
||||
}
|
||||
|
||||
public static BlockState getBlockStateFromItem(ItemStack itemStack, Player player, BlockPos blockPos, Direction facing, Vec3 hitVec, InteractionHand hand) {
|
||||
return Block.byItem(itemStack.getItem()).getStateForPlacement(new BlockPlaceContext(new UseOnContext(player, hand, new BlockHitResult(hitVec, facing, blockPos, false))));
|
||||
}
|
||||
|
||||
@@ -99,14 +99,6 @@ public class ModifierSettingsManager {
|
||||
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
|
||||
}
|
||||
|
||||
//Other
|
||||
if (modifierSettings.reachUpgrade < 0) {
|
||||
modifierSettings.reachUpgrade = 0;
|
||||
}
|
||||
if (modifierSettings.reachUpgrade > 3) {
|
||||
modifierSettings.reachUpgrade = 3;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -126,8 +118,6 @@ public class ModifierSettingsManager {
|
||||
private Mirror.MirrorSettings mirrorSettings;
|
||||
private Array.ArraySettings arraySettings;
|
||||
private RadialMirror.RadialMirrorSettings radialMirrorSettings;
|
||||
private boolean quickReplace = false;
|
||||
private int reachUpgrade = 0;
|
||||
|
||||
public ModifierSettings() {
|
||||
mirrorSettings = new Mirror.MirrorSettings();
|
||||
@@ -136,12 +126,10 @@ public class ModifierSettingsManager {
|
||||
}
|
||||
|
||||
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
|
||||
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
|
||||
RadialMirror.RadialMirrorSettings radialMirrorSettings) {
|
||||
this.mirrorSettings = mirrorSettings;
|
||||
this.arraySettings = arraySettings;
|
||||
this.radialMirrorSettings = radialMirrorSettings;
|
||||
this.quickReplace = quickReplace;
|
||||
this.reachUpgrade = reachUpgrade;
|
||||
}
|
||||
|
||||
public Mirror.MirrorSettings getMirrorSettings() {
|
||||
@@ -173,43 +161,6 @@ public class ModifierSettingsManager {
|
||||
if (radialMirrorSettings == null) return;
|
||||
this.radialMirrorSettings = radialMirrorSettings;
|
||||
}
|
||||
|
||||
public boolean doQuickReplace() {
|
||||
return quickReplace;
|
||||
}
|
||||
|
||||
public void setQuickReplace(boolean quickReplace) {
|
||||
this.quickReplace = quickReplace;
|
||||
}
|
||||
|
||||
public int getReachUpgrade() {
|
||||
return reachUpgrade;
|
||||
}
|
||||
|
||||
public void setReachUpgrade(int reachUpgrade) {
|
||||
this.reachUpgrade = reachUpgrade;
|
||||
//Set mirror radius to max
|
||||
int reach = 10;
|
||||
switch (reachUpgrade) {
|
||||
case 0:
|
||||
reach = CommonConfig.reach.maxReachLevel0.get();
|
||||
break;
|
||||
case 1:
|
||||
reach = CommonConfig.reach.maxReachLevel1.get();
|
||||
break;
|
||||
case 2:
|
||||
reach = CommonConfig.reach.maxReachLevel2.get();
|
||||
break;
|
||||
case 3:
|
||||
reach = CommonConfig.reach.maxReachLevel3.get();
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.mirrorSettings != null)
|
||||
this.mirrorSettings.radius = reach / 2;
|
||||
if (this.radialMirrorSettings != null)
|
||||
this.radialMirrorSettings.radius = reach / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public class UndoRedo {
|
||||
List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates);
|
||||
|
||||
if (player.level.isClientSide) {
|
||||
BlockPreviews.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
|
||||
// BlockPreviews.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
|
||||
} else {
|
||||
//break all those blocks, reset to what they were
|
||||
for (int i = 0; i < coordinates.size(); i++) {
|
||||
@@ -146,7 +146,7 @@ public class UndoRedo {
|
||||
List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates);
|
||||
|
||||
if (player.level.isClientSide) {
|
||||
BlockPreviews.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
|
||||
// BlockPreviews.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
|
||||
} else {
|
||||
//place blocks
|
||||
for (int i = 0; i < coordinates.size(); i++) {
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
package nl.requios.effortlessbuilding.capability;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraftforge.common.capabilities.*;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class ModeCapabilityManager {
|
||||
|
||||
public static Capability<IModeCapability> MODE_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
|
||||
// Allows for the capability to persist after death.
|
||||
@SubscribeEvent
|
||||
public static void clonePlayer(PlayerEvent.Clone event) {
|
||||
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(MODE_CAPABILITY, null);
|
||||
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(MODE_CAPABILITY, null);
|
||||
clone.ifPresent(cloneModeCapability ->
|
||||
original.ifPresent(originalModeCapability ->
|
||||
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
|
||||
}
|
||||
|
||||
public interface IModeCapability {
|
||||
ModeSettings getModeData();
|
||||
|
||||
void setModeData(ModeSettings modeSettings);
|
||||
}
|
||||
|
||||
public static class ModeCapability implements IModeCapability {
|
||||
private ModeSettings modeSettings;
|
||||
|
||||
@Override
|
||||
public ModeSettings getModeData() {
|
||||
return modeSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModeData(ModeSettings modeSettings) {
|
||||
this.modeSettings = modeSettings;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Provider extends CapabilityProvider<Provider> implements ICapabilitySerializable<Tag> {
|
||||
|
||||
private IModeCapability instance = new ModeCapability();
|
||||
private LazyOptional<IModeCapability> modeCapabilityOptional = LazyOptional.of(() -> instance);
|
||||
|
||||
public Provider() {
|
||||
super(Provider.class);
|
||||
gatherCapabilities();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
if (cap == MODE_CAPABILITY) return modeCapabilityOptional.cast();
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaps() {
|
||||
super.invalidateCaps();
|
||||
modeCapabilityOptional.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reviveCaps() {
|
||||
super.reviveCaps();
|
||||
modeCapabilityOptional = LazyOptional.of(() -> instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag serializeNBT() {
|
||||
CompoundTag compound = new CompoundTag();
|
||||
ModeSettings modeSettings = instance.getModeData();
|
||||
if (modeSettings == null) modeSettings = new ModeSettingsManager.ModeSettings();
|
||||
|
||||
//compound.putInteger("buildMode", modeSettings.getBuildMode().ordinal());
|
||||
|
||||
//TODO add mode settings
|
||||
|
||||
return compound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(Tag nbt) {
|
||||
CompoundTag compound = (CompoundTag) nbt;
|
||||
|
||||
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
|
||||
|
||||
//TODO add mode settings
|
||||
|
||||
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.DISABLED);
|
||||
instance.setModeData(modeSettings);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -113,8 +113,6 @@ public class ModifierCapabilityManager {
|
||||
compound.putInt("arrayOffsetZ", a.offset.getZ());
|
||||
compound.putInt("arrayCount", a.count);
|
||||
|
||||
compound.putInt("reachUpgrade", modifierSettings.getReachUpgrade());
|
||||
|
||||
//compound.putBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
|
||||
|
||||
//RADIAL MIRROR
|
||||
@@ -160,10 +158,6 @@ public class ModifierCapabilityManager {
|
||||
int arrayCount = compound.getInt("arrayCount");
|
||||
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
|
||||
|
||||
int reachUpgrade = compound.getInt("reachUpgrade");
|
||||
|
||||
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
|
||||
|
||||
//RADIAL MIRROR
|
||||
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
|
||||
Vec3 radialMirrorPosition = new Vec3(
|
||||
@@ -178,7 +172,7 @@ public class ModifierCapabilityManager {
|
||||
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
|
||||
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
|
||||
|
||||
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
|
||||
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings);
|
||||
instance.setModifierData(modifierSettings);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderLevelLastEvent;
|
||||
import net.minecraftforge.client.event.ViewportEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.TickEvent.ClientTickEvent;
|
||||
import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -29,10 +30,8 @@ public class ClientEvents {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTick(ClientTickEvent event) {
|
||||
if (!isGameActive())
|
||||
return;
|
||||
if (!isGameActive() || event.phase != TickEvent.Phase.END) return;
|
||||
|
||||
Level world = Minecraft.getInstance().level;
|
||||
AnimationTickHolder.tick();
|
||||
|
||||
CreateClient.GHOST_BLOCKS.tickGhosts();
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.ChatFormatting.*;
|
||||
import static nl.requios.effortlessbuilding.create.foundation.item.TooltipHelper.cutStringTextComponent;
|
||||
import static nl.requios.effortlessbuilding.create.foundation.item.TooltipHelper.cutTextComponent;
|
||||
|
||||
public class ItemDescription {
|
||||
|
||||
public static final ItemDescription MISSING = new ItemDescription(null);
|
||||
public static Component trim = Components.literal(" ").withStyle(WHITE, STRIKETHROUGH);
|
||||
|
||||
public enum Palette {
|
||||
|
||||
Blue(BLUE, AQUA),
|
||||
Green(DARK_GREEN, GREEN),
|
||||
Yellow(GOLD, YELLOW),
|
||||
Red(DARK_RED, RED),
|
||||
Purple(DARK_PURPLE, LIGHT_PURPLE),
|
||||
Gray(DARK_GRAY, GRAY),
|
||||
|
||||
;
|
||||
|
||||
private Palette(ChatFormatting primary, ChatFormatting highlight) {
|
||||
color = primary;
|
||||
hColor = highlight;
|
||||
}
|
||||
|
||||
public ChatFormatting color;
|
||||
public ChatFormatting hColor;
|
||||
}
|
||||
|
||||
private List<Component> lines;
|
||||
private List<Component> linesOnShift;
|
||||
private List<Component> linesOnCtrl;
|
||||
private Palette palette;
|
||||
|
||||
public ItemDescription(Palette palette) {
|
||||
this.palette = palette;
|
||||
lines = new ArrayList<>();
|
||||
linesOnShift = new ArrayList<>();
|
||||
linesOnCtrl = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ItemDescription withSummary(Component summary) {
|
||||
addStrings(linesOnShift, cutTextComponent(summary, palette.color, palette.hColor));
|
||||
return this;
|
||||
}
|
||||
|
||||
public static String makeProgressBar(int length, int filledLength) {
|
||||
String bar = " ";
|
||||
int emptySpaces = length - filledLength;
|
||||
for (int i = 0; i < filledLength; i++)
|
||||
bar += "\u2588";
|
||||
for (int i = 0; i < emptySpaces; i++)
|
||||
bar += "\u2592";
|
||||
return bar + " ";
|
||||
}
|
||||
|
||||
public ItemDescription withBehaviour(String condition, String behaviour) {
|
||||
add(linesOnShift, Components.literal(condition).withStyle(GRAY));
|
||||
addStrings(linesOnShift, cutStringTextComponent(behaviour, palette.color, palette.hColor, 1));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemDescription withControl(String condition, String action) {
|
||||
add(linesOnCtrl, Components.literal(condition).withStyle(GRAY));
|
||||
addStrings(linesOnCtrl, cutStringTextComponent(action, palette.color, palette.hColor, 1));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemDescription createTabs() {
|
||||
boolean hasDescription = !linesOnShift.isEmpty();
|
||||
boolean hasControls = !linesOnCtrl.isEmpty();
|
||||
|
||||
if (hasDescription || hasControls) {
|
||||
String[] holdDesc = Lang.translateDirect("tooltip.holdForDescription", "$")
|
||||
.getString()
|
||||
.split("\\$");
|
||||
String[] holdCtrl = Lang.translateDirect("tooltip.holdForControls", "$")
|
||||
.getString()
|
||||
.split("\\$");
|
||||
MutableComponent keyShift = Lang.translateDirect("tooltip.keyShift");
|
||||
MutableComponent keyCtrl = Lang.translateDirect("tooltip.keyCtrl");
|
||||
for (List<Component> list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) {
|
||||
boolean shift = list == linesOnShift;
|
||||
boolean ctrl = list == linesOnCtrl;
|
||||
|
||||
if (holdDesc.length != 2 || holdCtrl.length != 2) {
|
||||
list.add(0, Components.literal("Invalid lang formatting!"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasControls) {
|
||||
MutableComponent tabBuilder = Components.empty();
|
||||
tabBuilder.append(Components.literal(holdCtrl[0]).withStyle(DARK_GRAY));
|
||||
tabBuilder.append(keyCtrl.plainCopy()
|
||||
.withStyle(ctrl ? WHITE : GRAY));
|
||||
tabBuilder.append(Components.literal(holdCtrl[1]).withStyle(DARK_GRAY));
|
||||
list.add(0, tabBuilder);
|
||||
}
|
||||
|
||||
if (hasDescription) {
|
||||
MutableComponent tabBuilder = Components.empty();
|
||||
tabBuilder.append(Components.literal(holdDesc[0]).withStyle(DARK_GRAY));
|
||||
tabBuilder.append(keyShift.plainCopy()
|
||||
.withStyle(shift ? WHITE : GRAY));
|
||||
tabBuilder.append(Components.literal(holdDesc[1]).withStyle(DARK_GRAY));
|
||||
list.add(0, tabBuilder);
|
||||
}
|
||||
|
||||
if (shift || ctrl)
|
||||
list.add(hasDescription && hasControls ? 2 : 1, Components.immutableEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasDescription)
|
||||
linesOnShift = lines;
|
||||
if (!hasControls)
|
||||
linesOnCtrl = lines;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public static String hightlight(String s, Palette palette) {
|
||||
return palette.hColor + s + palette.color;
|
||||
}
|
||||
|
||||
public static void addStrings(List<Component> infoList, List<Component> textLines) {
|
||||
textLines.forEach(s -> add(infoList, s));
|
||||
}
|
||||
|
||||
public static void add(List<Component> infoList, List<Component> textLines) {
|
||||
infoList.addAll(textLines);
|
||||
}
|
||||
|
||||
public static void add(List<Component> infoList, Component line) {
|
||||
infoList.add(line);
|
||||
}
|
||||
|
||||
public Palette getPalette() {
|
||||
return palette;
|
||||
}
|
||||
|
||||
public List<Component> addInformation(List<Component> tooltip) {
|
||||
if (Screen.hasShiftDown()) {
|
||||
tooltip.addAll(linesOnShift);
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
if (Screen.hasControlDown()) {
|
||||
tooltip.addAll(linesOnCtrl);
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
tooltip.addAll(lines);
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public List<Component> getLines() {
|
||||
return lines;
|
||||
}
|
||||
|
||||
public List<Component> getLinesOnCtrl() {
|
||||
return linesOnCtrl;
|
||||
}
|
||||
|
||||
public List<Component> getLinesOnShift() {
|
||||
return linesOnShift;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
public class ItemHandlerWrapper implements IItemHandlerModifiable {
|
||||
|
||||
private IItemHandlerModifiable wrapped;
|
||||
|
||||
public ItemHandlerWrapper(IItemHandlerModifiable wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
return wrapped.getSlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int slot) {
|
||||
return wrapped.getStackInSlot(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||
return wrapped.insertItem(slot, stack, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
return wrapped.extractItem(slot, amount, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotLimit(int slot) {
|
||||
return wrapped.getSlotLimit(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return wrapped.isItemValid(slot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackInSlot(int slot, ItemStack stack) {
|
||||
wrapped.setStackInSlot(slot, stack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Pair;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ItemHelper {
|
||||
|
||||
public static void dropContents(Level world, BlockPos pos, IItemHandler inv) {
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++)
|
||||
Containers.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), inv.getStackInSlot(slot));
|
||||
}
|
||||
|
||||
public static List<ItemStack> multipliedOutput(ItemStack in, ItemStack out) {
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
ItemStack result = out.copy();
|
||||
result.setCount(in.getCount() * out.getCount());
|
||||
|
||||
while (result.getCount() > result.getMaxStackSize()) {
|
||||
stacks.add(result.split(result.getMaxStackSize()));
|
||||
}
|
||||
|
||||
stacks.add(result);
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public static void addToList(ItemStack stack, List<ItemStack> stacks) {
|
||||
for (ItemStack s : stacks) {
|
||||
if (!ItemHandlerHelper.canItemStacksStack(stack, s))
|
||||
continue;
|
||||
int transferred = Math.min(s.getMaxStackSize() - s.getCount(), stack.getCount());
|
||||
s.grow(transferred);
|
||||
stack.shrink(transferred);
|
||||
}
|
||||
if (stack.getCount() > 0)
|
||||
stacks.add(stack);
|
||||
}
|
||||
|
||||
public static boolean isSameInventory(IItemHandler h1, IItemHandler h2) {
|
||||
if (h1 == null || h2 == null)
|
||||
return false;
|
||||
if (h1.getSlots() != h2.getSlots())
|
||||
return false;
|
||||
for (int slot = 0; slot < h1.getSlots(); slot++) {
|
||||
if (h1.getStackInSlot(slot) != h2.getStackInSlot(slot))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int calcRedstoneFromInventory(@Nullable IItemHandler inv) {
|
||||
if (inv == null)
|
||||
return 0;
|
||||
int i = 0;
|
||||
float f = 0.0F;
|
||||
int totalSlots = inv.getSlots();
|
||||
|
||||
for (int j = 0; j < inv.getSlots(); ++j) {
|
||||
int slotLimit = inv.getSlotLimit(j);
|
||||
if (slotLimit == 0) {
|
||||
totalSlots--;
|
||||
continue;
|
||||
}
|
||||
ItemStack itemstack = inv.getStackInSlot(j);
|
||||
if (!itemstack.isEmpty()) {
|
||||
f += (float) itemstack.getCount() / (float) Math.min(slotLimit, itemstack.getMaxStackSize());
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalSlots == 0)
|
||||
return 0;
|
||||
|
||||
f = f / totalSlots;
|
||||
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
public static List<Pair<Ingredient, MutableInt>> condenseIngredients(NonNullList<Ingredient> recipeIngredients) {
|
||||
List<Pair<Ingredient, MutableInt>> actualIngredients = new ArrayList<>();
|
||||
Ingredients: for (Ingredient igd : recipeIngredients) {
|
||||
for (Pair<Ingredient, MutableInt> pair : actualIngredients) {
|
||||
ItemStack[] stacks1 = pair.getFirst()
|
||||
.getItems();
|
||||
ItemStack[] stacks2 = igd.getItems();
|
||||
if (stacks1.length != stacks2.length)
|
||||
continue;
|
||||
for (int i = 0; i <= stacks1.length; i++) {
|
||||
if (i == stacks1.length) {
|
||||
pair.getSecond()
|
||||
.increment();
|
||||
continue Ingredients;
|
||||
}
|
||||
if (!ItemStack.matches(stacks1[i], stacks2[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
actualIngredients.add(Pair.of(igd, new MutableInt(1)));
|
||||
}
|
||||
return actualIngredients;
|
||||
}
|
||||
|
||||
public static boolean matchIngredients(Ingredient i1, Ingredient i2) {
|
||||
if (i1 == i2)
|
||||
return true;
|
||||
ItemStack[] stacks1 = i1.getItems();
|
||||
ItemStack[] stacks2 = i2.getItems();
|
||||
if (stacks1 == stacks2)
|
||||
return true;
|
||||
if (stacks1.length == stacks2.length) {
|
||||
for (int i = 0; i < stacks1.length; i++)
|
||||
if (!ItemStack.isSame(stacks1[i], stacks2[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean matchAllIngredients(NonNullList<Ingredient> ingredients) {
|
||||
if (ingredients.size() <= 1)
|
||||
return true;
|
||||
Ingredient firstIngredient = ingredients.get(0);
|
||||
for (int i = 1; i < ingredients.size(); i++)
|
||||
if (!matchIngredients(firstIngredient, ingredients.get(i)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static enum ExtractionCountMode {
|
||||
EXACTLY, UPTO
|
||||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, boolean simulate) {
|
||||
return extract(inv, test, ExtractionCountMode.UPTO, 64, simulate);
|
||||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, int exactAmount, boolean simulate) {
|
||||
return extract(inv, test, ExtractionCountMode.EXACTLY, exactAmount, simulate);
|
||||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, ExtractionCountMode mode, int amount,
|
||||
boolean simulate) {
|
||||
ItemStack extracting = ItemStack.EMPTY;
|
||||
boolean amountRequired = mode == ExtractionCountMode.EXACTLY;
|
||||
boolean checkHasEnoughItems = amountRequired;
|
||||
boolean hasEnoughItems = !checkHasEnoughItems;
|
||||
boolean potentialOtherMatch = false;
|
||||
int maxExtractionCount = amount;
|
||||
|
||||
Extraction: do {
|
||||
extracting = ItemStack.EMPTY;
|
||||
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
int amountToExtractFromThisSlot =
|
||||
Math.min(maxExtractionCount - extracting.getCount(), inv.getStackInSlot(slot)
|
||||
.getMaxStackSize());
|
||||
ItemStack stack = inv.extractItem(slot, amountToExtractFromThisSlot, true);
|
||||
|
||||
if (stack.isEmpty())
|
||||
continue;
|
||||
if (!test.test(stack))
|
||||
continue;
|
||||
if (!extracting.isEmpty() && !canItemStackAmountsStack(stack, extracting)) {
|
||||
potentialOtherMatch = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extracting.isEmpty())
|
||||
extracting = stack.copy();
|
||||
else
|
||||
extracting.grow(stack.getCount());
|
||||
|
||||
if (!simulate && hasEnoughItems)
|
||||
inv.extractItem(slot, stack.getCount(), false);
|
||||
|
||||
if (extracting.getCount() >= maxExtractionCount) {
|
||||
if (checkHasEnoughItems) {
|
||||
hasEnoughItems = true;
|
||||
checkHasEnoughItems = false;
|
||||
continue Extraction;
|
||||
} else {
|
||||
break Extraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!extracting.isEmpty() && !hasEnoughItems && potentialOtherMatch) {
|
||||
ItemStack blackListed = extracting.copy();
|
||||
test = test.and(i -> !ItemHandlerHelper.canItemStacksStack(i, blackListed));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkHasEnoughItems)
|
||||
checkHasEnoughItems = false;
|
||||
else
|
||||
break Extraction;
|
||||
|
||||
} while (true);
|
||||
|
||||
if (amountRequired && extracting.getCount() < amount)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
return extracting;
|
||||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test,
|
||||
Function<ItemStack, Integer> amountFunction, boolean simulate) {
|
||||
ItemStack extracting = ItemStack.EMPTY;
|
||||
int maxExtractionCount = 64;
|
||||
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
if (extracting.isEmpty()) {
|
||||
ItemStack stackInSlot = inv.getStackInSlot(slot);
|
||||
if (stackInSlot.isEmpty() || !test.test(stackInSlot))
|
||||
continue;
|
||||
int maxExtractionCountForItem = amountFunction.apply(stackInSlot);
|
||||
if (maxExtractionCountForItem == 0)
|
||||
continue;
|
||||
maxExtractionCount = Math.min(maxExtractionCount, maxExtractionCountForItem);
|
||||
}
|
||||
|
||||
ItemStack stack = inv.extractItem(slot, maxExtractionCount - extracting.getCount(), true);
|
||||
|
||||
if (!test.test(stack))
|
||||
continue;
|
||||
if (!extracting.isEmpty() && !canItemStackAmountsStack(stack, extracting))
|
||||
continue;
|
||||
|
||||
if (extracting.isEmpty())
|
||||
extracting = stack.copy();
|
||||
else
|
||||
extracting.grow(stack.getCount());
|
||||
|
||||
if (!simulate)
|
||||
inv.extractItem(slot, stack.getCount(), false);
|
||||
if (extracting.getCount() >= maxExtractionCount)
|
||||
break;
|
||||
}
|
||||
|
||||
return extracting;
|
||||
}
|
||||
|
||||
public static boolean canItemStackAmountsStack(ItemStack a, ItemStack b) {
|
||||
return ItemHandlerHelper.canItemStacksStack(a, b) && a.getCount() + b.getCount() <= a.getMaxStackSize();
|
||||
}
|
||||
|
||||
public static ItemStack findFirstMatch(IItemHandler inv, Predicate<ItemStack> test) {
|
||||
int slot = findFirstMatchingSlotIndex(inv, test);
|
||||
if (slot == -1)
|
||||
return ItemStack.EMPTY;
|
||||
else
|
||||
return inv.getStackInSlot(slot);
|
||||
}
|
||||
|
||||
public static int findFirstMatchingSlotIndex(IItemHandler inv, Predicate<ItemStack> test) {
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
ItemStack toTest = inv.getStackInSlot(slot);
|
||||
if (test.test(toTest))
|
||||
return slot;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.tags.ITagManager;
|
||||
|
||||
public class TagDependentIngredientItem extends Item {
|
||||
|
||||
private TagKey<Item> tag;
|
||||
|
||||
public TagDependentIngredientItem(Properties properties, TagKey<Item> tag) {
|
||||
super(properties);
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillItemCategory(CreativeModeTab tab, NonNullList<ItemStack> list) {
|
||||
if (!shouldHide())
|
||||
super.fillItemCategory(tab, list);
|
||||
}
|
||||
|
||||
public boolean shouldHide() {
|
||||
ITagManager<Item> tagManager = ForgeRegistries.ITEMS.tags();
|
||||
return !tagManager.isKnownTagName(tag) || tagManager.getTag(tag).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.mojang.bridge.game.Language;
|
||||
import nl.requios.effortlessbuilding.create.foundation.item.ItemDescription.Palette;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Couple;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.FontHelper;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Lang;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.resources.language.I18n;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.text.BreakIterator;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TooltipHelper {
|
||||
|
||||
public static final int maxWidthPerLine = 200;
|
||||
public static final Map<String, ItemDescription> cachedTooltips = new HashMap<>();
|
||||
public static Language cachedLanguage;
|
||||
private static boolean gogglesMode;
|
||||
private static final Map<Item, Supplier<String>> tooltipReferrals = new HashMap<>();
|
||||
|
||||
public static MutableComponent holdShift(Palette color, boolean highlighted) {
|
||||
return Lang.translateDirect("tooltip.holdForDescription", Lang.translateDirect("tooltip.keyShift")
|
||||
.withStyle(ChatFormatting.GRAY))
|
||||
.withStyle(ChatFormatting.DARK_GRAY);
|
||||
}
|
||||
|
||||
public static void addHint(List<Component> tooltip, String hintKey, Object... messageParams) {
|
||||
Component spacing = Components.literal("");
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(Lang.translateDirect(hintKey + ".title"))
|
||||
.withStyle(ChatFormatting.GOLD));
|
||||
Component hint = Lang.translateDirect(hintKey);
|
||||
List<Component> cutComponent = TooltipHelper.cutTextComponent(hint, ChatFormatting.GRAY, ChatFormatting.WHITE);
|
||||
for (Component component : cutComponent)
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(component));
|
||||
}
|
||||
|
||||
public static void referTo(ItemLike item, Supplier<? extends ItemLike> itemWithTooltip) {
|
||||
tooltipReferrals.put(item.asItem(), () -> itemWithTooltip.get()
|
||||
.asItem()
|
||||
.getDescriptionId());
|
||||
}
|
||||
|
||||
public static void referTo(ItemLike item, String string) {
|
||||
tooltipReferrals.put(item.asItem(), () -> string);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<String> cutString(Component s, ChatFormatting defaultColor, ChatFormatting highlightColor) {
|
||||
return cutString(s.getString(), defaultColor, highlightColor, 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<String> cutString(String s, ChatFormatting defaultColor, ChatFormatting highlightColor,
|
||||
int indent) {
|
||||
// Apply markup
|
||||
String markedUp = s.replaceAll("_([^_]+)_", highlightColor + "$1" + defaultColor);
|
||||
|
||||
// Split words
|
||||
List<String> words = new LinkedList<>();
|
||||
BreakIterator iterator = BreakIterator.getLineInstance(Minecraft.getInstance().getLocale());
|
||||
iterator.setText(markedUp);
|
||||
int start = iterator.first();
|
||||
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) {
|
||||
String word = markedUp.substring(start, end);
|
||||
words.add(word);
|
||||
}
|
||||
|
||||
Font font = Minecraft.getInstance().font;
|
||||
List<String> lines = FontHelper.cutString(font, markedUp, maxWidthPerLine);
|
||||
|
||||
// Format
|
||||
String lineStart = Strings.repeat(" ", indent);
|
||||
List<String> formattedLines = new ArrayList<>(lines.size());
|
||||
String format = defaultColor.toString();
|
||||
for (String line : lines) {
|
||||
String formattedLine = format + lineStart + line;
|
||||
formattedLines.add(formattedLine);
|
||||
// format = TextFormatting.getFormatString(formattedLine);
|
||||
}
|
||||
return formattedLines;
|
||||
}
|
||||
|
||||
public static List<Component> cutStringTextComponent(String c, ChatFormatting defaultColor,
|
||||
ChatFormatting highlightColor) {
|
||||
return cutTextComponent(Components.literal(c), defaultColor, highlightColor, 0);
|
||||
}
|
||||
|
||||
public static List<Component> cutTextComponent(Component c, ChatFormatting defaultColor,
|
||||
ChatFormatting highlightColor) {
|
||||
return cutTextComponent(c, defaultColor, highlightColor, 0);
|
||||
}
|
||||
|
||||
public static List<Component> cutStringTextComponent(String c, ChatFormatting defaultColor,
|
||||
ChatFormatting highlightColor, int indent) {
|
||||
return cutTextComponent(Components.literal(c), defaultColor, highlightColor, indent);
|
||||
}
|
||||
|
||||
public static List<Component> cutTextComponent(Component c, ChatFormatting defaultColor,
|
||||
ChatFormatting highlightColor, int indent) {
|
||||
String s = c.getString();
|
||||
|
||||
// Apply markup
|
||||
String markedUp = s;// .replaceAll("_([^_]+)_", highlightColor + "$1" + defaultColor);
|
||||
|
||||
// Split words
|
||||
List<String> words = new LinkedList<>();
|
||||
BreakIterator iterator = BreakIterator.getLineInstance(Minecraft.getInstance().getLocale());
|
||||
iterator.setText(markedUp);
|
||||
int start = iterator.first();
|
||||
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) {
|
||||
String word = markedUp.substring(start, end);
|
||||
words.add(word);
|
||||
}
|
||||
|
||||
// Apply hard wrap
|
||||
Font font = Minecraft.getInstance().font;
|
||||
List<String> lines = new LinkedList<>();
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
int width = 0;
|
||||
for (String word : words) {
|
||||
int newWidth = font.width(word.replaceAll("_", ""));
|
||||
if (width + newWidth > maxWidthPerLine) {
|
||||
if (width > 0) {
|
||||
String line = currentLine.toString();
|
||||
lines.add(line);
|
||||
currentLine = new StringBuilder();
|
||||
width = 0;
|
||||
} else {
|
||||
lines.add(word);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
currentLine.append(word);
|
||||
width += newWidth;
|
||||
}
|
||||
if (width > 0) {
|
||||
lines.add(currentLine.toString());
|
||||
}
|
||||
|
||||
// Format
|
||||
MutableComponent lineStart = Components.literal(Strings.repeat(" ", indent));
|
||||
lineStart.withStyle(defaultColor);
|
||||
List<Component> formattedLines = new ArrayList<>(lines.size());
|
||||
Couple<ChatFormatting> f = Couple.create(highlightColor, defaultColor);
|
||||
|
||||
boolean currentlyHighlighted = false;
|
||||
for (String string : lines) {
|
||||
MutableComponent currentComponent = lineStart.plainCopy();
|
||||
String[] split = string.split("_");
|
||||
for (String part : split) {
|
||||
currentComponent.append(Components.literal(part).withStyle(f.get(currentlyHighlighted)));
|
||||
currentlyHighlighted = !currentlyHighlighted;
|
||||
}
|
||||
|
||||
formattedLines.add(currentComponent);
|
||||
currentlyHighlighted = !currentlyHighlighted;
|
||||
}
|
||||
|
||||
return formattedLines;
|
||||
}
|
||||
|
||||
// public static List<ITextComponent> cutTextComponentOld(ITextComponent c, TextFormatting defaultColor,
|
||||
// TextFormatting highlightColor, int indent) {
|
||||
// IFormattableTextComponent lineStart = StringTextComponent.EMPTY.copy();
|
||||
// for (int i = 0; i < indent; i++)
|
||||
// lineStart.append(" ");
|
||||
// lineStart.formatted(defaultColor);
|
||||
//
|
||||
// List<ITextComponent> lines = new ArrayList<>();
|
||||
// String rawText = getUnformattedDeepText(c);
|
||||
// String[] words = rawText.split(" ");
|
||||
// String word;
|
||||
// IFormattableTextComponent currentLine = lineStart.copy();
|
||||
//
|
||||
// boolean firstWord = true;
|
||||
// boolean lastWord;
|
||||
//
|
||||
// // Apply hard wrap
|
||||
// for (int i = 0; i < words.length; i++) {
|
||||
// word = words[i];
|
||||
// lastWord = i == words.length - 1;
|
||||
//
|
||||
// if (!lastWord && !firstWord && getComponentLength(currentLine) + word.length() > maxCharsPerLine) {
|
||||
// lines.add(currentLine);
|
||||
// currentLine = lineStart.copy();
|
||||
// firstWord = true;
|
||||
// }
|
||||
//
|
||||
// currentLine.append(new StringTextComponent((firstWord ? "" : " ") + word.replace("_", ""))
|
||||
// .formatted(word.matches("_([^_]+)_") ? highlightColor : defaultColor));
|
||||
// firstWord = false;
|
||||
// }
|
||||
//
|
||||
// if (!firstWord) {
|
||||
// lines.add(currentLine);
|
||||
// }
|
||||
//
|
||||
// return lines;
|
||||
// }
|
||||
|
||||
private static void checkLocale() {
|
||||
Language currentLanguage = Minecraft.getInstance()
|
||||
.getLanguageManager()
|
||||
.getSelected();
|
||||
if (cachedLanguage != currentLanguage) {
|
||||
cachedTooltips.clear();
|
||||
cachedLanguage = currentLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasTooltip(ItemStack stack, Player player) {
|
||||
checkLocale();
|
||||
|
||||
String key = getTooltipTranslationKey(stack);
|
||||
if (cachedTooltips.containsKey(key))
|
||||
return cachedTooltips.get(key) != ItemDescription.MISSING;
|
||||
return findTooltip(stack);
|
||||
}
|
||||
|
||||
public static ItemDescription getTooltip(ItemStack stack) {
|
||||
checkLocale();
|
||||
String key = getTooltipTranslationKey(stack);
|
||||
if (cachedTooltips.containsKey(key)) {
|
||||
ItemDescription itemDescription = cachedTooltips.get(key);
|
||||
if (itemDescription != ItemDescription.MISSING)
|
||||
return itemDescription;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean findTooltip(ItemStack stack) {
|
||||
String key = getTooltipTranslationKey(stack);
|
||||
if (I18n.exists(key)) {
|
||||
cachedTooltips.put(key, buildToolTip(key, stack));
|
||||
return true;
|
||||
}
|
||||
cachedTooltips.put(key, ItemDescription.MISSING);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ItemDescription buildToolTip(String translationKey, ItemStack stack) {
|
||||
ItemDescription tooltip = new ItemDescription(Palette.Blue);
|
||||
String summaryKey = translationKey + ".summary";
|
||||
|
||||
// Summary
|
||||
if (I18n.exists(summaryKey))
|
||||
tooltip = tooltip.withSummary(Components.literal(I18n.get(summaryKey)));
|
||||
|
||||
// Requirements
|
||||
// if (stack.getItem() instanceof BlockItem) {
|
||||
// BlockItem item = (BlockItem) stack.getItem();
|
||||
// if (item.getBlock() instanceof IRotate || item.getBlock() instanceof EngineBlock) {
|
||||
// tooltip = tooltip.withKineticStats(item.getBlock());
|
||||
// }
|
||||
// }
|
||||
|
||||
// Behaviours
|
||||
for (int i = 1; i < 100; i++) {
|
||||
String conditionKey = translationKey + ".condition" + i;
|
||||
String behaviourKey = translationKey + ".behaviour" + i;
|
||||
if (!I18n.exists(conditionKey))
|
||||
break;
|
||||
if (i == 1)
|
||||
tooltip.getLinesOnShift()
|
||||
.add(Components.immutableEmpty());
|
||||
tooltip.withBehaviour(I18n.get(conditionKey), I18n.get(behaviourKey));
|
||||
}
|
||||
|
||||
// Controls
|
||||
for (int i = 1; i < 100; i++) {
|
||||
String controlKey = translationKey + ".control" + i;
|
||||
String actionKey = translationKey + ".action" + i;
|
||||
if (!I18n.exists(controlKey))
|
||||
break;
|
||||
tooltip.withControl(I18n.get(controlKey), I18n.get(actionKey));
|
||||
}
|
||||
|
||||
return tooltip.createTabs();
|
||||
}
|
||||
|
||||
public static String getTooltipTranslationKey(ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
if (tooltipReferrals.containsKey(item))
|
||||
return tooltipReferrals.get(item)
|
||||
.get() + ".tooltip";
|
||||
return item.getDescriptionId(stack) + ".tooltip";
|
||||
}
|
||||
|
||||
// private static int getComponentLength(ITextComponent component) {
|
||||
// AtomicInteger l = new AtomicInteger();
|
||||
// TextProcessing.visitFormatted(component, Style.EMPTY, (s, style, charConsumer) -> {
|
||||
// l.getAndIncrement();
|
||||
// return true;
|
||||
// });
|
||||
// return l.get();
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item;
|
||||
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class UncontainableBlockItem extends BlockItem {
|
||||
public UncontainableBlockItem(Block block, Properties properties) {
|
||||
super(block, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFitInsideContainerItems() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item.render;
|
||||
|
||||
import nl.requios.effortlessbuilding.create.Create;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
|
||||
public abstract class CreateCustomRenderedItemModel extends CustomRenderedItemModel {
|
||||
|
||||
public CreateCustomRenderedItemModel(BakedModel template, String basePath) {
|
||||
super(template, Create.ID, basePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.BlockModelRotation;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
import net.minecraftforge.client.model.BakedModelWrapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class CustomRenderedItemModel extends BakedModelWrapper<BakedModel> {
|
||||
|
||||
protected String namespace;
|
||||
protected String basePath;
|
||||
protected Map<String, BakedModel> partials = new HashMap<>();
|
||||
|
||||
public CustomRenderedItemModel(BakedModel template, String namespace, String basePath) {
|
||||
super(template);
|
||||
this.namespace = namespace;
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel applyTransform(ItemTransforms.TransformType cameraTransformType, PoseStack mat, boolean leftHand) {
|
||||
// Super call returns originalModel, but we want to return this, else ISTER
|
||||
// won't be used.
|
||||
super.applyTransform(cameraTransformType, mat, leftHand);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final BakedModel getOriginalModel() {
|
||||
return originalModel;
|
||||
}
|
||||
|
||||
public BakedModel getPartial(String name) {
|
||||
return partials.get(name);
|
||||
}
|
||||
|
||||
public final List<ResourceLocation> getModelLocations() {
|
||||
return partials.keySet().stream().map(this::getPartialModelLocation).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected void addPartials(String... partials) {
|
||||
for (String name : partials)
|
||||
this.partials.put(name, null);
|
||||
}
|
||||
|
||||
public void loadPartials(ModelEvent.BakingCompleted event) {
|
||||
ModelBakery modelLoader = event.getModelBakery();
|
||||
for (String name : partials.keySet())
|
||||
partials.put(name, loadPartial(modelLoader, name));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected BakedModel loadPartial(ModelBakery modelLoader, String name) {
|
||||
return modelLoader.bake(getPartialModelLocation(name), BlockModelRotation.X0_Y0);
|
||||
}
|
||||
|
||||
protected ResourceLocation getPartialModelLocation(String name) {
|
||||
return new ResourceLocation(namespace, "item/" + basePath + "/" + name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.item.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import nl.requios.effortlessbuilding.create.foundation.render.RenderTypes;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class PartialItemModelRenderer {
|
||||
|
||||
private static final PartialItemModelRenderer INSTANCE = new PartialItemModelRenderer();
|
||||
|
||||
private final RandomSource random = RandomSource.create();
|
||||
|
||||
private ItemStack stack;
|
||||
private ItemTransforms.TransformType transformType;
|
||||
private PoseStack ms;
|
||||
private MultiBufferSource buffer;
|
||||
private int overlay;
|
||||
|
||||
public static PartialItemModelRenderer of(ItemStack stack, ItemTransforms.TransformType transformType,
|
||||
PoseStack ms, MultiBufferSource buffer, int overlay) {
|
||||
PartialItemModelRenderer instance = INSTANCE;
|
||||
instance.stack = stack;
|
||||
instance.transformType = transformType;
|
||||
instance.ms = ms;
|
||||
instance.buffer = buffer;
|
||||
instance.overlay = overlay;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void render(BakedModel model, int light) {
|
||||
render(model, RenderTypes.getItemPartialTranslucent(), light);
|
||||
}
|
||||
|
||||
public void renderSolid(BakedModel model, int light) {
|
||||
render(model, RenderTypes.getItemPartialSolid(), light);
|
||||
}
|
||||
|
||||
public void renderSolidGlowing(BakedModel model, int light) {
|
||||
render(model, RenderTypes.getGlowingSolid(), light);
|
||||
}
|
||||
|
||||
public void renderGlowing(BakedModel model, int light) {
|
||||
render(model, RenderTypes.getGlowingTranslucent(), light);
|
||||
}
|
||||
|
||||
public void render(BakedModel model, RenderType type, int light) {
|
||||
if (stack.isEmpty())
|
||||
return;
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(-0.5D, -0.5D, -0.5D);
|
||||
|
||||
if (!model.isCustomRenderer()) {
|
||||
VertexConsumer vc = ItemRenderer.getFoilBufferDirect(buffer, type, true, stack.hasFoil());
|
||||
for (BakedModel pass : model.getRenderPasses(stack, false)) {
|
||||
renderBakedItemModel(pass, light, ms, vc);
|
||||
}
|
||||
} else
|
||||
IClientItemExtensions.of(stack)
|
||||
.getCustomRenderer()
|
||||
.renderByItem(stack, transformType, ms, buffer, light, overlay);
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
private void renderBakedItemModel(BakedModel model, int light, PoseStack ms, VertexConsumer buffer) {
|
||||
ItemRenderer ir = Minecraft.getInstance()
|
||||
.getItemRenderer();
|
||||
ModelData data = ModelData.EMPTY;
|
||||
|
||||
for (RenderType renderType : model.getRenderTypes(stack, false)) {
|
||||
for (Direction direction : Iterate.directions) {
|
||||
random.setSeed(42L);
|
||||
ir.renderQuadList(ms, buffer, model.getQuads(null, direction, random, data, renderType), stack, light,
|
||||
overlay);
|
||||
}
|
||||
|
||||
random.setSeed(42L);
|
||||
ir.renderQuadList(ms, buffer, model.getQuads(null, null, random, data, renderType), stack, light, overlay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.networking;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface ISyncPersistentData {
|
||||
|
||||
void onPersistentDataUpdated();
|
||||
|
||||
public static class PersistentDataPacket extends SimplePacketBase {
|
||||
|
||||
private int entityId;
|
||||
private Entity entity;
|
||||
private CompoundTag readData;
|
||||
|
||||
public PersistentDataPacket(Entity entity) {
|
||||
this.entity = entity;
|
||||
this.entityId = entity.getId();
|
||||
}
|
||||
|
||||
public PersistentDataPacket(FriendlyByteBuf buffer) {
|
||||
entityId = buffer.readInt();
|
||||
readData = buffer.readNbt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(entityId);
|
||||
buffer.writeNbt(entity.getPersistentData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
Entity entityByID = Minecraft.getInstance().level.getEntity(entityId);
|
||||
CompoundTag data = entityByID.getPersistentData();
|
||||
new HashSet<>(data.getAllKeys()).forEach(data::remove);
|
||||
data.merge(readData);
|
||||
if (!(entityByID instanceof ISyncPersistentData))
|
||||
return;
|
||||
((ISyncPersistentData) entityByID).onPersistentDataUpdated();
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.networking;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class SimplePacketBase {
|
||||
|
||||
public abstract void write(FriendlyByteBuf buffer);
|
||||
|
||||
public abstract void handle(Supplier<Context> context);
|
||||
|
||||
}
|
||||
@@ -233,15 +233,12 @@ public class BlockHelper {
|
||||
if (state.hasProperty(BlockStateProperties.WATERLOGGED))
|
||||
state = state.setValue(BlockStateProperties.WATERLOGGED, Boolean.FALSE);
|
||||
|
||||
// if (AllBlocks.BELT.has(state)) {
|
||||
// world.setBlock(target, state, 2);
|
||||
// return;
|
||||
// } else if (state.getBlock() == Blocks.COMPOSTER)
|
||||
// state = Blocks.COMPOSTER.defaultBlockState();
|
||||
// else if (state.getBlock() != Blocks.SEA_PICKLE && state.getBlock() instanceof IPlantable)
|
||||
// state = ((IPlantable) state.getBlock()).getPlant(world, target);
|
||||
// else if (state.is(BlockTags.CAULDRONS))
|
||||
// state = Blocks.CAULDRON.defaultBlockState();
|
||||
if (state.getBlock() == Blocks.COMPOSTER)
|
||||
state = Blocks.COMPOSTER.defaultBlockState();
|
||||
else if (state.getBlock() != Blocks.SEA_PICKLE && state.getBlock() instanceof IPlantable)
|
||||
state = ((IPlantable) state.getBlock()).getPlant(world, target);
|
||||
else if (state.is(BlockTags.CAULDRONS))
|
||||
state = Blocks.CAULDRON.defaultBlockState();
|
||||
|
||||
if (world.dimensionType()
|
||||
.ultraWarm() && state.getFluidState().is(FluidTags.WATER)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package nl.requios.effortlessbuilding.create.foundation.utility.ghost;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.create.foundation.render.SuperRenderTypeBuffer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
@@ -20,10 +20,9 @@ import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import nl.requios.effortlessbuilding.ClientEvents;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.network.ModeActionMessage;
|
||||
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -33,7 +32,7 @@ import java.util.ArrayList;
|
||||
|
||||
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
|
||||
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeOptions.ActionEnum;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
|
||||
|
||||
@@ -99,7 +98,7 @@ public class RadialMenu extends Screen {
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, final int mouseX, final int mouseY, final float partialTicks) {
|
||||
BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(minecraft.player).getBuildMode();
|
||||
BuildModeEnum currentBuildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(0, 0, 200);
|
||||
@@ -450,16 +449,12 @@ public class RadialMenu extends Screen {
|
||||
private void performAction(boolean fromMouseClick) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
|
||||
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
|
||||
if (switchTo != null) {
|
||||
playRadialMenuSound();
|
||||
|
||||
modeSettings.setBuildMode(switchTo);
|
||||
ModeSettingsManager.setModeSettings(player, modeSettings);
|
||||
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
|
||||
EffortlessBuildingClient.BUILD_MODES.setBuildMode(switchTo);
|
||||
|
||||
EffortlessBuilding.log(player, I18n.get(modeSettings.getBuildMode().getNameKey()), true);
|
||||
EffortlessBuilding.log(player, I18n.get(switchTo.getNameKey()), true);
|
||||
|
||||
if (fromMouseClick) performedActionUsingMouse = true;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,8 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.systems.ServerBuildState;
|
||||
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
|
||||
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
|
||||
|
||||
@@ -134,9 +133,7 @@ public abstract class AbstractRandomizerBagItem extends Item {
|
||||
if (world.isClientSide) return InteractionResult.SUCCESS;
|
||||
|
||||
//Only place manually if in normal vanilla mode
|
||||
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
if (buildMode != BuildModes.BuildModeEnum.DISABLED || modifierSettings.doQuickReplace()) {
|
||||
if (ServerBuildState.isUsingBuildMode(player) || ServerBuildState.isQuickReplacing(player)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,9 @@ public class ReachUpgrade1Item extends Item {
|
||||
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
|
||||
}
|
||||
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
int currentLevel = modifierSettings.getReachUpgrade();
|
||||
int currentLevel = ReachHelper.getReachUpgrade(player);
|
||||
if (currentLevel == 0) {
|
||||
modifierSettings.setReachUpgrade(1);
|
||||
ReachHelper.setReachUpgrade(player, 1);
|
||||
|
||||
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
|
||||
player.setItemInHand(hand, ItemStack.EMPTY);
|
||||
|
||||
@@ -40,10 +40,10 @@ public class ReachUpgrade2Item extends Item {
|
||||
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
|
||||
}
|
||||
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
int currentLevel = modifierSettings.getReachUpgrade();
|
||||
int currentLevel = ReachHelper.getReachUpgrade(player);
|
||||
if (currentLevel == 1) {
|
||||
modifierSettings.setReachUpgrade(2);
|
||||
ReachHelper.setReachUpgrade(player, 2);
|
||||
|
||||
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
|
||||
player.setItemInHand(hand, ItemStack.EMPTY);
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ public class ReachUpgrade3Item extends Item {
|
||||
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
|
||||
}
|
||||
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
int currentLevel = modifierSettings.getReachUpgrade();
|
||||
int currentLevel = ReachHelper.getReachUpgrade(player);
|
||||
if (currentLevel == 2) {
|
||||
modifierSettings.setReachUpgrade(3);
|
||||
ReachHelper.setReachUpgrade(player, 3);
|
||||
|
||||
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
|
||||
player.setItemInHand(hand, ItemStack.EMPTY);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.function.Supplier;
|
||||
/***
|
||||
* Sends a message to the client asking to add a block to the undo stack.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AddUndoMessage {
|
||||
private final BlockPos coordinate;
|
||||
private final BlockState previousBlockState;
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.function.Supplier;
|
||||
/***
|
||||
* Sends a message to the client asking to clear the undo and redo stacks.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ClearUndoMessage {
|
||||
|
||||
public ClearUndoMessage() {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import nl.requios.effortlessbuilding.create.foundation.networking.SimplePacketBase;
|
||||
import nl.requios.effortlessbuilding.systems.ServerBuildState;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Shares mode settings (see ModeSettingsManager) between server and client
|
||||
*/
|
||||
public class IsQuickReplacingPacket {
|
||||
private boolean isQuickReplacing;
|
||||
|
||||
public IsQuickReplacingPacket() {
|
||||
}
|
||||
|
||||
public IsQuickReplacingPacket(boolean isQuickReplacing) {
|
||||
this.isQuickReplacing = isQuickReplacing;
|
||||
}
|
||||
|
||||
public static void encode(IsQuickReplacingPacket message, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(message.isQuickReplacing);
|
||||
}
|
||||
|
||||
public static IsQuickReplacingPacket decode(FriendlyByteBuf buf) {
|
||||
return new IsQuickReplacingPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(IsQuickReplacingPacket message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerBuildState.setIsQuickReplacing(ctx.get().getSender(), message.isQuickReplacing);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import nl.requios.effortlessbuilding.systems.ServerBuildState;
|
||||
|
||||
/**
|
||||
* Shares mode settings (see ModeSettingsManager) between server and client
|
||||
*/
|
||||
public class IsUsingBuildModePacket {
|
||||
private boolean isUsingBuildMode;
|
||||
|
||||
public IsUsingBuildModePacket() {
|
||||
}
|
||||
|
||||
public IsUsingBuildModePacket(boolean isUsingBuildMode) {
|
||||
this.isUsingBuildMode = isUsingBuildMode;
|
||||
}
|
||||
|
||||
public static void encode(IsUsingBuildModePacket message, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(message.isUsingBuildMode);
|
||||
}
|
||||
|
||||
public static IsUsingBuildModePacket decode(FriendlyByteBuf buf) {
|
||||
return new IsUsingBuildModePacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(IsUsingBuildModePacket message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerBuildState.setIsUsingBuildMode(ctx.get().getSender(), message.isUsingBuildMode);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Shares mode settings (see ModeSettingsManager) between server and client
|
||||
*/
|
||||
@Deprecated
|
||||
public class ModeActionMessage {
|
||||
|
||||
private ModeOptions.ActionEnum action;
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
|
||||
|
||||
/**
|
||||
* Shares mode settings (see ModeSettingsManager) between server and client
|
||||
*/
|
||||
public class ModeSettingsMessage {
|
||||
|
||||
private ModeSettings modeSettings;
|
||||
|
||||
public ModeSettingsMessage() {
|
||||
}
|
||||
|
||||
public ModeSettingsMessage(ModeSettings modeSettings) {
|
||||
this.modeSettings = modeSettings;
|
||||
}
|
||||
|
||||
public static void encode(ModeSettingsMessage message, FriendlyByteBuf buf) {
|
||||
buf.writeInt(message.modeSettings.getBuildMode().ordinal());
|
||||
}
|
||||
|
||||
public static ModeSettingsMessage decode(FriendlyByteBuf buf) {
|
||||
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
|
||||
|
||||
return new ModeSettingsMessage(new ModeSettings(buildMode));
|
||||
}
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
|
||||
|
||||
// Sanitize
|
||||
ModeSettingsManager.sanitize(message.modeSettings, player);
|
||||
|
||||
ModeSettingsManager.setModeSettings(player, message.modeSettings);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,10 +57,6 @@ public class ModifierSettingsMessage {
|
||||
buf.writeInt(a.count);
|
||||
}
|
||||
|
||||
buf.writeBoolean(message.modifierSettings.doQuickReplace());
|
||||
|
||||
buf.writeInt(message.modifierSettings.getReachUpgrade());
|
||||
|
||||
//RADIAL MIRROR
|
||||
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings();
|
||||
buf.writeBoolean(r != null);
|
||||
@@ -102,10 +98,6 @@ public class ModifierSettingsMessage {
|
||||
a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
|
||||
}
|
||||
|
||||
boolean quickReplace = buf.readBoolean();
|
||||
|
||||
int reachUpgrade = buf.readInt();
|
||||
|
||||
//RADIAL MIRROR
|
||||
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
|
||||
if (buf.readBoolean()) {
|
||||
@@ -120,7 +112,7 @@ public class ModifierSettingsMessage {
|
||||
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
|
||||
}
|
||||
|
||||
ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade);
|
||||
ModifierSettings modifierSettings = new ModifierSettings(m, a, r);
|
||||
return new ModifierSettingsMessage(modifierSettings);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/***
|
||||
* Sends a message to the client indicating that a block has been placed.
|
||||
* Necessary because Forge's onBlockPlaced event is only called on the server.
|
||||
*/
|
||||
public class OnBlockPlacedMessage {
|
||||
|
||||
public OnBlockPlacedMessage() {
|
||||
}
|
||||
|
||||
public static void encode(OnBlockPlacedMessage message, FriendlyByteBuf buf) {
|
||||
|
||||
}
|
||||
|
||||
public static OnBlockPlacedMessage decode(FriendlyByteBuf buf) {
|
||||
return new OnBlockPlacedMessage();
|
||||
}
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(OnBlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
|
||||
//Received clientside
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClientHandler.handle(message, ctx));
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class ClientHandler {
|
||||
public static void handle(OnBlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) {
|
||||
|
||||
EffortlessBuildingClient.BUILDER_CHAIN.onRightClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PacketHandler {
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||
@@ -17,14 +20,22 @@ public class PacketHandler {
|
||||
public static void register() {
|
||||
int id = 0;
|
||||
|
||||
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, OnBlockPlacedMessage.class, OnBlockPlacedMessage::encode, OnBlockPlacedMessage::decode, OnBlockPlacedMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ServerPlaceBlocksMessage.class, ServerPlaceBlocksMessage::encode, ServerPlaceBlocksMessage::decode, ServerPlaceBlocksMessage.Handler::handle);
|
||||
|
||||
INSTANCE.registerMessage(id++, IsUsingBuildModePacket.class, IsUsingBuildModePacket::encode, IsUsingBuildModePacket::decode,
|
||||
IsUsingBuildModePacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
|
||||
INSTANCE.registerMessage(id++, IsQuickReplacingPacket.class, IsQuickReplacingPacket::encode, IsQuickReplacingPacket::decode,
|
||||
IsQuickReplacingPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
|
||||
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode,
|
||||
ModifierSettingsMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode,
|
||||
ModeActionMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ServerPlaceBlocksPacket.class, ServerPlaceBlocksPacket::encode, ServerPlaceBlocksPacket::decode,
|
||||
ServerPlaceBlocksPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
|
||||
INSTANCE.registerMessage(id++, ServerBreakBlocksPacket.class, ServerBreakBlocksPacket::encode, ServerBreakBlocksPacket::decode,
|
||||
ServerBreakBlocksPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
|
||||
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode,
|
||||
AddUndoMessage.Handler::handle);
|
||||
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode,
|
||||
ClearUndoMessage.Handler::handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
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 java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Sends a message to the server to break multiple blocks
|
||||
*/
|
||||
public class ServerBreakBlocksPacket {
|
||||
|
||||
private List<BlockEntry> blocks;
|
||||
|
||||
public ServerBreakBlocksPacket() {}
|
||||
|
||||
public ServerBreakBlocksPacket(List<BlockEntry> blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public static void encode(ServerBreakBlocksPacket message, FriendlyByteBuf buf) {
|
||||
buf.writeCollection(message.blocks, BlockEntry::encode);
|
||||
}
|
||||
|
||||
public static ServerBreakBlocksPacket decode(FriendlyByteBuf buf) {
|
||||
ServerBreakBlocksPacket message = new ServerBreakBlocksPacket();
|
||||
message.blocks = buf.readList(BlockEntry::decode);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(ServerBreakBlocksPacket message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
|
||||
|
||||
EffortlessBuilding.SERVER_BLOCK_PLACER.breakBlocks(player, message.blocks);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package nl.requios.effortlessbuilding.network;
|
||||
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
@@ -13,29 +12,29 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Sends a message to the server to place multiple blocks
|
||||
*/
|
||||
public class ServerPlaceBlocksMessage {
|
||||
public class ServerPlaceBlocksPacket {
|
||||
|
||||
private List<BlockEntry> blocks;
|
||||
|
||||
public ServerPlaceBlocksMessage() {}
|
||||
public ServerPlaceBlocksPacket() {}
|
||||
|
||||
public ServerPlaceBlocksMessage(List<BlockEntry> blocks) {
|
||||
public ServerPlaceBlocksPacket(List<BlockEntry> blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public static void encode(ServerPlaceBlocksMessage message, FriendlyByteBuf buf) {
|
||||
public static void encode(ServerPlaceBlocksPacket message, FriendlyByteBuf buf) {
|
||||
buf.writeCollection(message.blocks, BlockEntry::encode);
|
||||
}
|
||||
|
||||
public static ServerPlaceBlocksMessage decode(FriendlyByteBuf buf) {
|
||||
ServerPlaceBlocksMessage message = new ServerPlaceBlocksMessage();
|
||||
public static ServerPlaceBlocksPacket decode(FriendlyByteBuf buf) {
|
||||
ServerPlaceBlocksPacket message = new ServerPlaceBlocksPacket();
|
||||
message.blocks = buf.readList(BlockEntry::decode);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(ServerPlaceBlocksMessage message, Supplier<NetworkEvent.Context> ctx) {
|
||||
public static void handle(ServerPlaceBlocksPacket message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
|
||||
|
||||
@@ -11,35 +11,35 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Send packet to client to translate and log the containing message
|
||||
*/
|
||||
public class TranslatedLogMessage {
|
||||
public class TranslatedLogPacket {
|
||||
private final String prefix;
|
||||
private final String translationKey;
|
||||
private final String suffix;
|
||||
private final boolean actionBar;
|
||||
|
||||
public TranslatedLogMessage() {
|
||||
public TranslatedLogPacket() {
|
||||
prefix = "";
|
||||
translationKey = "";
|
||||
suffix = "";
|
||||
actionBar = false;
|
||||
}
|
||||
|
||||
public TranslatedLogMessage(String prefix, String translationKey, String suffix, boolean actionBar) {
|
||||
public TranslatedLogPacket(String prefix, String translationKey, String suffix, boolean actionBar) {
|
||||
this.prefix = prefix;
|
||||
this.translationKey = translationKey;
|
||||
this.suffix = suffix;
|
||||
this.actionBar = actionBar;
|
||||
}
|
||||
|
||||
public static void encode(TranslatedLogMessage message, FriendlyByteBuf buf) {
|
||||
public static void encode(TranslatedLogPacket message, FriendlyByteBuf buf) {
|
||||
buf.writeUtf(message.prefix);
|
||||
buf.writeUtf(message.translationKey);
|
||||
buf.writeUtf(message.suffix);
|
||||
buf.writeBoolean(message.actionBar);
|
||||
}
|
||||
|
||||
public static TranslatedLogMessage decode(FriendlyByteBuf buf) {
|
||||
return new TranslatedLogMessage(buf.readUtf(), buf.readUtf(), buf.readUtf(), buf.readBoolean());
|
||||
public static TranslatedLogPacket decode(FriendlyByteBuf buf) {
|
||||
return new TranslatedLogPacket(buf.readUtf(), buf.readUtf(), buf.readUtf(), buf.readBoolean());
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
@@ -59,7 +59,7 @@ public class TranslatedLogMessage {
|
||||
}
|
||||
|
||||
public static class Handler {
|
||||
public static void handle(TranslatedLogMessage message, Supplier<NetworkEvent.Context> ctx) {
|
||||
public static void handle(TranslatedLogPacket message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
|
||||
//Received clientside
|
||||
@@ -5,7 +5,7 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
import nl.requios.effortlessbuilding.network.TranslatedLogMessage;
|
||||
import nl.requios.effortlessbuilding.network.TranslatedLogPacket;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -17,6 +17,6 @@ public class ServerProxy implements IProxy {
|
||||
}
|
||||
|
||||
public void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new TranslatedLogMessage(prefix, translationKey, suffix, actionBar));
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new TranslatedLogPacket(prefix, translationKey, suffix, actionBar));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package nl.requios.effortlessbuilding.render;
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -15,208 +14,136 @@ import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import nl.requios.effortlessbuilding.ClientConfig;
|
||||
import nl.requios.effortlessbuilding.ClientEvents;
|
||||
import nl.requios.effortlessbuilding.CommonConfig;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.*;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
|
||||
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
|
||||
import nl.requios.effortlessbuilding.create.AllSpecialTextures;
|
||||
import nl.requios.effortlessbuilding.create.CreateClient;
|
||||
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
|
||||
import nl.requios.effortlessbuilding.systems.BuilderChain;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
|
||||
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class BlockPreviews {
|
||||
private static final List<PlacedData> placedDataList = new ArrayList<>();
|
||||
private static List<BlockPos> previousCoordinates;
|
||||
private static List<BlockState> previousBlockStates;
|
||||
private static List<ItemStack> previousItemStacks;
|
||||
private static BlockPos previousFirstPos;
|
||||
private static BlockPos previousSecondPos;
|
||||
private static int soundTime = 0;
|
||||
private final List<PlacedBlocksEntry> placedBlocksList = new ArrayList<>();
|
||||
|
||||
public static void drawPlacedBlocks(Player player, ModifierSettings modifierSettings) {
|
||||
public void onTick() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
|
||||
drawPlacedBlocks(player);
|
||||
drawLookAtPreview(player);
|
||||
drawOutlinesIfNoBlockInHand(player);
|
||||
}
|
||||
|
||||
public void drawPlacedBlocks(Player player) {
|
||||
//Render placed blocks with appear animation
|
||||
if (ClientConfig.visuals.showBlockPreviews.get()) {
|
||||
for (PlacedData placed : placedDataList) {
|
||||
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
|
||||
for (PlacedBlocksEntry placed : placedBlocksList) {
|
||||
|
||||
int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get();
|
||||
if (totalTime <= 0) continue;
|
||||
int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get();
|
||||
if (totalTime <= 0) continue;
|
||||
|
||||
float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime;
|
||||
renderBlockPreviews(player, modifierSettings, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
|
||||
}
|
||||
float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime;
|
||||
renderBlockPreviews(placed.blocks, placed.breaking, dissolve);
|
||||
}
|
||||
}
|
||||
|
||||
//Expire
|
||||
placedDataList.removeIf(placed -> {
|
||||
placedBlocksList.removeIf(placed -> {
|
||||
int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get();
|
||||
return placed.time + totalTime < ClientEvents.ticksInGame;
|
||||
});
|
||||
}
|
||||
|
||||
public static void drawLookAtPreview(Player player, ModeSettings modeSettings, ModifierSettings modifierSettings, BlockPos startPos, Direction sideHit, Vec3 hitVec) {
|
||||
// if (!doShowBlockPreviews(modifierSettings, modeSettings, startPos)) return;
|
||||
//
|
||||
// //Keep blockstate the same for every block in the buildmode
|
||||
// //So dont rotate blocks when in the middle of placing wall etc.
|
||||
// if (BuildModes.isActive(player)) {
|
||||
// IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
|
||||
// if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
|
||||
// if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
|
||||
// }
|
||||
//
|
||||
// if (sideHit == null) return;
|
||||
//
|
||||
// //Should be red?
|
||||
// boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
|
||||
//
|
||||
// //get coordinates
|
||||
// List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
|
||||
//
|
||||
// //Remember first and last point for the shader
|
||||
// BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO;
|
||||
// if (!startCoordinates.isEmpty()) {
|
||||
// firstPos = startCoordinates.get(0);
|
||||
// secondPos = startCoordinates.get(startCoordinates.size() - 1);
|
||||
// }
|
||||
//
|
||||
// //Limit number of blocks you can place
|
||||
// int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
|
||||
// if (startCoordinates.size() > limit) {
|
||||
// startCoordinates = startCoordinates.subList(0, limit);
|
||||
// }
|
||||
//
|
||||
// List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
|
||||
//
|
||||
// sortOnDistanceToPlayer(newCoordinates, player);
|
||||
//
|
||||
// hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
|
||||
// Math.abs(hitVec.z - ((int) hitVec.z)));
|
||||
//
|
||||
// //Get blockstates
|
||||
// List<ItemStack> itemStacks = new ArrayList<>();
|
||||
// List<BlockState> blockStates = new ArrayList<>();
|
||||
// if (breaking) {
|
||||
// //Find blockstate of world
|
||||
// for (BlockPos coordinate : newCoordinates) {
|
||||
// blockStates.add(player.level.getBlockState(coordinate));
|
||||
// }
|
||||
// } else {
|
||||
// blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //Check if they are different from previous
|
||||
// //TODO fix triggering when moving player
|
||||
// if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
|
||||
// previousCoordinates = newCoordinates;
|
||||
// //remember the rest for placed blocks
|
||||
// previousBlockStates = blockStates;
|
||||
// previousItemStacks = itemStacks;
|
||||
// previousFirstPos = firstPos;
|
||||
// previousSecondPos = secondPos;
|
||||
//
|
||||
// //if so, renew randomness of randomizer bag
|
||||
// AbstractRandomizerBagItem.renewRandomness();
|
||||
// //and play sound (max once every tick)
|
||||
// if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientEvents.ticksInGame - 0) {
|
||||
// soundTime = ClientEvents.ticksInGame;
|
||||
//
|
||||
// if (blockStates.get(0) != null) {
|
||||
// SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.level,
|
||||
// newCoordinates.get(0), player);
|
||||
// player.level.playSound(player, player.blockPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(),
|
||||
// SoundSource.BLOCKS, 0.3f, 0.8f);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (blockStates.size() == 0 || newCoordinates.size() != blockStates.size()) return;
|
||||
//
|
||||
// int blockCount;
|
||||
//
|
||||
// Object outlineID = firstPos;
|
||||
// //Dont fade out the outline if we are still determining where to place
|
||||
// //Every outline with same ID will not fade out (because it gets replaced)
|
||||
// if (newCoordinates.size() == 1 || BuildModifiers.isEnabled(modifierSettings, firstPos)) outlineID = "single";
|
||||
//
|
||||
// if (!breaking) {
|
||||
// //Use fancy shader if config allows, otherwise outlines
|
||||
// if (ClientConfig.visuals.showBlockPreviews.get() && newCoordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) {
|
||||
// blockCount = renderBlockPreviews(player, modifierSettings, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
|
||||
//
|
||||
// CreateClient.OUTLINER.showCluster(outlineID, newCoordinates)
|
||||
// .withFaceTexture(AllSpecialTextures.CHECKERED)
|
||||
// .disableNormals()
|
||||
// .lineWidth(1 / 32f)
|
||||
// .colored(new Color(1f, 1f, 1f, 1f));
|
||||
// } else {
|
||||
// //Thicker outline without block previews
|
||||
// CreateClient.OUTLINER.showCluster(outlineID, newCoordinates)
|
||||
// .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED)
|
||||
// .disableNormals()
|
||||
// .lineWidth(1 / 16f)
|
||||
// .colored(new Color(1f, 1f, 1f, 1f));
|
||||
//
|
||||
// blockCount = newCoordinates.size();
|
||||
// }
|
||||
//
|
||||
// } else {
|
||||
// //Breaking
|
||||
// CreateClient.OUTLINER.showCluster(outlineID, newCoordinates)
|
||||
// .withFaceTexture(AllSpecialTextures.THIN_CHECKERED)
|
||||
// .disableNormals()
|
||||
// .lineWidth(1 / 16f)
|
||||
// .colored(new Color(0.8f, 0.1f, 0.1f, 1f));
|
||||
// blockCount = newCoordinates.size();
|
||||
// }
|
||||
//
|
||||
// //Display block count and dimensions in actionbar
|
||||
// if (BuildModes.isActive(player)) {
|
||||
//
|
||||
// //Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
|
||||
// int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
|
||||
// int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
|
||||
// int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
|
||||
// for (BlockPos pos : startCoordinates) {
|
||||
// if (pos.getX() < minX) minX = pos.getX();
|
||||
// if (pos.getX() > maxX) maxX = pos.getX();
|
||||
// if (pos.getY() < minY) minY = pos.getY();
|
||||
// if (pos.getY() > maxY) maxY = pos.getY();
|
||||
// if (pos.getZ() < minZ) minZ = pos.getZ();
|
||||
// if (pos.getZ() > maxZ) maxZ = pos.getZ();
|
||||
// }
|
||||
// BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
|
||||
//
|
||||
// String dimensions = "(";
|
||||
// if (dim.getX() > 1) dimensions += dim.getX() + "x";
|
||||
// if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
|
||||
// if (dim.getY() > 1) dimensions += dim.getY() + "x";
|
||||
// dimensions = dimensions.substring(0, dimensions.length() - 1);
|
||||
// if (dimensions.length() > 1) dimensions += ")";
|
||||
//
|
||||
// EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
|
||||
// }
|
||||
public void drawLookAtPreview(Player player) {
|
||||
if (EffortlessBuildingClient.BUILD_MODES.getBuildMode() == BuildModeEnum.DISABLED &&
|
||||
!ClientConfig.visuals.alwaysShowBlockPreview.get()) return;
|
||||
|
||||
var blocks = EffortlessBuildingClient.BUILDER_CHAIN.getBlocks();
|
||||
var state = EffortlessBuildingClient.BUILDER_CHAIN.getState();
|
||||
|
||||
if (blocks.size() == 0) return;
|
||||
|
||||
var coordinates = blocks.stream().map(block -> block.blockPos).toList();
|
||||
|
||||
//Dont fade out the outline if we are still determining where to place
|
||||
//Every outline with same ID will not fade out (because it gets replaced)
|
||||
Object outlineID = "single";
|
||||
if (blocks.size() > 1) outlineID = blocks.get(0).blockPos;
|
||||
|
||||
if (state != BuilderChain.State.BREAKING) {
|
||||
//Use fancy shader if config allows, otherwise outlines
|
||||
if (ClientConfig.visuals.showBlockPreviews.get() && blocks.size() < ClientConfig.visuals.maxBlockPreviews.get()) {
|
||||
renderBlockPreviews(blocks, false, 0f);
|
||||
|
||||
CreateClient.OUTLINER.showCluster(outlineID, coordinates)
|
||||
.withFaceTexture(AllSpecialTextures.CHECKERED)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 32f)
|
||||
.colored(new Color(1f, 1f, 1f, 1f));
|
||||
} else {
|
||||
//Thicker outline without block previews
|
||||
CreateClient.OUTLINER.showCluster(outlineID, coordinates)
|
||||
.withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 16f)
|
||||
.colored(new Color(1f, 1f, 1f, 1f));
|
||||
}
|
||||
|
||||
} else {
|
||||
//Breaking
|
||||
CreateClient.OUTLINER.showCluster(outlineID, coordinates)
|
||||
.withFaceTexture(AllSpecialTextures.THIN_CHECKERED)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 16f)
|
||||
.colored(new Color(0.8f, 0.1f, 0.1f, 1f));
|
||||
}
|
||||
|
||||
//Display block count and dimensions in actionbar
|
||||
if (state != BuilderChain.State.IDLE) {
|
||||
|
||||
//Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
|
||||
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
|
||||
int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
|
||||
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
|
||||
for (BlockPos pos : coordinates) {
|
||||
if (pos.getX() < minX) minX = pos.getX();
|
||||
if (pos.getX() > maxX) maxX = pos.getX();
|
||||
if (pos.getY() < minY) minY = pos.getY();
|
||||
if (pos.getY() > maxY) maxY = pos.getY();
|
||||
if (pos.getZ() < minZ) minZ = pos.getZ();
|
||||
if (pos.getZ() > maxZ) maxZ = pos.getZ();
|
||||
}
|
||||
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
|
||||
|
||||
String dimensions = "(";
|
||||
if (dim.getX() > 1) dimensions += dim.getX() + "x";
|
||||
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
|
||||
if (dim.getY() > 1) dimensions += dim.getY() + "x";
|
||||
dimensions = dimensions.substring(0, dimensions.length() - 1);
|
||||
if (dimensions.length() > 1) dimensions += ")";
|
||||
|
||||
EffortlessBuilding.log(player, blocks.size() + " blocks " + dimensions, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawOutlinesIfNoBlockInHand(Player player, HitResult lookingAt) {
|
||||
public void drawOutlinesIfNoBlockInHand(Player player) {
|
||||
ItemStack mainhand = player.getMainHandItem();
|
||||
HitResult lookingAt = ClientEvents.getLookingAt(player);
|
||||
if (EffortlessBuildingClient.BUILD_MODES.getBuildMode() == BuildModeEnum.DISABLED)
|
||||
lookingAt = Minecraft.getInstance().hitResult;
|
||||
|
||||
boolean noBlockInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
|
||||
if (!noBlockInHand) return;
|
||||
|
||||
//Draw outlines if no block in hand
|
||||
//Find proper raytrace: either normal range or increased range depending on canBreakFar
|
||||
HitResult objectMouseOver = Minecraft.getInstance().hitResult;
|
||||
@@ -245,58 +172,35 @@ public class BlockPreviews {
|
||||
}
|
||||
}
|
||||
|
||||
//Whether to draw any block previews or outlines
|
||||
public static boolean doShowBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
|
||||
if (!ClientConfig.visuals.showBlockPreviews.get()) return false;
|
||||
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.DISABLED ||
|
||||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
|
||||
ClientConfig.visuals.alwaysShowBlockPreview.get();
|
||||
}
|
||||
protected void renderBlockPreviews(List<BlockEntry> blocks, boolean breaking, float dissolve) {
|
||||
|
||||
protected static int renderBlockPreviews(Player player, ModifierSettings modifierSettings, List<BlockPos> coordinates,
|
||||
List<BlockState> blockStates, List<ItemStack> itemStacks, float dissolve,
|
||||
BlockPos firstPos, BlockPos secondPos, boolean checkCanPlace, boolean red) {
|
||||
int blocksValid = 0;
|
||||
var firstPos = blocks.get(0).blockPos;
|
||||
var lastPos = blocks.get(blocks.size() - 1).blockPos;
|
||||
|
||||
if (coordinates.isEmpty()) return blocksValid;
|
||||
|
||||
for (int i = coordinates.size() - 1; i >= 0; i--) {
|
||||
BlockPos blockPos = coordinates.get(i);
|
||||
BlockState blockState = blockStates.get(i);
|
||||
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
|
||||
if (CompatHelper.isItemBlockProxy(itemstack))
|
||||
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
|
||||
|
||||
//Check if we can place
|
||||
boolean canPlace = true;
|
||||
if (checkCanPlace) {
|
||||
canPlace = SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace());
|
||||
} else {
|
||||
//If check is turned off, check if blockstate is the same (for dissolve effect)
|
||||
canPlace = player.level.getBlockState(blockPos) != blockState;
|
||||
}
|
||||
|
||||
if (canPlace) {
|
||||
renderBlockPreview(blockPos, blockState, dissolve, firstPos, secondPos, red);
|
||||
blocksValid++;
|
||||
}
|
||||
for (BlockEntry blockEntry : blocks) {
|
||||
renderBlockPreview(blockEntry, breaking, dissolve, firstPos, lastPos);
|
||||
}
|
||||
return blocksValid;
|
||||
}
|
||||
|
||||
protected static void renderBlockPreview(BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
|
||||
if (blockState == null) return;
|
||||
protected void renderBlockPreview(BlockEntry blockEntry, boolean breaking, float dissolve, BlockPos firstPos, BlockPos lastPos) {
|
||||
if (blockEntry.blockState == null) return;
|
||||
|
||||
var blockPos = blockEntry.blockPos;
|
||||
var blockState = blockEntry.blockState;
|
||||
if (breaking) {
|
||||
blockState = Minecraft.getInstance().level.getBlockState(blockPos);
|
||||
}
|
||||
|
||||
float scale = 0.5f;
|
||||
float alpha = 0.7f;
|
||||
if (dissolve > 0f) {
|
||||
float animationLength = 0.8f;
|
||||
|
||||
double firstToSecond = secondPos.distSqr(firstPos);
|
||||
double firstToSecond = lastPos.distSqr(firstPos);
|
||||
double place = 0;
|
||||
if (firstToSecond > 0.5) {
|
||||
double placeFromFirst = firstPos.distSqr(blockPos) / firstToSecond;
|
||||
double placeFromSecond = secondPos.distSqr(blockPos) / firstToSecond;
|
||||
double placeFromSecond = lastPos.distSqr(blockPos) / firstToSecond;
|
||||
place = (placeFromFirst + (1.0 - placeFromSecond)) / 2.0;
|
||||
} //else only one block
|
||||
|
||||
@@ -328,7 +232,7 @@ public class BlockPreviews {
|
||||
}
|
||||
|
||||
//A bezier easing function where implicit first and last control points are (0,0) and (1,1).
|
||||
public static double bezier(double t, double x1, double y1, double x2, double y2) {
|
||||
public double bezier(double t, double x1, double y1, double x2, double y2) {
|
||||
double t2 = t * t;
|
||||
double t3 = t2 * t;
|
||||
|
||||
@@ -344,61 +248,25 @@ public class BlockPreviews {
|
||||
return (ay * t3) + (by * t2) + (cy * t) + 0;
|
||||
}
|
||||
|
||||
public static void onBlocksPlaced() {
|
||||
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
|
||||
public void onBlocksPlaced(List<BlockEntry> blocks) {
|
||||
if (!ClientConfig.visuals.showBlockPreviews.get()) return;
|
||||
if (blocks.size() <= 1 || blocks.size() > ClientConfig.visuals.maxBlockPreviews.get()) return;
|
||||
|
||||
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, false, blocks));
|
||||
|
||||
CreateClient.OUTLINER.keep(blocks.get(0).blockPos, CommonConfig.visuals.appearAnimationLength.get());
|
||||
}
|
||||
|
||||
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
|
||||
BlockPos firstPos, BlockPos secondPos) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
public void onBlocksBroken(List<BlockEntry> blocks) {
|
||||
if (!ClientConfig.visuals.showBlockPreviews.get()) return;
|
||||
if (blocks.size() <= 1 || blocks.size() > ClientConfig.visuals.maxBlockPreviews.get()) return;
|
||||
|
||||
//Check if block previews are enabled
|
||||
if (doShowBlockPreviews(modifierSettings, modeSettings, firstPos)) {
|
||||
|
||||
//Save current coordinates, blockstates and itemstacks
|
||||
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
|
||||
coordinates.size() > 1 && coordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) {
|
||||
|
||||
placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates,
|
||||
itemStacks, firstPos, secondPos, false));
|
||||
}
|
||||
|
||||
CreateClient.OUTLINER.keep(firstPos, CommonConfig.visuals.appearAnimationLength.get());
|
||||
}
|
||||
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, true, blocks));
|
||||
|
||||
CreateClient.OUTLINER.keep(blocks.get(0).blockPos, CommonConfig.visuals.breakAnimationLength.get());
|
||||
}
|
||||
|
||||
public static void onBlocksBroken() {
|
||||
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
|
||||
}
|
||||
|
||||
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
|
||||
BlockPos firstPos, BlockPos secondPos) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
|
||||
//Check if block previews are enabled
|
||||
if (doShowBlockPreviews(modifierSettings, modeSettings, firstPos)) {
|
||||
|
||||
//Save current coordinates, blockstates and itemstacks
|
||||
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
|
||||
coordinates.size() > 1 && coordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) {
|
||||
|
||||
sortOnDistanceToPlayer(coordinates, player);
|
||||
|
||||
placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates,
|
||||
itemStacks, firstPos, secondPos, true));
|
||||
}
|
||||
|
||||
CreateClient.OUTLINER.keep(firstPos, CommonConfig.visuals.breakAnimationLength.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
|
||||
private void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
|
||||
|
||||
Collections.sort(coordinates, (lhs, rhs) -> {
|
||||
// -1 - less than, 1 - greater than, 0 - equal
|
||||
@@ -409,24 +277,15 @@ public class BlockPreviews {
|
||||
|
||||
}
|
||||
|
||||
static class PlacedData {
|
||||
public static class PlacedBlocksEntry {
|
||||
float time;
|
||||
List<BlockPos> coordinates;
|
||||
List<BlockState> blockStates;
|
||||
List<ItemStack> itemStacks;
|
||||
BlockPos firstPos;
|
||||
BlockPos secondPos;
|
||||
boolean breaking;
|
||||
List<BlockEntry> blocks;
|
||||
|
||||
public PlacedData(float time, List<BlockPos> coordinates, List<BlockState> blockStates,
|
||||
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
|
||||
public PlacedBlocksEntry(float time, boolean breaking, List<BlockEntry> blocks) {
|
||||
this.time = time;
|
||||
this.coordinates = coordinates;
|
||||
this.blockStates = blockStates;
|
||||
this.itemStacks = itemStacks;
|
||||
this.firstPos = firstPos;
|
||||
this.secondPos = secondPos;
|
||||
this.breaking = breaking;
|
||||
this.blocks = blocks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import nl.requios.effortlessbuilding.ClientEvents;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModes;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
|
||||
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
|
||||
@@ -31,56 +31,6 @@ import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
|
||||
@EventBusSubscriber(Dist.CLIENT)
|
||||
public class RenderHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTick(TickEvent.ClientTickEvent event) {
|
||||
if (!nl.requios.effortlessbuilding.create.events.ClientEvents.isGameActive()) return;
|
||||
|
||||
var player = Minecraft.getInstance().player;
|
||||
var modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
var modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
|
||||
BlockPreviews.drawPlacedBlocks(player, modifierSettings);
|
||||
|
||||
|
||||
HitResult lookingAt = ClientEvents.getLookingAt(player);
|
||||
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.DISABLED)
|
||||
lookingAt = Minecraft.getInstance().hitResult;
|
||||
|
||||
ItemStack mainhand = player.getMainHandItem();
|
||||
boolean noBlockInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
|
||||
|
||||
//Find start position, side hit and hit vector
|
||||
BlockPos startPos = null;
|
||||
Direction sideHit = null;
|
||||
Vec3 hitVec = null;
|
||||
|
||||
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
|
||||
if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
|
||||
startPos = blockLookingAt.getBlockPos();
|
||||
|
||||
//Check if tool (or none) in hand
|
||||
boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
|
||||
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos);
|
||||
if (!modifierSettings.doQuickReplace() && !noBlockInHand && !replaceable && !becomesDoubleSlab) {
|
||||
startPos = startPos.relative(blockLookingAt.getDirection());
|
||||
}
|
||||
|
||||
//Get under tall grass and other replaceable blocks
|
||||
if (modifierSettings.doQuickReplace() && !noBlockInHand && replaceable) {
|
||||
startPos = startPos.below();
|
||||
}
|
||||
|
||||
sideHit = blockLookingAt.getDirection();
|
||||
hitVec = blockLookingAt.getLocation();
|
||||
}
|
||||
|
||||
|
||||
BlockPreviews.drawLookAtPreview(player, modeSettings, modifierSettings, startPos, sideHit, hitVec);
|
||||
|
||||
if (noBlockInHand) BlockPreviews.drawOutlinesIfNoBlockInHand(player, lookingAt);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRender(RenderLevelStageEvent event) {
|
||||
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS) return;
|
||||
@@ -92,7 +42,6 @@ public class RenderHandler {
|
||||
MultiBufferSource.BufferSource buffer = MultiBufferSource.immediate(bufferBuilder);
|
||||
|
||||
Player player = Minecraft.getInstance().player;
|
||||
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
|
||||
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
|
||||
ms.pushPose();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package nl.requios.effortlessbuilding.systems;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@@ -19,11 +21,14 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import nl.requios.effortlessbuilding.ClientEvents;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
|
||||
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
import nl.requios.effortlessbuilding.network.ServerPlaceBlocksMessage;
|
||||
import nl.requios.effortlessbuilding.network.ServerBreakBlocksPacket;
|
||||
import nl.requios.effortlessbuilding.network.ServerPlaceBlocksPacket;
|
||||
import nl.requios.effortlessbuilding.render.BlockPreviews;
|
||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||
import nl.requios.effortlessbuilding.utilities.ReachHelper;
|
||||
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
|
||||
@@ -38,6 +43,7 @@ import java.util.List;
|
||||
public class BuilderChain {
|
||||
|
||||
private final List<BlockEntry> blocks = new ArrayList<>();
|
||||
private int soundTime = 0;
|
||||
|
||||
public enum State {
|
||||
IDLE,
|
||||
@@ -47,7 +53,6 @@ public class BuilderChain {
|
||||
|
||||
private State state = State.IDLE;
|
||||
|
||||
|
||||
public void onRightClick() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
|
||||
@@ -68,12 +73,16 @@ public class BuilderChain {
|
||||
state = State.PLACING;
|
||||
}
|
||||
|
||||
var buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
var buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
//Find out if we should place blocks now
|
||||
if (buildMode.instance.onClick(blocks)) {
|
||||
state = State.IDLE;
|
||||
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksMessage(blocks));
|
||||
|
||||
if (!blocks.isEmpty()) {
|
||||
EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksPlaced(blocks);
|
||||
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +103,16 @@ public class BuilderChain {
|
||||
onTick();
|
||||
}
|
||||
|
||||
var buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
var buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
//Find out if we should break blocks now
|
||||
if (buildMode.instance.onClick(blocks)) {
|
||||
state = State.IDLE;
|
||||
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksMessage(blocks));
|
||||
|
||||
if (!blocks.isEmpty()) {
|
||||
EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksBroken(blocks);
|
||||
PacketHandler.INSTANCE.sendToServer(new ServerBreakBlocksPacket(blocks));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,11 +132,11 @@ public class BuilderChain {
|
||||
// }
|
||||
|
||||
var modifierSettings = ModifierSettingsManager.getModifierSettings(player);
|
||||
var buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
|
||||
var buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
|
||||
|
||||
|
||||
BlockHitResult lookingAt = ClientEvents.getLookingAt(player);
|
||||
BlockEntry startEntry = findStartPosition(player, lookingAt, modifierSettings.doQuickReplace());
|
||||
BlockEntry startEntry = findStartPosition(player, lookingAt);
|
||||
if (startEntry != null) {
|
||||
blocks.add(startEntry);
|
||||
}
|
||||
@@ -131,34 +144,36 @@ public class BuilderChain {
|
||||
EffortlessBuildingClient.BUILD_MODES.findCoordinates(blocks, player, buildMode);
|
||||
EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player, modifierSettings);
|
||||
|
||||
if (blockInHand && state != State.BREAKING) {
|
||||
//find block states
|
||||
if (blockInHand && state != State.BREAKING)
|
||||
findBlockStates(player, itemStack);
|
||||
|
||||
if (itemStack.getItem() instanceof BlockItem) {
|
||||
|
||||
for (BlockEntry blockEntry : blocks) {
|
||||
blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemStack, blockEntry);
|
||||
}
|
||||
|
||||
} else if (CompatHelper.isItemBlockProxy(itemStack, false)) {
|
||||
|
||||
for (BlockEntry blockEntry : blocks) {
|
||||
ItemStack itemBlockStack = CompatHelper.getItemBlockFromStack(itemStack);
|
||||
if (itemBlockStack == null || itemBlockStack.isEmpty()) continue;
|
||||
blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemBlockStack, blockEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Check if they are different
|
||||
// if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
|
||||
//
|
||||
// //Renew randomness of randomizer bag
|
||||
// AbstractRandomizerBagItem.renewRandomness();
|
||||
//
|
||||
// //Play sound (max once every tick)
|
||||
// if (blocks.size() > 1 && blockStates.size() > 1 && soundTime < ClientEvents.ticksInGame) {
|
||||
// soundTime = ClientEvents.ticksInGame;
|
||||
//
|
||||
// var firstBlockState = blocks.get(0).blockState;
|
||||
// if (firstBlockState != null) {
|
||||
// SoundType soundType = firstBlockState.getBlock().getSoundType(firstBlockState, player.level,
|
||||
// blocks.get(0).blockPos, player);
|
||||
// SoundEvent soundEvent = state == BuilderChain.State.BREAKING ? soundType.getBreakSound() : soundType.getPlaceSound();
|
||||
// player.level.playSound(player, player.blockPosition(), soundEvent, SoundSource.BLOCKS, 0.3f, 0.8f);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
|
||||
state = State.IDLE;
|
||||
EffortlessBuildingClient.BUILD_MODES.onCancel(player);
|
||||
EffortlessBuildingClient.BUILD_MODES.onCancel();
|
||||
}
|
||||
|
||||
private BlockEntry findStartPosition(Player player, BlockHitResult lookingAt, boolean doingQuickReplace) {
|
||||
private BlockEntry findStartPosition(Player player, BlockHitResult lookingAt) {
|
||||
if (lookingAt == null || lookingAt.getType() == HitResult.Type.MISS) return null;
|
||||
|
||||
var startPos = lookingAt.getBlockPos();
|
||||
@@ -169,14 +184,15 @@ public class BuilderChain {
|
||||
|
||||
if (state != State.BREAKING) {
|
||||
//Offset in direction of sidehit if not quickreplace and not replaceable
|
||||
boolean isQuickReplacing = EffortlessBuildingClient.QUICK_REPLACE.isQuickReplacing();
|
||||
boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
|
||||
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos);
|
||||
if (!doingQuickReplace && !replaceable && !becomesDoubleSlab) {
|
||||
if (!isQuickReplacing && !replaceable && !becomesDoubleSlab) {
|
||||
startPos = startPos.relative(lookingAt.getDirection());
|
||||
}
|
||||
|
||||
//Get under tall grass and other replaceable blocks
|
||||
if (doingQuickReplace && replaceable) {
|
||||
if (isQuickReplacing && replaceable) {
|
||||
startPos = startPos.below();
|
||||
}
|
||||
}
|
||||
@@ -194,6 +210,23 @@ public class BuilderChain {
|
||||
return blockEntry;
|
||||
}
|
||||
|
||||
private void findBlockStates(LocalPlayer player, ItemStack itemStack) {
|
||||
if (itemStack.getItem() instanceof BlockItem) {
|
||||
|
||||
for (BlockEntry blockEntry : blocks) {
|
||||
blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemStack, blockEntry);
|
||||
}
|
||||
|
||||
} else if (CompatHelper.isItemBlockProxy(itemStack, false)) {
|
||||
|
||||
for (BlockEntry blockEntry : blocks) {
|
||||
ItemStack itemBlockStack = CompatHelper.getItemBlockFromStack(itemStack);
|
||||
if (itemBlockStack == null || itemBlockStack.isEmpty()) continue;
|
||||
blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemBlockStack, blockEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockState getBlockState(Player player, InteractionHand hand, ItemStack blockItemStack, BlockEntry blockEntry) {
|
||||
Block block = Block.byItem(blockItemStack.getItem());
|
||||
//TODO convert lookingAt hitvec to relative hitvec
|
||||
@@ -230,4 +263,8 @@ public class BuilderChain {
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public List<BlockEntry> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package nl.requios.effortlessbuilding.systems;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.network.IsQuickReplacingPacket;
|
||||
import nl.requios.effortlessbuilding.network.PacketHandler;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class QuickReplace {
|
||||
private boolean isQuickReplacing = false;
|
||||
|
||||
public boolean isQuickReplacing() {
|
||||
return isQuickReplacing;
|
||||
}
|
||||
|
||||
public void toggleQuickReplacing() {
|
||||
setIsQuickReplacing(!isQuickReplacing);
|
||||
}
|
||||
|
||||
public void setIsQuickReplacing(boolean isQuickReplacing) {
|
||||
this.isQuickReplacing = isQuickReplacing;
|
||||
|
||||
EffortlessBuilding.log(Minecraft.getInstance().player, "Set " + ChatFormatting.GOLD + "Quick Replace " +
|
||||
ChatFormatting.RESET + (this.isQuickReplacing ? "on" : "off"));
|
||||
PacketHandler.INSTANCE.sendToServer(new IsQuickReplacingPacket(this.isQuickReplacing));
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,17 @@ package nl.requios.effortlessbuilding.systems;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
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 java.util.List;
|
||||
|
||||
// Receives block placement requests from the client and places them
|
||||
public class ServerBlockPlacer {
|
||||
private boolean isPlacingOrBreakingBlocks = false;
|
||||
|
||||
public void placeBlocks(Player player, List<BlockEntry> blocks) {
|
||||
EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks");
|
||||
@@ -27,31 +27,33 @@ public class ServerBlockPlacer {
|
||||
Level world = player.level;
|
||||
if (!world.isLoaded(block.blockPos)) return;
|
||||
|
||||
if (block.meansBreakBlock()) {
|
||||
breakBlock(player, block.blockPos);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = world.setBlock(block.blockPos, block.blockState, 3);
|
||||
isPlacingOrBreakingBlocks = true;
|
||||
BlockHelper.placeSchematicBlock(world, block.blockState, block.blockPos, block.itemStack, null);
|
||||
isPlacingOrBreakingBlocks = false;
|
||||
}
|
||||
|
||||
public void breakBlock(Player player, BlockPos pos) {
|
||||
public void breakBlocks(Player player, List<BlockEntry> blocks) {
|
||||
EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks");
|
||||
|
||||
for (BlockEntry block : blocks) {
|
||||
breakBlock(player, block);
|
||||
}
|
||||
}
|
||||
|
||||
public void breakBlock(Player player, BlockEntry block) {
|
||||
ServerLevel world = (ServerLevel) player.level;
|
||||
if (!world.isLoaded(pos) || world.isEmptyBlock(pos)) return;
|
||||
if (!world.isLoaded(block.blockPos) || world.isEmptyBlock(block.blockPos)) return;
|
||||
|
||||
//Held tool
|
||||
|
||||
if (!player.getAbilities().instabuild) {
|
||||
|
||||
//Drops
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
List<ItemStack> drops = Block.getDrops(blockState, world, pos, world.getBlockEntity(pos), player, player.getMainHandItem());
|
||||
for (ItemStack drop : drops) {
|
||||
player.addItem(drop);
|
||||
isPlacingOrBreakingBlocks = true;
|
||||
BlockHelper.destroyBlockAs(world, block.blockPos, player, player.getMainHandItem(), 1.0f, stack -> {
|
||||
if (!player.isCreative()) {
|
||||
ItemHandlerHelper.giveItemToPlayer(player, stack);
|
||||
}
|
||||
}
|
||||
|
||||
world.removeBlock(pos, false);
|
||||
});
|
||||
isPlacingOrBreakingBlocks = false;
|
||||
}
|
||||
|
||||
public boolean isPlacingOrBreakingBlocks() {
|
||||
return isPlacingOrBreakingBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package nl.requios.effortlessbuilding.systems;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
|
||||
public class ServerBuildState {
|
||||
private static final String IS_USING_BUILD_MODE_KEY = EffortlessBuilding.MODID + ":isUsingBuildMode";
|
||||
private static final String IS_QUICK_REPLACING_KEY = EffortlessBuilding.MODID + ":isQuickReplacing";
|
||||
|
||||
public static boolean isUsingBuildMode(Player player) {
|
||||
return player.getPersistentData().contains(IS_USING_BUILD_MODE_KEY);
|
||||
}
|
||||
|
||||
public static void setIsUsingBuildMode(Player player, boolean isUsingBuildMode) {
|
||||
if (isUsingBuildMode) {
|
||||
player.getPersistentData().putBoolean(IS_USING_BUILD_MODE_KEY, true);
|
||||
} else {
|
||||
player.getPersistentData().remove(IS_USING_BUILD_MODE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isQuickReplacing(Player player) {
|
||||
return player.getPersistentData().contains(IS_QUICK_REPLACING_KEY);
|
||||
}
|
||||
|
||||
public static void setIsQuickReplacing(Player player, boolean isQuickReplacing) {
|
||||
if (isQuickReplacing) {
|
||||
player.getPersistentData().putBoolean(IS_QUICK_REPLACING_KEY, true);
|
||||
} else {
|
||||
player.getPersistentData().remove(IS_QUICK_REPLACING_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,60 @@ package nl.requios.effortlessbuilding.utilities;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.util.Mth;
|
||||
import nl.requios.effortlessbuilding.CommonConfig;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
|
||||
public class ReachHelper {
|
||||
private static final String REACH_UPGRADE_KEY = EffortlessBuilding.MODID + ":reachUpgrade";
|
||||
|
||||
public static int getReachUpgrade(Player player) {
|
||||
if (!player.getPersistentData().contains(REACH_UPGRADE_KEY)) return 0;
|
||||
return player.getPersistentData().getInt(REACH_UPGRADE_KEY);
|
||||
}
|
||||
|
||||
//Remember that to actually save it, this needs to be called on the server
|
||||
public static void setReachUpgrade(Player player, int reachUpgrade) {
|
||||
player.getPersistentData().putInt(REACH_UPGRADE_KEY, reachUpgrade);
|
||||
|
||||
if (player.level.isClientSide) {
|
||||
//Set mirror radius to max
|
||||
int reach = 10;
|
||||
switch (reachUpgrade) {
|
||||
case 0:
|
||||
reach = CommonConfig.reach.maxReachLevel0.get();
|
||||
break;
|
||||
case 1:
|
||||
reach = CommonConfig.reach.maxReachLevel1.get();
|
||||
break;
|
||||
case 2:
|
||||
reach = CommonConfig.reach.maxReachLevel2.get();
|
||||
break;
|
||||
case 3:
|
||||
reach = CommonConfig.reach.maxReachLevel3.get();
|
||||
break;
|
||||
}
|
||||
|
||||
//TODO enable
|
||||
// if (this.mirrorSettings != null)
|
||||
// this.mirrorSettings.radius = reach / 2;
|
||||
// if (this.radialMirrorSettings != null)
|
||||
// this.radialMirrorSettings.radius = reach / 2;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static int getMaxReach(Player player) {
|
||||
if (player.isCreative()) return CommonConfig.reach.maxReachCreative.get();
|
||||
|
||||
if (!CommonConfig.reach.enableReachUpgrades.get()) return CommonConfig.reach.maxReachLevel3.get();
|
||||
|
||||
//Check buildsettings for reachUpgrade
|
||||
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
|
||||
switch (reachUpgrade) {
|
||||
case 0:
|
||||
return CommonConfig.reach.maxReachLevel0.get();
|
||||
case 1:
|
||||
return CommonConfig.reach.maxReachLevel1.get();
|
||||
case 2:
|
||||
return CommonConfig.reach.maxReachLevel2.get();
|
||||
case 3:
|
||||
return CommonConfig.reach.maxReachLevel3.get();
|
||||
}
|
||||
return CommonConfig.reach.maxReachLevel0.get();
|
||||
return switch (getReachUpgrade(player)) {
|
||||
case 1 -> CommonConfig.reach.maxReachLevel1.get();
|
||||
case 2 -> CommonConfig.reach.maxReachLevel2.get();
|
||||
case 3 -> CommonConfig.reach.maxReachLevel3.get();
|
||||
default -> CommonConfig.reach.maxReachLevel0.get();
|
||||
};
|
||||
}
|
||||
|
||||
public static int getPlacementReach(Player player) {
|
||||
|
||||
@@ -24,8 +24,10 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import nl.requios.effortlessbuilding.CommonConfig;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
|
||||
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
|
||||
import nl.requios.effortlessbuilding.systems.ServerBuildState;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -271,8 +273,12 @@ public class SurvivalHelper {
|
||||
}
|
||||
|
||||
//Check quickreplace
|
||||
if (placer != null && ModifierSettingsManager.getModifierSettings(((Player) placer)).doQuickReplace()) {
|
||||
return true;
|
||||
boolean isQuickReplacing = false;
|
||||
if (placer instanceof Player player) {
|
||||
if (world.isClientSide) EffortlessBuildingClient.QUICK_REPLACE.isQuickReplacing();
|
||||
else isQuickReplacing = ServerBuildState.isQuickReplacing(player);
|
||||
|
||||
if (isQuickReplacing) return true;
|
||||
}
|
||||
|
||||
return currentBlockState.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
|
||||
|
||||
Reference in New Issue
Block a user