Added power level items and their loot modifiers.

This commit is contained in:
Christian Knaapen
2023-06-24 16:45:36 +02:00
parent 33033666b9
commit 9e680fc2dc
29 changed files with 594 additions and 62 deletions

View File

@@ -3,7 +3,7 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
mod_version = 3.0
mod_version = 3.1
artifact_minecraft_version = 1.19.2
minecraft_version = 1.19.2

View File

@@ -37,12 +37,9 @@ public class ClientEvents {
@SubscribeEvent
public static void registerKeyMappings(RegisterKeyMappingsEvent event) {
EffortlessBuilding.log("Registering KeyMappings!");
// register key bindings
keyBindings = new KeyMapping[6];
// instantiate the key bindings
keyBindings[0] = new KeyMapping("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category");
keyBindings[1] = new KeyMapping("key.effortlessbuilding.hud.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category");
keyBindings[2] = new KeyMapping("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");

View File

@@ -29,7 +29,7 @@ public class CommonConfig {
level0 = builder
.comment("Maximum reach in survival without upgrades",
"Consume Power Level upgrades upgrades to permanently increase this.")
"Consume Power Level upgrades to permanently increase this.")
.defineInRange("reachLevel0", 0, 0, 1000);
level1 = builder
@@ -61,7 +61,7 @@ public class CommonConfig {
level0 = builder
.comment("In survival without upgrades",
"Consume Power Level upgrades upgrades to permanently increase this.",
"Consume Power Level upgrades to permanently increase this.",
"Set to 0 to disable Effortless Building until the player has increased their Building Power Level.")
.defineInRange("maxBlocksPlacedAtOnceLevel0", 128, 0, 100000);
@@ -89,12 +89,13 @@ public class CommonConfig {
builder.push("MaxBlocksPerAxis");
creative = builder
.comment("How many blocks can be placed at once per axis.")
.comment("How many blocks can be placed at once per axis when using build modes (e.g. walls).",
"Also affects the array modifier.")
.defineInRange("maxBlocksPerAxisCreative", 1000, 0, 1000);
level0 = builder
.comment("In survival without upgrades",
"Consume Power Level upgrades upgrades to permanently increase this.")
"Consume Power Level upgrades to permanently increase this.")
.defineInRange("maxBlocksPerAxisLevel0", 8, 0, 1000);
level1 = builder

View File

@@ -68,7 +68,7 @@ public class CommonEvents {
//Don't cancel event if our custom logic is breaking blocks
if (EffortlessBuilding.SERVER_BLOCK_PLACER.isPlacingOrBreakingBlocks()) return;
if (!ServerBuildState.isLikeVanilla(player) && PowerLevel.canBreakFar(player)) {
if (!ServerBuildState.isLikeVanilla(player) && EffortlessBuilding.SERVER_POWER_LEVEL.canBreakFar(player)) {
event.setCanceled(true);
}
}
@@ -88,6 +88,7 @@ public class CommonEvents {
ServerBuildState.handleNewPlayer(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ModifierSettingsPacket(player));
EffortlessBuilding.SERVER_POWER_LEVEL.sendToClient(player);
}
@SubscribeEvent

View File

@@ -1,5 +1,6 @@
package nl.requios.effortlessbuilding;
import com.mojang.serialization.Codec;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
@@ -7,6 +8,7 @@ import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Item;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModLoadingContext;
@@ -29,6 +31,7 @@ import nl.requios.effortlessbuilding.proxy.IProxy;
import nl.requios.effortlessbuilding.proxy.ServerProxy;
import nl.requios.effortlessbuilding.systems.ItemUsageTracker;
import nl.requios.effortlessbuilding.systems.ServerBlockPlacer;
import nl.requios.effortlessbuilding.systems.ServerPowerLevel;
import nl.requios.effortlessbuilding.systems.UndoRedo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -45,10 +48,12 @@ public class EffortlessBuilding {
public static final ServerBlockPlacer SERVER_BLOCK_PLACER = new ServerBlockPlacer();
public static final UndoRedo UNDO_REDO = new UndoRedo();
public static final ItemUsageTracker ITEM_USAGE_TRACKER = new ItemUsageTracker();
public static final ServerPowerLevel SERVER_POWER_LEVEL = new ServerPowerLevel();
//Registration
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
private static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, EffortlessBuilding.MODID);
public static final DeferredRegister<Codec<? extends IGlobalLootModifier>> LOOT_MODIFIERS = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, EffortlessBuilding.MODID);
public static final RegistryObject<Item> RANDOMIZER_BAG_ITEM = ITEMS.register("randomizer_bag", RandomizerBagItem::new);
public static final RegistryObject<Item> GOLDEN_RANDOMIZER_BAG_ITEM = ITEMS.register("golden_randomizer_bag", GoldenRandomizerBagItem::new);
@@ -56,11 +61,15 @@ public class EffortlessBuilding {
public static final RegistryObject<Item> REACH_UPGRADE_1_ITEM = ITEMS.register("reach_upgrade1", ReachUpgrade1Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_2_ITEM = ITEMS.register("reach_upgrade2", ReachUpgrade2Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_3_ITEM = ITEMS.register("reach_upgrade3", ReachUpgrade3Item::new);
public static final RegistryObject<Item> MUSCLES_ITEM = ITEMS.register("muscles", PowerLevelItem::new);
public static final RegistryObject<Item> ELASTIC_HAND_ITEM = ITEMS.register("elastic_hand", PowerLevelItem::new);
public static final RegistryObject<Item> BUILDING_TECHNIQUES_BOOK_ITEM = ITEMS.register("building_techniques_book", PowerLevelItem::new);
public static final RegistryObject<MenuType<RandomizerBagContainer>> RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("randomizer_bag", () -> registerContainer(RandomizerBagContainer::new));
public static final RegistryObject<MenuType<GoldenRandomizerBagContainer>> GOLDEN_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("golden_randomizer_bag", () -> registerContainer(GoldenRandomizerBagContainer::new));
public static final RegistryObject<MenuType<DiamondRandomizerBagContainer>> DIAMOND_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("diamond_randomizer_bag", () -> registerContainer(DiamondRandomizerBagContainer::new));
public EffortlessBuilding() {
instance = this;
@@ -75,6 +84,9 @@ public class EffortlessBuilding {
ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus());
var singleItemLootModifier = SingleItemLootModifier.CODEC; //load this class to register the loot modifier
LOOT_MODIFIERS.register(FMLJavaModLoadingContext.get().getModEventBus());
//Register config
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.spec);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ClientConfig.spec);

View File

@@ -144,13 +144,17 @@ public class RadialMenu extends Screen {
}
//Add actions
boolean canReplace = Minecraft.getInstance().player != null && EffortlessBuildingClient.POWER_LEVEL.canReplaceBlocks(Minecraft.getInstance().player);
// buttons.add(new MenuButton(ActionEnum.OPEN_PLAYER_SETTINGS, -buttonDistance - 65, -13, Direction.UP));
if (canReplace) {
buttons.add(new MenuButton(ActionEnum.TOGGLE_PROTECT_TILE_ENTITIES, -buttonDistance - 78, -13, Direction.UP));
}
buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 52, -13, Direction.UP));
buttons.add(new MenuButton(ActionEnum.UNDO, -buttonDistance - 26, -13, Direction.UP));
buttons.add(new MenuButton(ActionEnum.REDO, -buttonDistance, -13, Direction.UP));
if (Minecraft.getInstance().player != null && PowerLevel.canReplaceBlocks(Minecraft.getInstance().player)) {
if (canReplace) {
buttons.add(new MenuButton(ActionEnum.REPLACE_ONLY_AIR, -buttonDistance - 78, 13, Direction.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE_BLOCKS_AND_AIR, -buttonDistance - 52, 13, Direction.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE_ONLY_BLOCKS, -buttonDistance - 26, 13, Direction.DOWN));

View File

@@ -0,0 +1,56 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.ChatFormatting;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class PowerLevelItem extends Item {
public PowerLevelItem() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (world.isClientSide){
if (EffortlessBuildingClient.POWER_LEVEL.canIncreasePowerLevel()) {
EffortlessBuildingClient.POWER_LEVEL.increasePowerLevel();
EffortlessBuilding.log(player, "Upgraded power level to " + EffortlessBuildingClient.POWER_LEVEL.getPowerLevel());
player.setItemInHand(hand, ItemStack.EMPTY);
return InteractionResultHolder.consume(player.getItemInHand(hand));
} else {
EffortlessBuilding.log(player, "Already reached maximum power level!");
return InteractionResultHolder.fail(player.getItemInHand(hand));
}
} else {
return InteractionResultHolder.consume(player.getItemInHand(hand));
}
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag isAdvanced) {
tooltip.add(Component.translatable(getDescriptionId() + ".desc").withStyle(ChatFormatting.GRAY));
tooltip.add(Component.translatable("key.effortlessbuilding.upgrade_power_level").withStyle(ChatFormatting.BLUE));
}
}

View File

@@ -20,7 +20,6 @@ import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@@ -36,12 +35,12 @@ public class ReachUpgrade1Item extends Item {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
return InteractionResultHolder.pass(player.getItemInHand(hand));
}
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel(player);
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel();
if (currentLevel == 0) {
EffortlessBuildingClient.POWER_LEVEL.setPowerLevel(player, 1);
EffortlessBuildingClient.POWER_LEVEL.loadPowerLevel(1);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + EffortlessBuildingClient.POWER_LEVEL.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
@@ -56,7 +55,7 @@ public class ReachUpgrade1Item extends Item {
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
return InteractionResultHolder.consume(player.getItemInHand(hand));
}
@Override

View File

@@ -39,9 +39,9 @@ public class ReachUpgrade2Item extends Item {
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel(player);
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel();
if (currentLevel == 1) {
EffortlessBuildingClient.POWER_LEVEL.setPowerLevel(player, 2);
EffortlessBuildingClient.POWER_LEVEL.loadPowerLevel(2);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + EffortlessBuildingClient.POWER_LEVEL.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);

View File

@@ -39,9 +39,9 @@ public class ReachUpgrade3Item extends Item {
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel(player);
int currentLevel = EffortlessBuildingClient.POWER_LEVEL.getPowerLevel();
if (currentLevel == 2) {
EffortlessBuildingClient.POWER_LEVEL.setPowerLevel(player, 3);
EffortlessBuildingClient.POWER_LEVEL.loadPowerLevel(3);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + EffortlessBuildingClient.POWER_LEVEL.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);

View File

@@ -0,0 +1,59 @@
package nl.requios.effortlessbuilding.item;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifier;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import org.jetbrains.annotations.NotNull;
//Adds a single item with a chance to any loot tables. Specify loot tables in the JSON file.
//Add JSON files to resources/data/effortlessbuilding/loot_modifiers, and list them in resources/data/forge/loot_modifiers/global_loot_modifiers.json
//https://forge.gemwire.uk/wiki/Dynamic_Loot_Modification
//https://forums.minecraftforge.net/topic/112960-1182-solved-adding-modded-items-to-existing-vanilla-loot-tables/
//https://mcreator.net/wiki/minecraft-vanilla-loot-tables-list#toc-index-1
public class SingleItemLootModifier extends LootModifier {
public static final RegistryObject<Codec<SingleItemLootModifier>> CODEC = EffortlessBuilding.LOOT_MODIFIERS.register("single_item_loot_modifier", () ->
RecordCodecBuilder.create(inst -> codecStart(inst).and(
inst.group(
Codec.FLOAT.fieldOf("chance").forGetter(m -> m.chance),
ForgeRegistries.ITEMS.getCodec().fieldOf("item").forGetter(m -> m.item)
)).apply(inst, SingleItemLootModifier::new)
));
private final float chance;
private final Item item;
public SingleItemLootModifier(LootItemCondition[] conditionsIn, float chance, Item item) {
super(conditionsIn);
this.chance = chance;
this.item = item;
}
@NotNull
@Override
public ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, LootContext context) {
//
// Additional conditions can be checked, though as much as possible should be parameterized via JSON data.
// It is better to write a new ILootCondition implementation than to do things here.
//
//with chance, add an item
if (context.getRandom().nextFloat() < chance) {
generatedLoot.add(new ItemStack(item, 1));
}
return generatedLoot;
}
@Override
public Codec<? extends IGlobalLootModifier> codec() {
return CODEC.get();
}
}

View File

@@ -49,12 +49,12 @@ public class ModifierSettingsPacket {
if (ctx.get().getDirection().getReceptionSide().isServer()) {
ctx.get().enqueueWork(() -> {
var player = ctx.get().getSender();
//Save to persistent player data
//To server, save to persistent player data
player.getPersistentData().put(DATA_KEY, message.modifiersTag);
});
} else {
ctx.get().enqueueWork(() -> {
//Load from persistent player data
//To client, load into system
EffortlessBuildingClient.BUILD_MODIFIERS.deserializeNBT(message.modifiersTag);
});
}

View File

@@ -34,6 +34,8 @@ public class PacketHandler {
PerformRedoPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
INSTANCE.registerMessage(id++, ModifierSettingsPacket.class, ModifierSettingsPacket::encode, ModifierSettingsPacket::decode,
ModifierSettingsPacket.Handler::handle);
INSTANCE.registerMessage(id++, PowerLevelPacket.class, PowerLevelPacket::encode, PowerLevelPacket::decode,
PowerLevelPacket.Handler::handle);
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import java.util.function.Supplier;
/**
* Sync power level between server and client, for saving and loading.
*/
public class PowerLevelPacket {
private int powerLevel;
public PowerLevelPacket() {
}
public PowerLevelPacket(int powerLevel) {
this.powerLevel = powerLevel;
}
public static void encode(PowerLevelPacket message, FriendlyByteBuf buf) {
buf.writeInt(message.powerLevel);
}
public static PowerLevelPacket decode(FriendlyByteBuf buf) {
return new PowerLevelPacket(buf.readInt());
}
public static class Handler {
public static void handle(PowerLevelPacket message, Supplier<NetworkEvent.Context> ctx) {
if (ctx.get().getDirection().getReceptionSide().isServer()) {
ctx.get().enqueueWork(() -> {
var player = ctx.get().getSender();
//To server, save to persistent player data
EffortlessBuilding.SERVER_POWER_LEVEL.setPowerLevel(player, message.powerLevel);
});
} else {
ctx.get().enqueueWork(() -> {
//To client, load into system
EffortlessBuildingClient.POWER_LEVEL.setPowerLevel(message.powerLevel);
});
}
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -68,6 +68,6 @@ public class BuildSettings {
}
private boolean canReplaceBlocks(){
return Minecraft.getInstance().player != null && PowerLevel.canReplaceBlocks(Minecraft.getInstance().player);
return Minecraft.getInstance().player != null && EffortlessBuildingClient.POWER_LEVEL.canReplaceBlocks(Minecraft.getInstance().player);
}
}

View File

@@ -103,7 +103,7 @@ public class BuilderChain {
}
var player = Minecraft.getInstance().player;
if (player != null && !PowerLevel.canBreakFar(player)) return;
if (player != null && !EffortlessBuildingClient.POWER_LEVEL.canBreakFar(player)) return;
if (buildingState == BuildingState.IDLE){
buildingState = BuildingState.BREAKING;
@@ -220,7 +220,7 @@ public class BuilderChain {
var startPos = lookingAt.getBlockPos();
//Check if out of reach
int maxReach = EffortlessBuildingClient.POWER_LEVEL.getMaxReach(player);
int maxReach = EffortlessBuildingClient.POWER_LEVEL.getPlacementReach(player);
if (player.blockPosition().distSqr(startPos) > maxReach * maxReach) return null;
startPosForBreaking = startPos;
@@ -240,7 +240,7 @@ public class BuilderChain {
//We can only break
//Do not break far if we are not allowed to
if (!shouldLookAtNear && !PowerLevel.canBreakFar(player)) return null;
if (!shouldLookAtNear && !EffortlessBuildingClient.POWER_LEVEL.canBreakFar(player)) return null;
}
var blockEntry = new BlockEntry(startPos);

View File

@@ -1,49 +1,46 @@
package nl.requios.effortlessbuilding.systems;
import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.PowerLevelPacket;
//Common
@OnlyIn(Dist.CLIENT)
public class PowerLevel {
private static final String POWER_LEVEL_KEY = EffortlessBuilding.MODID + ":powerLevel";
private static final int MAX_POWER_LEVEL = 3;
private int powerLevel;
public int getPowerLevel(Player player) {
if (!player.getPersistentData().contains(POWER_LEVEL_KEY)) return 0;
return player.getPersistentData().getInt(POWER_LEVEL_KEY);
public int getPowerLevel() {
return powerLevel;
}
public void increasePowerLevel(Player player) {
int powerLevel = getPowerLevel(player);
if (powerLevel < MAX_POWER_LEVEL) {
setPowerLevel(player, powerLevel + 1);
}
}
public void setPowerLevel(Player player, int powerLevel) {
player.getPersistentData().putInt(POWER_LEVEL_KEY, powerLevel);
if (player.level.isClientSide) {
public void setPowerLevel(int powerLevel) {
this.powerLevel = powerLevel;
EffortlessBuildingClient.BUILD_MODIFIERS.onPowerLevelChanged(powerLevel);
}
public boolean canIncreasePowerLevel() {
return getPowerLevel() < MAX_POWER_LEVEL;
}
public void increasePowerLevel() {
if (canIncreasePowerLevel()) {
setPowerLevel(getPowerLevel() + 1);
PacketHandler.INSTANCE.sendToServer(new PowerLevelPacket(powerLevel));
}
}
@Deprecated
public int getMaxReach(Player player) {
if (player.isCreative()) return CommonConfig.reach.creative.get();
return switch (getPowerLevel(player)) {
case 1 -> CommonConfig.reach.level1.get();
case 2 -> CommonConfig.reach.level2.get();
case 3 -> CommonConfig.reach.level3.get();
default -> CommonConfig.reach.level0.get();
};
return getPlacementReach(player);
}
public int getPlacementReach(Player player) {
if (player.isCreative()) return CommonConfig.reach.creative.get();
return switch (getPowerLevel(player)) {
return switch (getPowerLevel()) {
case 1 -> CommonConfig.reach.level1.get();
case 2 -> CommonConfig.reach.level2.get();
case 3 -> CommonConfig.reach.level3.get();
@@ -54,12 +51,12 @@ public class PowerLevel {
//How far away we can detect the second and third click of build modes (distance to player)
public int getBuildModeReach(Player player) {
//A bit further than placement reach, so you can build lines when looking to the side without having to move.
return getMaxReach(player) + 6;
return getPlacementReach(player) + 6;
}
public int getMaxBlocksPlacedAtOnce(Player player) {
if (player.isCreative()) return CommonConfig.maxBlocksPlacedAtOnce.creative.get();
return switch (getPowerLevel(player)) {
return switch (getPowerLevel()) {
case 1 -> CommonConfig.maxBlocksPlacedAtOnce.level1.get();
case 2 -> CommonConfig.maxBlocksPlacedAtOnce.level2.get();
case 3 -> CommonConfig.maxBlocksPlacedAtOnce.level3.get();
@@ -69,7 +66,7 @@ public class PowerLevel {
public int getMaxBlocksPerAxis(Player player) {
if (player.isCreative()) return CommonConfig.maxBlocksPerAxis.creative.get();
return switch (getPowerLevel(player)) {
return switch (getPowerLevel()) {
case 1 -> CommonConfig.maxBlocksPerAxis.level1.get();
case 2 -> CommonConfig.maxBlocksPerAxis.level2.get();
case 3 -> CommonConfig.maxBlocksPerAxis.level3.get();
@@ -79,7 +76,7 @@ public class PowerLevel {
public int getMaxMirrorRadius(Player player) {
if (player.isCreative()) return CommonConfig.maxMirrorRadius.creative.get();
return switch (getPowerLevel(player)) {
return switch (getPowerLevel()) {
case 1 -> CommonConfig.maxMirrorRadius.level1.get();
case 2 -> CommonConfig.maxMirrorRadius.level2.get();
case 3 -> CommonConfig.maxMirrorRadius.level3.get();
@@ -91,12 +88,11 @@ public class PowerLevel {
return getMaxBlocksPlacedAtOnce(player) <= 0 || getMaxBlocksPerAxis(player) <= 0;
}
//Static methods are used by client and server
public static boolean canBreakFar(Player player) {
public boolean canBreakFar(Player player) {
return player.isCreative();
}
public static boolean canReplaceBlocks(Player player) {
public boolean canReplaceBlocks(Player player) {
return player.isCreative();
}
}

View File

@@ -2,6 +2,7 @@ package nl.requios.effortlessbuilding.systems;
import net.minecraft.world.entity.player.Player;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
public class ServerBuildState {
private static final String IS_USING_BUILD_MODE_KEY = EffortlessBuilding.MODID + ":isUsingBuildMode";
@@ -25,7 +26,7 @@ public class ServerBuildState {
}
public static boolean isQuickReplacing(Player player) {
if (!PowerLevel.canReplaceBlocks(player)) return false;
if (!EffortlessBuilding.SERVER_POWER_LEVEL.canReplaceBlocks(player)) return false;
return player.getPersistentData().contains(IS_QUICK_REPLACING_KEY);
}

View File

@@ -0,0 +1,33 @@
package nl.requios.effortlessbuilding.systems;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.PowerLevelPacket;
public class ServerPowerLevel {
private static final String POWER_LEVEL_KEY = EffortlessBuilding.MODID + ":powerLevel";
public int getPowerLevel(Player player) {
if (!player.getPersistentData().contains(POWER_LEVEL_KEY)) return 0;
return player.getPersistentData().getInt(POWER_LEVEL_KEY);
}
public void setPowerLevel(Player player, int powerLevel) {
player.getPersistentData().putInt(POWER_LEVEL_KEY, powerLevel);
}
public void sendToClient(Player player) {
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new PowerLevelPacket(getPowerLevel(player)));
}
public boolean canBreakFar(Player player) {
return player.isCreative();
}
public boolean canReplaceBlocks(Player player) {
return player.isCreative();
}
}

View File

@@ -12,6 +12,7 @@
"key.effortlessbuilding.altplacement.desc": "Alternative placement",
"key.effortlessbuilding.previous_build_mode.desc": "Activate Previous Build Mode",
"key.effortlessbuilding.disable_build_mode_toggle.desc": "Toggle Disabled <> Previous Build Mode",
"key.effortlessbuilding.upgrade_power_level": "Use to permanently upgrade your Building Power Level by 1.",
"item.effortlessbuilding.randomizer_bag": "Leather Randomizer Bag",
"item.effortlessbuilding.golden_randomizer_bag": "Golden Randomizer Bag",
@@ -19,6 +20,12 @@
"item.effortlessbuilding.reach_upgrade1": "Reach Upgrade 1",
"item.effortlessbuilding.reach_upgrade2": "Reach Upgrade 2",
"item.effortlessbuilding.reach_upgrade3": "Reach Upgrade 3",
"item.effortlessbuilding.muscles": "Muscles",
"item.effortlessbuilding.muscles.desc": "Train your biceps to place multiple blocks at once.",
"item.effortlessbuilding.elastic_hand": "Elastic Hand",
"item.effortlessbuilding.elastic_hand.desc": "A flexible arm to place blocks further away.",
"item.effortlessbuilding.building_techniques_book": "Building Techniques Book",
"item.effortlessbuilding.building_techniques_book.desc": "Contains various building techniques to help you build faster.",
"effortlessbuilding.mode.normal": "Disable",
"effortlessbuilding.mode.normal_plus": "Single",
@@ -98,5 +105,6 @@
"effortlessbuilding.tooltip.holdForControls": "Hold [%1$s] for Controls",
"effortlessbuilding.tooltip.keyShift": "Shift",
"effortlessbuilding.tooltip.keyCtrl": "Ctrl",
"effortlessbuilding.tooltip.keybind": "[%1$s]"
"effortlessbuilding.tooltip.keybind": "[%1$s]",
"fdsaf": "key.effortlessbuilding.upgrade_power_level"
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/buildingtechniquesbook"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/elastichand"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/muscles"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -0,0 +1,11 @@
{
"type": "effortlessbuilding:single_item_loot_modifier",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_library"
}
],
"item": "effortlessbuilding:building_techniques_book",
"chance": 0.6
}

View File

@@ -0,0 +1,92 @@
{
"type": "effortlessbuilding:single_item_loot_modifier",
"conditions": [
{
"condition": "minecraft:alternative",
"terms": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/abandoned_mineshaft"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ancient_city"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_other"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/buried_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/desert_pyramid"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/end_city_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/igloo_chest"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/jungle_temple"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/nether_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/pillager_outpost"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ruined_portal"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_supply"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/simple_dungeon"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_corridor"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_crossing"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_library"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/woodland_mansion"
}
]
}
],
"item": "effortlessbuilding:building_techniques_book",
"chance": 0.05
}

View File

@@ -0,0 +1,92 @@
{
"type": "effortlessbuilding:single_item_loot_modifier",
"conditions": [
{
"condition": "minecraft:alternative",
"terms": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/abandoned_mineshaft"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ancient_city"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_other"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/buried_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/desert_pyramid"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/end_city_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/igloo_chest"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/jungle_temple"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/nether_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/pillager_outpost"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ruined_portal"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_supply"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/simple_dungeon"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_corridor"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_crossing"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_library"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/woodland_mansion"
}
]
}
],
"item": "effortlessbuilding:elastic_hand",
"chance": 0.07
}

View File

@@ -0,0 +1,92 @@
{
"type": "effortlessbuilding:single_item_loot_modifier",
"conditions": [
{
"condition": "minecraft:alternative",
"terms": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/abandoned_mineshaft"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ancient_city"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_other"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/buried_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/desert_pyramid"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/end_city_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/igloo_chest"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/jungle_temple"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/nether_bridge"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/pillager_outpost"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ruined_portal"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_supply"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_treasure"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/simple_dungeon"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_corridor"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_crossing"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_library"
},
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/woodland_mansion"
}
]
}
],
"item": "effortlessbuilding:muscles",
"chance": 0.07
}

View File

@@ -0,0 +1,9 @@
{
"replace": false,
"entries": [
"effortlessbuilding:muscles_loot_modifier",
"effortlessbuilding:elastic_hand_loot_modifier",
"effortlessbuilding:building_techniques_book_loot_modifier",
"effortlessbuilding:building_techniques_book_library_loot_modifier"
]
}