Skip to content

Commit

Permalink
feat(actions): WeatherChangeEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
PeyaPeyaPeyang committed Dec 16, 2024
1 parent b138b5b commit 048df4d
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
import org.bukkit.event.Event;
import org.bukkit.event.world.WorldEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.kunlab.scenamatica.action.AbstractAction;
import org.kunlab.scenamatica.bookkeeper.annotations.Admonition;
import org.kunlab.scenamatica.bookkeeper.annotations.Category;
import org.kunlab.scenamatica.bookkeeper.annotations.InputDoc;
import org.kunlab.scenamatica.bookkeeper.annotations.OutputDoc;
import org.kunlab.scenamatica.bookkeeper.annotations.OutputDocs;
import org.kunlab.scenamatica.bookkeeper.enums.ActionMethod;
import org.kunlab.scenamatica.bookkeeper.enums.AdmonitionType;
import org.kunlab.scenamatica.enums.ScenarioType;
import org.kunlab.scenamatica.exceptions.scenario.IllegalActionInputException;
import org.kunlab.scenamatica.interfaces.action.ActionContext;
import org.kunlab.scenamatica.interfaces.action.input.InputBoard;
import org.kunlab.scenamatica.interfaces.action.input.InputToken;
Expand All @@ -35,7 +40,14 @@ public abstract class AbstractWorldAction extends AbstractAction
@InputDoc(
name = "world",
description = "ワールドの名前です。",
type = String.class
type = String.class,
admonitions = {
@Admonition(
type = AdmonitionType.INFORMATION,
on = ActionMethod.EXECUTE,
content = "この項目を省略した場合は, 自動的にステージが選択されます。"
)
}
)
public static final InputToken<String> IN_WORLD = ofInput(
"world",
Expand All @@ -51,11 +63,20 @@ public boolean checkFired(@NotNull ActionContext ctxt, @NotNull Event event)
return false;

WorldEvent e = (WorldEvent) event;
return this.checkMatchedWorld(ctxt, e.getWorld());
}

protected boolean checkMatchedWorld(@NotNull ActionContext ctxt, @NotNull World world)
{
boolean result = ctxt.ifHasInput(
IN_WORLD, worldName ->
worldName.equals(world.getName())
|| ("world_" + worldName).equals(world.getName())
);

if (result)
this.makeOutputs(ctxt, world);

boolean result = ctxt.ifHasInput(IN_WORLD, world ->
world.equals(e.getWorld().getName())
|| ("world_" + world).equals(e.getWorld().getName()));
this.makeOutputs(ctxt, e.getWorld().getName());
return result;
}

Expand All @@ -65,7 +86,8 @@ public InputBoard getInputBoard(ScenarioType type)
return ofInputs(type, IN_WORLD);
}

protected World getWorld(ActionContext ctxt)
@Nullable
protected World getWorld(@NotNull ActionContext ctxt)
{
String name = ctxt.input(IN_WORLD);
World world = null;
Expand All @@ -78,12 +100,20 @@ protected World getWorld(ActionContext ctxt)
return null;
}

protected World getWorldNonNull(ActionContext ctxt)
@NotNull
protected World getWorldNonNull(@NotNull ActionContext ctxt)
{
if (!ctxt.hasInput(IN_WORLD))
return ctxt.getContext().getStage().getWorld();

return this.getWorld(ctxt);
World world = this.getWorld(ctxt);
if (world == null)
{
String inputWorldName = ctxt.orElseInput(IN_WORLD, () -> "**unset**");
throw new IllegalActionInputException(IN_WORLD, "Unable to find world: " + inputWorldName);
}

return world;
}

protected void makeOutputs(@NotNull ActionContext ctxt, @NotNull String worldName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void execute(@NotNull ActionContext ctxt)
public boolean checkConditionFulfilled(@NotNull ActionContext ctxt)
{
World world;
boolean result = (world = super.getWorld(ctxt)) != null;
boolean result = (world = super.getWorldNonNull(ctxt)) != null;
if (result)
this.makeOutputs(ctxt, world);
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class WorldUnloadAction extends AbstractWorldAction
@Override
public void execute(@NotNull ActionContext ctxt)
{
World world = super.getWorld(ctxt);
World world = super.getWorldNonNull(ctxt);

if (world == null)
throw new IllegalActionInputException(IN_WORLD, "Unable to find world: " + ctxt.input(IN_WORLD));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.kunlab.scenamatica.action.actions.base.world.weather;

import org.bukkit.event.Event;
import org.bukkit.event.weather.WeatherEvent;
import org.jetbrains.annotations.NotNull;
import org.kunlab.scenamatica.action.actions.base.world.AbstractWorldAction;
import org.kunlab.scenamatica.interfaces.action.ActionContext;

public abstract class AbstractWeatherAction extends AbstractWorldAction
{
@Override
public boolean checkFired(@NotNull ActionContext ctxt, @NotNull Event event)
{
if (!(event instanceof WeatherEvent))
return false;

WeatherEvent e = (WeatherEvent) event;
return this.checkMatchedWorld(ctxt, e.getWorld());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.kunlab.scenamatica.action.actions.base.world.weather;

import org.bukkit.World;
import org.bukkit.event.Event;
import org.bukkit.event.weather.WeatherChangeEvent;
import org.jetbrains.annotations.NotNull;
import org.kunlab.scenamatica.annotations.action.Action;
import org.kunlab.scenamatica.bookkeeper.annotations.ActionDoc;
import org.kunlab.scenamatica.bookkeeper.annotations.Admonition;
import org.kunlab.scenamatica.bookkeeper.annotations.InputDoc;
import org.kunlab.scenamatica.bookkeeper.annotations.OutputDoc;
import org.kunlab.scenamatica.bookkeeper.enums.ActionMethod;
import org.kunlab.scenamatica.bookkeeper.enums.AdmonitionType;
import org.kunlab.scenamatica.enums.ScenarioType;
import org.kunlab.scenamatica.interfaces.action.ActionContext;
import org.kunlab.scenamatica.interfaces.action.input.InputBoard;
import org.kunlab.scenamatica.interfaces.action.input.InputToken;
import org.kunlab.scenamatica.interfaces.action.types.Executable;
import org.kunlab.scenamatica.interfaces.action.types.Expectable;

import java.util.Collections;
import java.util.List;

@Action("weather_change")
@ActionDoc(
name = "天候の变化",
description = "ワールドの天候を変更します。",
events = WeatherChangeEvent.class,

executable = "ワールドの天候を変更します。",
expectable = "ワールドの天候が変わるまで待機します。",
requireable = ActionDoc.UNALLOWED,

outputs = {
@OutputDoc(
name = WeatherChangeAction.OUTPUT_RAINING,
description = "雨(または雪)が降っているかを出力します。",
type = Boolean.class
),
@OutputDoc(
name = WeatherChangeAction.OUTPUT_DURATION,
description = "その天候が続く期間(チック)を出力します。",
type = Integer.class,

admonitions = {
@Admonition(
type = AdmonitionType.INFORMATION,
content = "この値が `0` の場合は, その天候が永久に続くことを意味します。"
)
}
)
}
)
public class WeatherChangeAction extends AbstractWeatherAction
implements Executable, Expectable
{
public static final String OUTPUT_RAINING = "raining";
public static final String OUTPUT_DURATION = "duration";

@InputDoc(
name = "raining",
description = "雨(または雪)が降っているかどうかを指定します。",
type = Boolean.class,

admonitions = {
@Admonition(
type = AdmonitionType.INFORMATION,
on = ActionMethod.EXECUTE,
content = "この値を指定しない場合は, 今とは逆の天候に変更されます。\n" +
"雨(または雪)の場合は晴れに, 晴れの場合は雨(または雪)に変更されます。"
)
}
)
public static final InputToken<Boolean> IN_RAINING = ofInput("raining", Boolean.class);

@InputDoc(
name = "duration",
description = "その天候が続く期間(チック)を指定します。",
type = Integer.class,
availableFor = {ActionMethod.EXECUTE},

admonitions = {
@Admonition(
type = AdmonitionType.INFORMATION,
on = ActionMethod.EXECUTE,
content = "この値を指定しなかった場合は, 自動的に `0` が設定されます。"
),
@Admonition(
type = AdmonitionType.INFORMATION,
content = "この値が `0` の場合は, その天候が永久に続くことを意味します。"
)
}
)
public static final InputToken<Integer> IN_DURATION = ofInput("duration", Integer.class);

@Override
public List<Class<? extends Event>> getAttachingEvents()
{
return Collections.singletonList(WeatherChangeEvent.class);
}

@Override
public void execute(@NotNull ActionContext ctxt)
{
World world = this.getWorldNonNull(ctxt);

int duration = ctxt.orElseInput(IN_DURATION, () -> 0);
boolean changeToRaining;
if (ctxt.hasInput(IN_RAINING))
changeToRaining = ctxt.input(IN_RAINING);
else
changeToRaining = !world.hasStorm();

world.setStorm(changeToRaining);
world.setWeatherDuration(duration);
}

@Override
public boolean checkFired(@NotNull ActionContext ctxt, @NotNull Event event)
{
if (!(event instanceof WeatherChangeEvent))
return false;

WeatherChangeEvent e = (WeatherChangeEvent) event;
if (!super.checkMatchedWorld(ctxt, e.getWorld()))
return false;

return ctxt.ifHasInput(IN_RAINING, r -> e.toWeatherState() == r);
}

@Override
public InputBoard getInputBoard(ScenarioType type)
{
return super.getInputBoard(type)
.registerAll(IN_RAINING, IN_DURATION);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_weather_change_2
description: Testing WeatherChangeAction without duration works or not
on:
- type: on_load
- type: manual_dispatch

context:
stage:
type: FLAT

scenario:
- type: execute
action: weather_change
with:
raining: true
- type: expect
action: weather_change
with:
raining: true
duration: 0 # Default duration is 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_weather_change
description: Testing WeatherChangeAction works or not
on:
- type: on_load
- type: manual_dispatch

context:
stage:
type: FLAT

scenario:
- type: execute
action: weather_change
with:
raining: true
duration: 300
- type: expect
action: weather_change
with:
raining: true
duration: 300

0 comments on commit 048df4d

Please sign in to comment.