Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/io/github/pylonmc/pylon/Pylon.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.github.pylonmc.pylon.content.machines.simple.Grindstone;
import io.github.pylonmc.pylon.content.machines.smelting.Bloomery;
import io.github.pylonmc.pylon.content.talismans.*;
import io.github.pylonmc.pylon.content.tools.BedRoll;
import io.github.pylonmc.pylon.content.tools.ShimmerMagnet;
import io.github.pylonmc.pylon.content.tools.SoulboundRune;
import io.github.pylonmc.pylon.content.tools.base.Rune;
Expand Down Expand Up @@ -67,6 +68,8 @@ public void onEnable() {
pm.registerEvents(new BreedingTalisman.BreedingTalismanListener(), this);
pm.registerEvents(new EnchantingTalisman.EnchantingListener(), this);
pm.registerEvents(new HuntingTalisman.HuntingTalismanListener(), this);

pm.registerEvents(new BedRoll.BedRollListener(), this);
}

@Override
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/io/github/pylonmc/pylon/PylonItemTag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.github.pylonmc.pylon;

import com.destroystokyo.paper.MaterialSetTag;
import io.github.pylonmc.rebar.item.RebarItemTag;
import io.github.pylonmc.rebar.registry.RebarRegistry;
import org.bukkit.Material;

import static io.github.pylonmc.pylon.util.PylonUtils.pylonKey;

public class PylonItemTag {
public static final MaterialSetTag GLASSLIKE_BUKKIT = new MaterialSetTag(pylonKey("all_glass"))
.endsWith("_GLASS")
.endsWith("GLASS_PANE")
.add(Material.GLASS)
.add(Material.SEA_LANTERN)
.add(Material.BEACON)
.add(Material.GLOWSTONE)
.add(Material.REDSTONE_LAMP);

public static final RebarItemTag GLASSLIKE = new RebarItemTag(
GLASSLIKE_BUKKIT.getKey(),
GLASSLIKE_BUKKIT.getValues().toArray(new Material[0])
);

static {
RebarRegistry.ITEM_TAGS.register(GLASSLIKE);
}
}
39 changes: 39 additions & 0 deletions src/main/java/io/github/pylonmc/pylon/PylonItems.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@
import io.papermc.paper.datacomponent.item.*;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.keys.SoundEventKeys;
import io.papermc.paper.registry.keys.tags.DamageTypeTagKeys;
import io.papermc.paper.registry.set.RegistrySet;
import net.kyori.adventure.key.Key;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
Expand Down Expand Up @@ -79,6 +82,33 @@ private PylonItems() {
PylonPages.SCIENCE.addItem(LOUPE);
}


public static final ItemStack BRONZE_LOUPE = ItemStackBuilder.rebar(Material.CLAY_BALL, PylonKeys.BRONZE_LOUPE)
.set(DataComponentTypes.ITEM_MODEL, Material.GLASS_PANE.getKey())
.set(DataComponentTypes.CONSUMABLE, Consumable.consumable()
.animation(ItemUseAnimation.SPYGLASS)
.hasConsumeParticles(false)
.consumeSeconds(Settings.get(PylonKeys.BRONZE_LOUPE).getOrThrow("use-ticks", ConfigAdapter.INTEGER) / 20.0F)
.sound(SoundEventKeys.INTENTIONALLY_EMPTY)
)
.set(DataComponentTypes.USE_COOLDOWN, UseCooldown.useCooldown(
Settings.get(PylonKeys.BRONZE_LOUPE).getOrThrow("cooldown-ticks", ConfigAdapter.INTEGER) / 20.0F)
.cooldownGroup(PylonKeys.LOUPE)
)
.build();
static {
RebarItem.register(Loupe.class, BRONZE_LOUPE);
PylonPages.SCIENCE.addItem(BRONZE_LOUPE);
}

public static final ItemStack BED_ROLL = ItemStackBuilder.rebar(Material.CLAY_BALL, PylonKeys.BED_ROLL)
.set(DataComponentTypes.ITEM_MODEL, Material.RED_BED.getKey())
.build();
static {
RebarItem.register(BedRoll.class, BED_ROLL);
PylonPages.TOOLS.addItem(BED_ROLL);
}

public static final ItemStack RESEARCH_PACK_1 = ItemStackBuilder.rebar(Material.RED_BANNER, PylonKeys.RESEARCH_PACK_1)
.useCooldown(Settings.get(PylonKeys.RESEARCH_PACK_1).getOrThrow("cooldown-ticks", ConfigAdapter.INTEGER), PylonKeys.RESEARCH_PACK_1)
.set(DataComponentTypes.MAX_STACK_SIZE, 3)
Expand Down Expand Up @@ -817,6 +847,15 @@ private PylonItems() {
PylonPages.TOOLS.addItem(DIAMOND_HAMMER);
}

public static final ItemStack GLASS_BREAKER = ItemStackBuilder.rebarToolWeapon(Material.CLAY_BALL, PylonKeys.GLASS_BREAKER, RegistrySet.keySet(RegistryKey.BLOCK, PylonItemTag.GLASSLIKE.getValues().stream().map(it -> TypedKey.create(RegistryKey.BLOCK, it.getKey())).toList()), true, false, false)
.set(DataComponentTypes.ITEM_MODEL, Material.IRON_PICKAXE.getKey())
.build();
static {
RebarItem.register(RebarItem.class, GLASS_BREAKER);
PylonPages.TOOLS.addItem(GLASS_BREAKER);
}


public static final ItemStack BRONZE_AXE = ItemStackBuilder.rebarToolWeapon(Material.CLAY_BALL, PylonKeys.BRONZE_AXE, RebarUtils.axeMineable(), true, false, true)
.set(DataComponentTypes.ITEM_MODEL, Material.GOLDEN_AXE.getKey())
.build();
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/github/pylonmc/pylon/PylonKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ public class PylonKeys {

public static final NamespacedKey FIBER = pylonKey("fiber");

public static final NamespacedKey GLASS_BREAKER = pylonKey("glass_breaker");

public static final NamespacedKey BRONZE_SWORD = pylonKey("bronze_sword");
public static final NamespacedKey BRONZE_AXE = pylonKey("bronze_axe");
public static final NamespacedKey BRONZE_PICKAXE = pylonKey("bronze_pickaxe");
Expand Down Expand Up @@ -218,6 +220,9 @@ public class PylonKeys {
public static final NamespacedKey CREATIVE_FLUID_SOURCE = pylonKey("creative_fluid_source");

public static final NamespacedKey LOUPE = pylonKey("loupe");
public static final NamespacedKey BRONZE_LOUPE = pylonKey("bronze_loupe");

public static final NamespacedKey BED_ROLL = pylonKey("bed_roll");

public static final NamespacedKey RESEARCH_PACK_1 = pylonKey("research_pack_1");
public static final NamespacedKey RESEARCH_PACK_2 = pylonKey("research_pack_2");
Expand Down
130 changes: 130 additions & 0 deletions src/main/java/io/github/pylonmc/pylon/content/tools/BedRoll.java
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just feels like a bad way to implement this imo. There’s no perm checks for placement or breaking, its manual place & break which is just prone to issues with other plugins, also you don’t set facing on the blockdata, does this work on all rotations?

I would make the bedroll a normal bed item, prevent placement if its not night time, and then post successful place do most of the existing logic. Then on wake auto break with the actual method and give the bed directly to the player. That way we actually call events properly.

We could also make a RebarBed block interface for onSleep, onWakeup, onSetSpawn which this could use but obv that can happen later (if ever)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any realistic way on why the plugins should interact with the bed roll, but I can open an issue later I don't feel like adding that stuff because it doesn't seem that necessary to me nor I have a clear idea what you are trying to pitch (beside the permission checks)

Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package io.github.pylonmc.pylon.content.tools;

import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent;
import io.github.pylonmc.rebar.event.api.annotation.MultiHandler;
import io.github.pylonmc.rebar.item.RebarItem;
import io.github.pylonmc.rebar.item.base.RebarBlockInteractor;
import kotlin.Pair;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.type.Bed;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;

public final class BedRoll extends RebarItem implements RebarBlockInteractor {
public static final Map<UUID, Pair<Block, Block>> SLEEP_MAP = new HashMap<>();
public static final HashSet<Location> BLOCKS = new HashSet<>();

public BedRoll(@NotNull ItemStack stack) {
super(stack);
}

@Override
@MultiHandler(priorities = { EventPriority.NORMAL, EventPriority.MONITOR })
public void onUsedToClickBlock(@NotNull PlayerInteractEvent event, @NotNull EventPriority priority) {
Player player = event.getPlayer();
Block clicked = event.getClickedBlock();
if (!event.getAction().isRightClick()
|| clicked == null
|| event.useItemInHand() == Event.Result.DENY
|| player.isSneaking()) {
return;
}

if (priority == EventPriority.NORMAL) {
event.setUseInteractedBlock(Event.Result.DENY);
return;
}

World world = player.getWorld();
if (world.getEnvironment() == World.Environment.NETHER || world.getEnvironment() == World.Environment.THE_END) {
player.getInventory().getItemInMainHand().subtract();
world.createExplosion(clicked.getLocation(), 5f, true, true);
return;
}

if (!world.isBedWorks()) {
return; // we cannot sleep
}

UUID playerId = player.getUniqueId();
if (SLEEP_MAP.containsKey(playerId)) {
return; // maybe error message
}

Block baseBed = clicked.getRelative(BlockFace.UP);
Block otherBed = baseBed.getRelative(player.getFacing());
if (!baseBed.isEmpty() || !otherBed.isEmpty()) {
return; // maybe error message
}

baseBed.setBlockData(
Bukkit.createBlockData(Material.RED_BED, (bd) -> {
Bed bed = (Bed) bd;
bed.setPart(Bed.Part.FOOT);
})
);

otherBed.setBlockData(
Bukkit.createBlockData(Material.RED_BED, (bd) -> {
Bed bed = (Bed) bd;
bed.setPart(Bed.Part.HEAD);
})
);

Location bedLocation = baseBed.getLocation();
player.teleport(bedLocation);

// put before just in case the event doesn't pick it up
SLEEP_MAP.put(playerId, new Pair<>(baseBed, otherBed));
BLOCKS.add(baseBed.getLocation());
BLOCKS.add(otherBed.getLocation());
if (!player.sleep(bedLocation, true)) {
SLEEP_MAP.remove(playerId);
BLOCKS.remove(baseBed.getLocation());
BLOCKS.remove(otherBed.getLocation());
}
}

public static class BedRollListener implements Listener {

@EventHandler(ignoreCancelled = true)
public void changeRespawn(PlayerSetSpawnEvent event) {
if (event.getCause() != PlayerSetSpawnEvent.Cause.BED) return;
if (SLEEP_MAP.containsKey(event.getPlayer().getUniqueId())) event.setCancelled(true);
}

@EventHandler(ignoreCancelled = true)
public void sleepCompleted(TimeSkipEvent event) {
if (event.getSkipReason() != TimeSkipEvent.SkipReason.NIGHT_SKIP) return;
SLEEP_MAP.forEach((k, v) -> {
v.getFirst().setType(Material.AIR, false);
v.getSecond().setType(Material.AIR, false);
});
SLEEP_MAP.clear();
BLOCKS.clear();
}

@EventHandler(ignoreCancelled = true)
public void preventBedRollBreak(BlockBreakEvent event) {
if (BLOCKS.contains(event.getBlock().getLocation())) event.setCancelled(true);
}
}
}
18 changes: 18 additions & 0 deletions src/main/resources/lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,24 @@ item:
<diamond> 1x <yellow><lang:pylon.item.bloomery.name/></yellow>
<diamond> 4x <yellow><lang:pylon.item.refractory_bricks.name/></yellow>

glass_breaker:
name: "Glass Breaker"
lore: |-
<arrow> Breaks glass like material faster, includes:
<arrow> - All types of glass blocks
<arrow> - All types of glass panes
<arrow> - Sea Lantern
<arrow> - Glowstone Block
<arrow> - Redstone Lamp
<arrow> - Beacon

bed_roll:
name: "Bed Roll"
lore: |-
<arrow> Right click to sleep on selected block.
<arrow> There must be space available to place a bed.
<arrow> Doesn't change respawn point

bronze_anvil:
name: "Bronze Anvil"
lore: |-
Expand Down
36 changes: 36 additions & 0 deletions src/main/resources/recipes/minecraft/crafting_shaped.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@ pylon:charcoal_block_from_charcoal:
result: pylon:charcoal_block
category: building

pylon:glass_breaker:
pattern:
- "TCT"
- "RSR"
- " S "
key:
S: minecraft:stick
C: minecraft:glowstone
T: pylon:tin_ingot
R: minecraft:redstone
result: pylon:glass_breaker
category: equipment

pylon:bed_roll:
pattern:
- "CCW"
- "CWW"
- "WWS"
key:
C: "#minecraft:wool_carpets"
W: "#minecraft:wool"
S: minecraft:string
result: pylon:bed_roll
category: equipment

pylon:bronze_sword:
pattern:
- " I "
Expand Down Expand Up @@ -970,6 +995,17 @@ pylon:loupe:
result: pylon:loupe
category: equipment

pylon:bronze_loupe:
pattern:
- " C "
- "CGC"
- " C "
key:
C: pylon:bronze_ingot
G: pylon:loupe
result: pylon:bronze_loupe
category: equipment

pylon:fluid_strainer:
pattern:
- "CBC"
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/settings/bronze_loupe.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# how long it takes to scan an object
use-ticks: 10
# after a successful scan, how long should the item be on cooldown
cooldown-ticks: 10
6 changes: 6 additions & 0 deletions src/main/resources/settings/glass_breaker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
durability: 512
mining-speed: 9.0
mining-durability-damage: 1
attack-durability-damage: 1
attack-damage: 4.5
attack-speed: 1.2