Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package me.devnatan.inventoryframework.runtime.command
import me.devnatan.inventoryframework.ViewFrame
import me.devnatan.inventoryframework.runtime.view.Failing
import me.devnatan.inventoryframework.runtime.view.ScheduledView
import me.devnatan.inventoryframework.runtime.view.ScheduledViewAdvanced
import me.devnatan.inventoryframework.runtime.view.SimplePagination
import net.minestom.server.command.CommandSender
import net.minestom.server.command.builder.Command
Expand All @@ -20,6 +21,7 @@ class IFExampleCommand(
"failing" to Failing::class.java,
"simple-pagination" to SimplePagination::class.java,
"scheduled" to ScheduledView::class.java,
"scheduled-advanced" to ScheduledViewAdvanced::class.java,
)

private val arg: Argument<String> =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package me.devnatan.inventoryframework.runtime.view

import me.devnatan.inventoryframework.View
import me.devnatan.inventoryframework.ViewConfigBuilder
import me.devnatan.inventoryframework.context.Context
import me.devnatan.inventoryframework.context.RenderContext
import me.devnatan.inventoryframework.context.SlotClickContext
import me.devnatan.inventoryframework.runtime.ExampleUtil
import me.devnatan.inventoryframework.state.timerState
import net.minestom.server.item.Material
import kotlin.time.Duration.Companion.seconds

class ScheduledViewAdvanced : View() {
val counter = mutableState(0)
val timer = timerState(1.seconds)

override fun onInit(config: ViewConfigBuilder): Unit =
with(config) {
cancelOnClick()
size(3)
title("Simple Pagination")
layout(" ", " C ", "B ")
scheduleUpdate(timer)
}

override fun onFirstRender(render: RenderContext) {
render.layoutSlot('C').onRender {
it.item = ExampleUtil.displayItem(Material.STONE, counter.increment(it).toString())
}

render
.layoutSlot('B', ExampleUtil.displayItem(Material.PAPER, "Back"))
.displayIf(Context::canBack)
.onClick(SlotClickContext::back)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public class SamplePlugin extends JavaPlugin {
public void onEnable() {
ViewFrame viewFrame = ViewFrame.create(this)
.install(AnvilInputFeature.AnvilInput)
.with(new AnvilInputSample(), new Failing(), new SimplePagination(), new AutoUpdate())
.with(
new AnvilInputSample(),
new Failing(),
new SimplePagination(),
new AutoUpdate(),
new TimerSample())
.register();

IFExampleCommandExecutor command = new IFExampleCommandExecutor(viewFrame);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.devnatan.inventoryframework.runtime.commands;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.devnatan.inventoryframework.View;
Expand All @@ -9,6 +10,7 @@
import me.devnatan.inventoryframework.runtime.view.AutoUpdate;
import me.devnatan.inventoryframework.runtime.view.Failing;
import me.devnatan.inventoryframework.runtime.view.SimplePagination;
import me.devnatan.inventoryframework.runtime.view.TimerSample;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
Expand All @@ -19,11 +21,15 @@

public class IFExampleCommandExecutor implements CommandExecutor, TabCompleter {

private static final Map<String, Class<? extends View>> views = Map.of(
"anvil", AnvilInputSample.class,
"failing", Failing.class,
"simple-pagination", SimplePagination.class,
"auto-update", AutoUpdate.class);
private static final Map<String, Class<? extends View>> views = new HashMap<>();

static {
views.put("anvil", AnvilInputSample.class);
views.put("failing", Failing.class);
views.put("simple-pagination", SimplePagination.class);
views.put("auto-update", AutoUpdate.class);
views.put("timer", TimerSample.class);
}

private final ViewFrame viewFrame;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package me.devnatan.inventoryframework.runtime.view;

import me.devnatan.inventoryframework.View;
import me.devnatan.inventoryframework.ViewConfigBuilder;
import me.devnatan.inventoryframework.context.Context;
import me.devnatan.inventoryframework.context.RenderContext;
import me.devnatan.inventoryframework.context.SlotClickContext;
import me.devnatan.inventoryframework.context.SlotRenderContext;
import me.devnatan.inventoryframework.state.MutableIntState;
import me.devnatan.inventoryframework.state.timer.Timer;
import me.devnatan.inventoryframework.state.timer.TimerState;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;

public class TimerSample extends View {

private final MutableIntState countState = mutableState(0);
private final TimerState timerState = timerState(20);

@Override
public void onInit(@NotNull ViewConfigBuilder config) {
config.cancelOnClick().title("Timer (?)").scheduleUpdate(timerState);
}

@Override
public void onFirstRender(@NotNull RenderContext render) {
render.firstSlot()
.onRender(this::onClockItemRender)
.onClick(this::onClockItemClick)
.updateOnStateChange(timerState);

render.lastSlot()
.renderWith(() -> createIntervalItem(timerState.get(render)))
.onClick(this::onIntervalItemClicked)
.updateOnStateChange(timerState);
}

@Override
public void onUpdate(@NotNull Context update) {
final int count = countState.increment(update);
final String pause = timerState.get(update).isPaused() ? "paused" : "running";
update.updateTitleForPlayer(String.format("Timer (%d) [%b]", count, pause));
}

private void onIntervalItemClicked(SlotClickContext click) {
final Timer timer = timerState.get(click);
final long newInterval = (timer.currentInterval() + 1) % 20;

click.getPlayer().sendMessage(String.format(
"Timer interval changed from %d to %d ticks",
timer.currentInterval(), newInterval
));
timer.changeInterval(newInterval);
}

private static @NotNull ItemStack createIntervalItem(Timer timer) {
final long intervalInSeconds = Math.max(timer.currentInterval(), 1) / 20L; // ticks to seconds
final ItemStack item = new ItemStack(Material.ARROW, (int) intervalInSeconds);
final ItemMeta meta = item.getItemMeta();
meta.setDisplayName("Current clock interval");
meta.setLore(Arrays.asList("Initial: " + timer.initialInterval(), "Current: " + timer.currentInterval()));
item.setItemMeta(meta);

return item;
}

private void onClockItemRender(SlotRenderContext context) {
final Timer timer = timerState.get(context);

final ItemStack stack = new ItemStack(Material.CLOCK);
final ItemMeta meta = stack.getItemMeta();
meta.setDisplayName("Timer");
meta.setLore(Arrays.asList(timer.isPaused() ? "Click to unpause" : "Click to pause"));
stack.setItemMeta(meta);

context.setItem(stack);
}

private void onClockItemClick(SlotClickContext context) {
final Timer timer = timerState.get(context);
if (timer.pause()) {
context.getPlayer().sendMessage("Paused");
} else {
context.getPlayer().sendMessage("Unpaused");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import me.devnatan.inventoryframework.exception.InvalidLayoutException;
import me.devnatan.inventoryframework.state.timer.TimerState;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

Expand All @@ -31,6 +32,7 @@ public final class ViewConfigBuilder {
private String[] layout = null;
private final Set<ViewConfig.Modifier> modifiers = new HashSet<>();
private long updateIntervalInTicks, interactionDelayInMillis;
private TimerState updateIntervalState;
private boolean transitiveInitialData;

/**
Expand Down Expand Up @@ -200,6 +202,19 @@ public ViewConfigBuilder scheduleUpdate(long intervalInTicks) {
return this;
}

/**
* Schedules the view to update every fixed interval.
*
* @param timerState The
* @return This configuration builder.
* @see <a href="https://github.com/DevNatan/inventory-framework/wiki/scheduled-updates">Scheduled Updates on Wiki</a>
*/
@ApiStatus.Experimental
public ViewConfigBuilder scheduleUpdate(TimerState timerState) {
this.updateIntervalState = timerState;
return this;
}

/**
* Waits a fixed delay before any player interaction.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import me.devnatan.inventoryframework.context.IFSlotClickContext;
import me.devnatan.inventoryframework.context.IFSlotRenderContext;
import me.devnatan.inventoryframework.logging.Logger;
import me.devnatan.inventoryframework.state.timer.TimerState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -89,4 +90,6 @@ public abstract IFCloseContext createCloseContext(
public abstract boolean worksInCurrentPlatform();

public abstract Job scheduleJobInterval(@NotNull RootView root, long intervalInTicks, @NotNull Runnable execution);

public abstract TimerState createTimerState(long stateId, long intervalInTicks);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import me.devnatan.inventoryframework.component.PaginationValueConsumer;
import me.devnatan.inventoryframework.context.IFContext;
import me.devnatan.inventoryframework.context.IFOpenContext;
import me.devnatan.inventoryframework.state.timer.TimerState;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -173,6 +174,19 @@ public interface StateAccess<
*/
<T> MutableState<T> initialState(@NotNull String key);

/**
* Creates a new unmodifiable timer state.
*
* @param intervalInTicks Ticks to schedule the timer to run.
* <p>
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
* such API may be changed or may be removed completely in any further release. </i></b>
*
* @return A new unmodifiable timer state.
*/
@ApiStatus.Experimental
TimerState timerState(long intervalInTicks);

/**
* Creates a new immutable pagination with static data source.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.devnatan.inventoryframework.state.timer;

public interface Timer {

void loop();

long initialInterval();

long currentInterval();

void changeInterval(long interval);

boolean isPaused();

boolean pause();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.devnatan.inventoryframework.state.timer;

import me.devnatan.inventoryframework.state.State;

public interface TimerState extends State<Timer> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.devnatan.inventoryframework.state

import me.devnatan.inventoryframework.state.timer.TimerState
import kotlin.time.Duration

public fun StateAccess<*, *>.timerState(interval: Duration): TimerState = timerState(interval.inWholeSeconds / 20)
Loading
Loading