Added server validation: allowInSurvival and whitelist.
Instantly placing blocksets of size 1. Added server config and moved some config values around.
This commit is contained in:
@@ -2,18 +2,22 @@ package nl.requios.effortlessbuilding;
|
|||||||
|
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
import static net.minecraftforge.common.ForgeConfigSpec.*;
|
||||||
|
|
||||||
public class ClientConfig {
|
public class ClientConfig {
|
||||||
|
|
||||||
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
private static final Builder builder = new Builder();
|
||||||
public static final Visuals visuals = new Visuals(builder);
|
public static final Visuals visuals = new Visuals(builder);
|
||||||
public static final ForgeConfigSpec spec = builder.build();
|
public static final ForgeConfigSpec spec = builder.build();
|
||||||
|
|
||||||
public static class Visuals {
|
public static class Visuals {
|
||||||
public final ForgeConfigSpec.ConfigValue<Boolean> showBlockPreviews;
|
public final BooleanValue showBlockPreviews;
|
||||||
public final ForgeConfigSpec.ConfigValue<Boolean> onlyShowBlockPreviewsWhenBuilding;
|
public final BooleanValue onlyShowBlockPreviewsWhenBuilding;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxBlockPreviews;
|
public final IntValue maxBlockPreviews;
|
||||||
|
public final IntValue appearAnimationLength;
|
||||||
|
public final IntValue breakAnimationLength;
|
||||||
|
|
||||||
public Visuals(ForgeConfigSpec.Builder builder) {
|
public Visuals(Builder builder) {
|
||||||
builder.push("Visuals");
|
builder.push("Visuals");
|
||||||
|
|
||||||
showBlockPreviews = builder
|
showBlockPreviews = builder
|
||||||
@@ -27,8 +31,17 @@ public class ClientConfig {
|
|||||||
maxBlockPreviews = builder
|
maxBlockPreviews = builder
|
||||||
.comment("Don't show block previews when placing more than this many blocks. " +
|
.comment("Don't show block previews when placing more than this many blocks. " +
|
||||||
"The outline will always be rendered.")
|
"The outline will always be rendered.")
|
||||||
.define("maxBlockPreviews", 500);
|
.defineInRange("maxBlockPreviews", 500, 0, 5000);
|
||||||
|
|
||||||
|
appearAnimationLength = builder
|
||||||
|
.comment("How long it takes for a block to appear when placed in ticks.",
|
||||||
|
"Set to 0 to disable animation.")
|
||||||
|
.defineInRange("appearAnimationLength", 5, 0, 100);
|
||||||
|
|
||||||
|
breakAnimationLength = builder
|
||||||
|
.comment("How long the break animation is in ticks.",
|
||||||
|
"Set to 0 to disable animation.")
|
||||||
|
.defineInRange("breakAnimationLength", 10, 0, 100);
|
||||||
|
|
||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,24 @@ package nl.requios.effortlessbuilding;
|
|||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
import nl.requios.effortlessbuilding.create.foundation.render.SuperByteBufferCache;
|
import nl.requios.effortlessbuilding.create.foundation.render.SuperByteBufferCache;
|
||||||
|
|
||||||
|
import static net.minecraftforge.common.ForgeConfigSpec.*;
|
||||||
|
|
||||||
public class CommonConfig {
|
public class CommonConfig {
|
||||||
|
|
||||||
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
private static final Builder builder = new Builder();
|
||||||
public static final Reach reach = new Reach(builder);
|
public static final Reach reach = new Reach(builder);
|
||||||
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder);
|
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder);
|
||||||
public static final Visuals visuals = new Visuals(builder);
|
|
||||||
public static final ForgeConfigSpec spec = builder.build();
|
public static final ForgeConfigSpec spec = builder.build();
|
||||||
|
|
||||||
public static class Reach {
|
public static class Reach {
|
||||||
public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades;
|
public final BooleanValue enableReachUpgrades;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative;
|
public final IntValue maxReachCreative;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0;
|
public final IntValue maxReachLevel0;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1;
|
public final IntValue maxReachLevel1;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2;
|
public final IntValue maxReachLevel2;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3;
|
public final IntValue maxReachLevel3;
|
||||||
|
|
||||||
public Reach(ForgeConfigSpec.Builder builder) {
|
public Reach(Builder builder) {
|
||||||
builder.push("Reach");
|
builder.push("Reach");
|
||||||
enableReachUpgrades = builder
|
enableReachUpgrades = builder
|
||||||
.comment("Reach: how far away the player can place blocks using mirror/array etc.",
|
.comment("Reach: how far away the player can place blocks using mirror/array etc.",
|
||||||
@@ -30,35 +31,34 @@ public class CommonConfig {
|
|||||||
maxReachCreative = builder
|
maxReachCreative = builder
|
||||||
.comment("Maximum reach in creative",
|
.comment("Maximum reach in creative",
|
||||||
"Keep in mind that chunks need to be loaded to be able to place blocks inside.")
|
"Keep in mind that chunks need to be loaded to be able to place blocks inside.")
|
||||||
.define("maxReachCreative", 200);
|
.defineInRange("maxReachCreative", 200, 0, 1000);
|
||||||
|
|
||||||
maxReachLevel0 = builder
|
maxReachLevel0 = builder
|
||||||
.comment("Maximum reach in survival without upgrades",
|
.comment("Maximum reach in survival without upgrades",
|
||||||
"Reach upgrades are craftable consumables that permanently increase reach.",
|
"Reach upgrades are craftable consumables that permanently increase reach.",
|
||||||
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
|
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
|
||||||
.define("maxReachLevel0", 20);
|
.defineInRange("maxReachLevel0", 20, 0, 1000);
|
||||||
|
|
||||||
maxReachLevel1 = builder
|
maxReachLevel1 = builder
|
||||||
.comment("Maximum reach in survival with one upgrade")
|
.comment("Maximum reach in survival with one upgrade")
|
||||||
.define("maxReachLevel1", 50);
|
.defineInRange("maxReachLevel1", 50, 0, 1000);
|
||||||
|
|
||||||
maxReachLevel2 = builder
|
maxReachLevel2 = builder
|
||||||
.comment("Maximum reach in survival with two upgrades")
|
.comment("Maximum reach in survival with two upgrades")
|
||||||
.define("maxReachLevel2", 100);
|
.defineInRange("maxReachLevel2", 100, 0, 1000);
|
||||||
|
|
||||||
maxReachLevel3 = builder
|
maxReachLevel3 = builder
|
||||||
.comment("Maximum reach in survival with three upgrades")
|
.comment("Maximum reach in survival with three upgrades")
|
||||||
.define("maxReachLevel3", 200);
|
.defineInRange("maxReachLevel3", 200, 0, 1000);
|
||||||
|
|
||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SurvivalBalancers {
|
public static class SurvivalBalancers {
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
|
public final IntValue quickReplaceMiningLevel;
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
|
|
||||||
|
|
||||||
public SurvivalBalancers(ForgeConfigSpec.Builder builder) {
|
public SurvivalBalancers(Builder builder) {
|
||||||
builder.push("SurvivalBalancers");
|
builder.push("SurvivalBalancers");
|
||||||
|
|
||||||
quickReplaceMiningLevel = builder
|
quickReplaceMiningLevel = builder
|
||||||
@@ -71,32 +71,6 @@ public class CommonConfig {
|
|||||||
"4: blocks that can be harvested with netherite tools")
|
"4: blocks that can be harvested with netherite tools")
|
||||||
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
|
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
|
||||||
|
|
||||||
undoStackSize = builder
|
|
||||||
.comment("How many placements are remembered for the undo functionality.")
|
|
||||||
.worldRestart()
|
|
||||||
.define("undoStackSize", 50);
|
|
||||||
|
|
||||||
builder.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Visuals {
|
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> appearAnimationLength;
|
|
||||||
public final ForgeConfigSpec.ConfigValue<Integer> breakAnimationLength;
|
|
||||||
|
|
||||||
public Visuals(ForgeConfigSpec.Builder builder) {
|
|
||||||
builder.push("Visuals");
|
|
||||||
|
|
||||||
appearAnimationLength = builder
|
|
||||||
.comment("How long it takes for a block to appear when placed in ticks.",
|
|
||||||
"Set to 0 to disable animation.")
|
|
||||||
.define("appearAnimationLength", 5);
|
|
||||||
|
|
||||||
breakAnimationLength = builder
|
|
||||||
.comment("How long the break animation is in ticks.",
|
|
||||||
"Set to 0 to disable animation.")
|
|
||||||
.define("breakAnimationLength", 10);
|
|
||||||
|
|
||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public class EffortlessBuilding {
|
|||||||
//Register config
|
//Register config
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.spec);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.spec);
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ClientConfig.spec);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ClientConfig.spec);
|
||||||
|
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ServerConfig.spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setup(final FMLCommonSetupEvent event) {
|
public static void setup(final FMLCommonSetupEvent event) {
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package nl.requios.effortlessbuilding;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static net.minecraftforge.common.ForgeConfigSpec.*;
|
||||||
|
|
||||||
|
public class ServerConfig {
|
||||||
|
private static final Builder builder = new Builder();
|
||||||
|
public static final ServerConfig.Validation validation = new ServerConfig.Validation(builder);
|
||||||
|
public static final ServerConfig.Memory memory = new ServerConfig.Memory(builder);
|
||||||
|
public static final ForgeConfigSpec spec = builder.build();
|
||||||
|
|
||||||
|
public static class Validation {
|
||||||
|
public final BooleanValue allowInSurvival;
|
||||||
|
public final BooleanValue useWhitelist;
|
||||||
|
public final ConfigValue<List<? extends String>> whitelist;
|
||||||
|
|
||||||
|
public Validation(Builder builder) {
|
||||||
|
builder.push("Validation");
|
||||||
|
|
||||||
|
allowInSurvival = builder
|
||||||
|
.comment("Allow use of the mod for players that are in survival mode. Otherwise, only creative mode players can use the mod.")
|
||||||
|
.define("allowInSurvival", true);
|
||||||
|
|
||||||
|
useWhitelist = builder
|
||||||
|
.comment("Use a whitelist to determine which players can use the mod. If false, all players can use the mod.")
|
||||||
|
.define("useWhitelist", false);
|
||||||
|
|
||||||
|
whitelist = builder
|
||||||
|
.comment("List of player names that can use the mod.")
|
||||||
|
.defineList("whitelist", Arrays.asList("Player1", "Player2"), o -> true);
|
||||||
|
|
||||||
|
builder.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Memory {
|
||||||
|
public final IntValue undoStackSize;
|
||||||
|
|
||||||
|
public Memory(Builder builder) {
|
||||||
|
builder.push("Memory");
|
||||||
|
|
||||||
|
undoStackSize = builder
|
||||||
|
.comment("How many placements are remembered for the undo functionality.")
|
||||||
|
.worldRestart()
|
||||||
|
.defineInRange("undoStackSize", 50, 10, 200);
|
||||||
|
|
||||||
|
builder.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ public class BlockPreviews {
|
|||||||
if (ClientConfig.visuals.showBlockPreviews.get()) {
|
if (ClientConfig.visuals.showBlockPreviews.get()) {
|
||||||
for (PlacedBlocksEntry placed : placedBlocksList) {
|
for (PlacedBlocksEntry placed : placedBlocksList) {
|
||||||
|
|
||||||
int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get();
|
int totalTime = placed.breaking ? ClientConfig.visuals.breakAnimationLength.get() : ClientConfig.visuals.appearAnimationLength.get();
|
||||||
if (totalTime <= 0) continue;
|
if (totalTime <= 0) continue;
|
||||||
|
|
||||||
float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime;
|
float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime;
|
||||||
@@ -50,7 +50,7 @@ public class BlockPreviews {
|
|||||||
|
|
||||||
//Expire
|
//Expire
|
||||||
placedBlocksList.removeIf(placed -> {
|
placedBlocksList.removeIf(placed -> {
|
||||||
int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get();
|
int totalTime = placed.breaking ? ClientConfig.visuals.breakAnimationLength.get() : ClientConfig.visuals.appearAnimationLength.get();
|
||||||
return placed.time + totalTime < ClientEvents.ticksInGame;
|
return placed.time + totalTime < ClientEvents.ticksInGame;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ public class BlockPreviews {
|
|||||||
|
|
||||||
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, false, new BlockSet(blocks)));
|
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, false, new BlockSet(blocks)));
|
||||||
|
|
||||||
CreateClient.OUTLINER.keep(blocks.firstPos, CommonConfig.visuals.appearAnimationLength.get());
|
CreateClient.OUTLINER.keep(blocks.firstPos, ClientConfig.visuals.appearAnimationLength.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onBlocksBroken(BlockSet blocks) {
|
public void onBlocksBroken(BlockSet blocks) {
|
||||||
@@ -237,7 +237,7 @@ public class BlockPreviews {
|
|||||||
|
|
||||||
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, true, new BlockSet(blocks)));
|
placedBlocksList.add(new PlacedBlocksEntry(ClientEvents.ticksInGame, true, new BlockSet(blocks)));
|
||||||
|
|
||||||
CreateClient.OUTLINER.keep(blocks.firstPos, CommonConfig.visuals.breakAnimationLength.get());
|
CreateClient.OUTLINER.keep(blocks.firstPos, ClientConfig.visuals.breakAnimationLength.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
|
private void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.minecraft.world.phys.HitResult;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import nl.requios.effortlessbuilding.ClientConfig;
|
||||||
import nl.requios.effortlessbuilding.ClientEvents;
|
import nl.requios.effortlessbuilding.ClientEvents;
|
||||||
import nl.requios.effortlessbuilding.CommonConfig;
|
import nl.requios.effortlessbuilding.CommonConfig;
|
||||||
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
|
||||||
@@ -87,7 +88,8 @@ public class BuilderChain {
|
|||||||
player.swing(InteractionHand.MAIN_HAND);
|
player.swing(InteractionHand.MAIN_HAND);
|
||||||
|
|
||||||
blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
|
blocks.skipFirst = buildMode == BuildModeEnum.DISABLED;
|
||||||
long placeTime = player.level.getGameTime() + CommonConfig.visuals.appearAnimationLength.get() - 3;
|
long placeTime = player.level.getGameTime();
|
||||||
|
if (blocks.size() > 1) placeTime += ClientConfig.visuals.appearAnimationLength.get();
|
||||||
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks, placeTime));
|
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks, placeTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,17 @@
|
|||||||
package nl.requios.effortlessbuilding.systems;
|
package nl.requios.effortlessbuilding.systems;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.stats.Stats;
|
|
||||||
import net.minecraft.world.InteractionHand;
|
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.BucketItem;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
|
|
||||||
import net.minecraftforge.common.util.BlockSnapshot;
|
|
||||||
import net.minecraftforge.event.ForgeEventFactory;
|
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||||
|
import nl.requios.effortlessbuilding.ServerConfig;
|
||||||
import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper;
|
import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper;
|
||||||
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
import nl.requios.effortlessbuilding.utilities.BlockEntry;
|
||||||
import nl.requios.effortlessbuilding.utilities.BlockSet;
|
import nl.requios.effortlessbuilding.utilities.BlockSet;
|
||||||
|
import nl.requios.effortlessbuilding.utilities.BlockUtilities;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -31,7 +22,8 @@ public class ServerBlockPlacer {
|
|||||||
private boolean isPlacingOrBreakingBlocks = false;
|
private boolean isPlacingOrBreakingBlocks = false;
|
||||||
|
|
||||||
public void placeBlocksDelayed(Player player, BlockSet blocks, long placeTime) {
|
public void placeBlocksDelayed(Player player, BlockSet blocks, long placeTime) {
|
||||||
|
if (!checkAndNotifyAllowedToUseMod(player)) return;
|
||||||
|
|
||||||
delayedEntries.add(new DelayedEntry(player, blocks, placeTime));
|
delayedEntries.add(new DelayedEntry(player, blocks, placeTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +38,7 @@ public class ServerBlockPlacer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void placeBlocks(Player player, BlockSet blocks) {
|
public void placeBlocks(Player player, BlockSet blocks) {
|
||||||
|
if (!checkAndNotifyAllowedToUseMod(player)) return;
|
||||||
// EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks");
|
// EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks");
|
||||||
|
|
||||||
for (BlockEntry block : blocks) {
|
for (BlockEntry block : blocks) {
|
||||||
@@ -54,16 +47,17 @@ public class ServerBlockPlacer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void placeBlock(Player player, BlockEntry block) {
|
private void placeBlock(Player player, BlockEntry block) {
|
||||||
Level world = player.level;
|
Level world = player.level;
|
||||||
if (!world.isLoaded(block.blockPos)) return;
|
if (!world.isLoaded(block.blockPos)) return;
|
||||||
|
|
||||||
isPlacingOrBreakingBlocks = true;
|
isPlacingOrBreakingBlocks = true;
|
||||||
boolean placedBlock = onPlaceItemIntoWorld(player, block) == InteractionResult.SUCCESS;
|
boolean placedBlock = BlockUtilities.placeBlockEntry(player, block) == InteractionResult.SUCCESS;
|
||||||
isPlacingOrBreakingBlocks = false;
|
isPlacingOrBreakingBlocks = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void breakBlocks(Player player, BlockSet blocks) {
|
public void breakBlocks(Player player, BlockSet blocks) {
|
||||||
|
if (!checkAndNotifyAllowedToUseMod(player)) return;
|
||||||
// EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks");
|
// EffortlessBuilding.log(player, "Breaking " + blocks.size() + " blocks");
|
||||||
|
|
||||||
for (BlockEntry block : blocks) {
|
for (BlockEntry block : blocks) {
|
||||||
@@ -72,7 +66,7 @@ public class ServerBlockPlacer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void breakBlock(Player player, BlockEntry block) {
|
private void breakBlock(Player player, BlockEntry block) {
|
||||||
ServerLevel world = (ServerLevel) player.level;
|
ServerLevel world = (ServerLevel) player.level;
|
||||||
if (!world.isLoaded(block.blockPos) || world.isEmptyBlock(block.blockPos)) return;
|
if (!world.isLoaded(block.blockPos) || world.isEmptyBlock(block.blockPos)) return;
|
||||||
|
|
||||||
@@ -84,6 +78,24 @@ public class ServerBlockPlacer {
|
|||||||
});
|
});
|
||||||
isPlacingOrBreakingBlocks = false;
|
isPlacingOrBreakingBlocks = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean checkAndNotifyAllowedToUseMod(Player player) {
|
||||||
|
if (!isAllowedToUseMod(player)) {
|
||||||
|
EffortlessBuilding.log(player, ChatFormatting.RED + "You are not allowed to use Effortless Building.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowedToUseMod(Player player) {
|
||||||
|
if (!ServerConfig.validation.allowInSurvival.get() && !player.isCreative()) return false;
|
||||||
|
|
||||||
|
if (ServerConfig.validation.useWhitelist.get()) {
|
||||||
|
return ServerConfig.validation.whitelist.get().contains(player.getGameProfile().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<DelayedEntry> getDelayedEntries() {
|
public Set<DelayedEntry> getDelayedEntries() {
|
||||||
return delayedEntriesView;
|
return delayedEntriesView;
|
||||||
@@ -95,96 +107,4 @@ public class ServerBlockPlacer {
|
|||||||
|
|
||||||
public record DelayedEntry(Player player, BlockSet blocks, long placeTime) {}
|
public record DelayedEntry(Player player, BlockSet blocks, long placeTime) {}
|
||||||
|
|
||||||
//ForgeHooks::onPlaceItemIntoWorld
|
|
||||||
private InteractionResult onPlaceItemIntoWorld(Player player, BlockEntry block) {
|
|
||||||
|
|
||||||
ItemStack itemstack = block.itemStack;
|
|
||||||
Level level = player.level;
|
|
||||||
|
|
||||||
if (player != null && !player.getAbilities().mayBuild && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, block.blockPos, false)))
|
|
||||||
return InteractionResult.PASS;
|
|
||||||
|
|
||||||
// handle all placement events here
|
|
||||||
Item item = itemstack.getItem();
|
|
||||||
int size = itemstack.getCount();
|
|
||||||
CompoundTag nbt = null;
|
|
||||||
if (itemstack.getTag() != null)
|
|
||||||
nbt = itemstack.getTag().copy();
|
|
||||||
|
|
||||||
if (!(itemstack.getItem() instanceof BucketItem)) // if not bucket
|
|
||||||
level.captureBlockSnapshots = true;
|
|
||||||
|
|
||||||
ItemStack copy = itemstack.copy();
|
|
||||||
////
|
|
||||||
BlockHelper.placeSchematicBlock(level, player, block.newBlockState, block.blockPos, block.itemStack, null);
|
|
||||||
////
|
|
||||||
InteractionResult ret = InteractionResult.SUCCESS;
|
|
||||||
if (itemstack.isEmpty())
|
|
||||||
ForgeEventFactory.onPlayerDestroyItem(player, copy, InteractionHand.MAIN_HAND);
|
|
||||||
|
|
||||||
level.captureBlockSnapshots = false;
|
|
||||||
|
|
||||||
if (ret.consumesAction())
|
|
||||||
{
|
|
||||||
// save new item data
|
|
||||||
int newSize = itemstack.getCount();
|
|
||||||
CompoundTag newNBT = null;
|
|
||||||
if (itemstack.getTag() != null)
|
|
||||||
{
|
|
||||||
newNBT = itemstack.getTag().copy();
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<BlockSnapshot> blockSnapshots = (List<BlockSnapshot>)level.capturedBlockSnapshots.clone();
|
|
||||||
level.capturedBlockSnapshots.clear();
|
|
||||||
|
|
||||||
// make sure to set pre-placement item data for event
|
|
||||||
itemstack.setCount(size);
|
|
||||||
itemstack.setTag(nbt);
|
|
||||||
|
|
||||||
Direction side = Direction.UP;
|
|
||||||
|
|
||||||
boolean eventResult = false;
|
|
||||||
if (blockSnapshots.size() > 1)
|
|
||||||
{
|
|
||||||
eventResult = ForgeEventFactory.onMultiBlockPlace(player, blockSnapshots, side);
|
|
||||||
}
|
|
||||||
else if (blockSnapshots.size() == 1)
|
|
||||||
{
|
|
||||||
eventResult = ForgeEventFactory.onBlockPlace(player, blockSnapshots.get(0), side);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventResult)
|
|
||||||
{
|
|
||||||
ret = InteractionResult.FAIL; // cancel placement
|
|
||||||
// revert back all captured blocks
|
|
||||||
for (BlockSnapshot blocksnapshot : Lists.reverse(blockSnapshots))
|
|
||||||
{
|
|
||||||
level.restoringBlockSnapshots = true;
|
|
||||||
blocksnapshot.restore(true, false);
|
|
||||||
level.restoringBlockSnapshots = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Change the stack to its new content
|
|
||||||
itemstack.setCount(newSize);
|
|
||||||
itemstack.setTag(newNBT);
|
|
||||||
|
|
||||||
for (BlockSnapshot snap : blockSnapshots)
|
|
||||||
{
|
|
||||||
int updateFlag = snap.getFlag();
|
|
||||||
BlockState oldBlock = snap.getReplacedBlock();
|
|
||||||
BlockState newBlock = level.getBlockState(snap.getPos());
|
|
||||||
newBlock.onPlace(level, snap.getPos(), oldBlock, false);
|
|
||||||
|
|
||||||
level.markAndNotifyBlock(snap.getPos(), level.getChunkAt(snap.getPos()), oldBlock, newBlock, updateFlag, 512);
|
|
||||||
}
|
|
||||||
if (player != null)
|
|
||||||
player.awardStat(Stats.ITEM_USED.get(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
level.capturedBlockSnapshots.clear();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import nl.requios.effortlessbuilding.CommonConfig;
|
import nl.requios.effortlessbuilding.CommonConfig;
|
||||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||||
|
import nl.requios.effortlessbuilding.ServerConfig;
|
||||||
import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet;
|
import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet;
|
||||||
import nl.requios.effortlessbuilding.utilities.FixedStack;
|
import nl.requios.effortlessbuilding.utilities.FixedStack;
|
||||||
import nl.requios.effortlessbuilding.utilities.InventoryHelper;
|
import nl.requios.effortlessbuilding.utilities.InventoryHelper;
|
||||||
@@ -49,7 +50,7 @@ public class UndoRedo {
|
|||||||
|
|
||||||
//If no stack exists, make one
|
//If no stack exists, make one
|
||||||
if (!undoStacks.containsKey(player.getUUID())) {
|
if (!undoStacks.containsKey(player.getUUID())) {
|
||||||
undoStacks.put(player.getUUID(), new FixedStack<>(new UndoRedoBlockSet[CommonConfig.survivalBalancers.undoStackSize.get()]));
|
undoStacks.put(player.getUUID(), new FixedStack<>(new UndoRedoBlockSet[ServerConfig.memory.undoStackSize.get()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
undoStacks.get(player.getUUID()).push(blockSet);
|
undoStacks.get(player.getUUID()).push(blockSet);
|
||||||
@@ -62,7 +63,7 @@ public class UndoRedo {
|
|||||||
|
|
||||||
//If no stack exists, make one
|
//If no stack exists, make one
|
||||||
if (!redoStacks.containsKey(player.getUUID())) {
|
if (!redoStacks.containsKey(player.getUUID())) {
|
||||||
redoStacks.put(player.getUUID(), new FixedStack<>(new UndoRedoBlockSet[CommonConfig.survivalBalancers.undoStackSize.get()]));
|
redoStacks.put(player.getUUID(), new FixedStack<>(new UndoRedoBlockSet[ServerConfig.memory.undoStackSize.get()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
redoStacks.get(player.getUUID()).push(blockSet);
|
redoStacks.get(player.getUUID()).push(blockSet);
|
||||||
|
|||||||
@@ -1,22 +1,35 @@
|
|||||||
package nl.requios.effortlessbuilding.utilities;
|
package nl.requios.effortlessbuilding.utilities;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.stats.Stats;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.BucketItem;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
import net.minecraft.world.level.ClipContext;
|
import net.minecraft.world.level.ClipContext;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.*;
|
import net.minecraft.world.level.block.*;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
|
||||||
import net.minecraft.world.level.block.state.properties.Half;
|
import net.minecraft.world.level.block.state.properties.Half;
|
||||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.common.util.BlockSnapshot;
|
||||||
|
import net.minecraftforge.event.ForgeEventFactory;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.BlockHelper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
//Common
|
//Common
|
||||||
public class BlockUtilities {
|
public class BlockUtilities {
|
||||||
@@ -47,6 +60,98 @@ public class BlockUtilities {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ForgeHooks::onPlaceItemIntoWorld
|
||||||
|
public static InteractionResult placeBlockEntry(Player player, BlockEntry block) {
|
||||||
|
ItemStack itemstack = block.itemStack;
|
||||||
|
Level level = player.level;
|
||||||
|
|
||||||
|
if (player != null && !player.getAbilities().mayBuild && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, block.blockPos, false)))
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
|
||||||
|
// handle all placement events here
|
||||||
|
Item item = itemstack.getItem();
|
||||||
|
int size = itemstack.getCount();
|
||||||
|
CompoundTag nbt = null;
|
||||||
|
if (itemstack.getTag() != null)
|
||||||
|
nbt = itemstack.getTag().copy();
|
||||||
|
|
||||||
|
if (!(itemstack.getItem() instanceof BucketItem)) // if not bucket
|
||||||
|
level.captureBlockSnapshots = true;
|
||||||
|
|
||||||
|
ItemStack copy = itemstack.copy();
|
||||||
|
////
|
||||||
|
BlockHelper.placeSchematicBlock(level, player, block.newBlockState, block.blockPos, block.itemStack, null);
|
||||||
|
////
|
||||||
|
InteractionResult ret = InteractionResult.SUCCESS;
|
||||||
|
if (itemstack.isEmpty())
|
||||||
|
ForgeEventFactory.onPlayerDestroyItem(player, copy, InteractionHand.MAIN_HAND);
|
||||||
|
|
||||||
|
level.captureBlockSnapshots = false;
|
||||||
|
|
||||||
|
if (ret.consumesAction())
|
||||||
|
{
|
||||||
|
// save new item data
|
||||||
|
int newSize = itemstack.getCount();
|
||||||
|
CompoundTag newNBT = null;
|
||||||
|
if (itemstack.getTag() != null)
|
||||||
|
{
|
||||||
|
newNBT = itemstack.getTag().copy();
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<BlockSnapshot> blockSnapshots = (List<BlockSnapshot>)level.capturedBlockSnapshots.clone();
|
||||||
|
level.capturedBlockSnapshots.clear();
|
||||||
|
|
||||||
|
// make sure to set pre-placement item data for event
|
||||||
|
itemstack.setCount(size);
|
||||||
|
itemstack.setTag(nbt);
|
||||||
|
|
||||||
|
Direction side = Direction.UP;
|
||||||
|
|
||||||
|
boolean eventResult = false;
|
||||||
|
if (blockSnapshots.size() > 1)
|
||||||
|
{
|
||||||
|
eventResult = ForgeEventFactory.onMultiBlockPlace(player, blockSnapshots, side);
|
||||||
|
}
|
||||||
|
else if (blockSnapshots.size() == 1)
|
||||||
|
{
|
||||||
|
eventResult = ForgeEventFactory.onBlockPlace(player, blockSnapshots.get(0), side);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventResult)
|
||||||
|
{
|
||||||
|
ret = InteractionResult.FAIL; // cancel placement
|
||||||
|
// revert back all captured blocks
|
||||||
|
for (BlockSnapshot blocksnapshot : Lists.reverse(blockSnapshots))
|
||||||
|
{
|
||||||
|
level.restoringBlockSnapshots = true;
|
||||||
|
blocksnapshot.restore(true, false);
|
||||||
|
level.restoringBlockSnapshots = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Change the stack to its new content
|
||||||
|
itemstack.setCount(newSize);
|
||||||
|
itemstack.setTag(newNBT);
|
||||||
|
|
||||||
|
for (BlockSnapshot snap : blockSnapshots)
|
||||||
|
{
|
||||||
|
int updateFlag = snap.getFlag();
|
||||||
|
BlockState oldBlock = snap.getReplacedBlock();
|
||||||
|
BlockState newBlock = level.getBlockState(snap.getPos());
|
||||||
|
newBlock.onPlace(level, snap.getPos(), oldBlock, false);
|
||||||
|
|
||||||
|
level.markAndNotifyBlock(snap.getPos(), level.getChunkAt(snap.getPos()), oldBlock, newBlock, updateFlag, 512);
|
||||||
|
}
|
||||||
|
if (player != null)
|
||||||
|
player.awardStat(Stats.ITEM_USED.get(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
level.capturedBlockSnapshots.clear();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public static void playSoundIfFurtherThanNormal(Player player, BlockEntry blockEntry, boolean breaking) {
|
public static void playSoundIfFurtherThanNormal(Player player, BlockEntry blockEntry, boolean breaking) {
|
||||||
|
|
||||||
if (Minecraft.getInstance().hitResult != null && Minecraft.getInstance().hitResult.getType() == HitResult.Type.BLOCK)
|
if (Minecraft.getInstance().hitResult != null && Minecraft.getInstance().hitResult.getType() == HitResult.Type.BLOCK)
|
||||||
|
|||||||
Reference in New Issue
Block a user