Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal Events API #5552

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7e806f8
Combine activity events and add unload event
APickledWalrus Mar 25, 2023
d2c75fc
Add global script events
APickledWalrus Mar 25, 2023
18aae27
Add EventRegister API
APickledWalrus Mar 25, 2023
82ac723
Javadoc improvements
APickledWalrus Mar 25, 2023
a01b0bb
Merge branch 'master' into feature/script-event-updates
APickledWalrus Jul 19, 2023
254a799
Refactoring
APickledWalrus Jul 19, 2023
c391d9b
Cleanup and additional refactoring
APickledWalrus Jul 19, 2023
9312100
Add ScriptLoadEvent and ScriptInitEvent
APickledWalrus Jul 19, 2023
4df1644
Add PreScriptInitEvent
APickledWalrus Jul 19, 2023
c24ca0a
Minor javadoc corrections
APickledWalrus Jul 19, 2023
8759556
Oopsie! add license headers
APickledWalrus Jul 19, 2023
e9d8810
Requested formatting changes
APickledWalrus Jul 19, 2023
efd6362
Merge branch 'dev/feature' into feature/script-event-updates
APickledWalrus Dec 19, 2023
a5cde98
Javadoc tweaks
APickledWalrus Dec 19, 2023
f32e529
Merge branch 'dev/feature' into feature/script-event-updates
APickledWalrus Jul 14, 2024
fde7dfe
Fix script load triggering
APickledWalrus Jul 14, 2024
af02f81
Remove license headers
APickledWalrus Jul 14, 2024
478276b
Update class and method names
APickledWalrus Jul 14, 2024
48272bd
Formatting tweaks
APickledWalrus Jul 14, 2024
3d11e8b
Refactor event classes into appropriate locations
APickledWalrus Jul 14, 2024
7bac33a
Merge branch 'dev/feature' into feature/script-event-updates
APickledWalrus Sep 22, 2024
50128e9
Add Event parent class for type restriction
APickledWalrus Sep 22, 2024
37bb18d
Merge branch 'dev/feature' into feature/script-event-updates
sovdeeth Oct 13, 2024
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
24 changes: 24 additions & 0 deletions src/main/java/ch/njol/skript/ScriptLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;
import org.skriptlang.skript.api.event.EventRegister;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.script.ScriptLoaderEvent;
import org.skriptlang.skript.lang.structure.Structure;

import java.io.File;
Expand Down Expand Up @@ -804,6 +806,13 @@ public static ScriptInfo unloadScripts(Set<Script> scripts) {
// initial unload stage
for (Script script : scripts) {
parser.setActive(script);

// trigger unload event before beginning
eventRegister.getEvents(ScriptLoaderEvent.ScriptUnloadEvent.class)
.forEach(eventHandler -> eventHandler.onUnload(parser, script));
script.getEventRegister().getEvents(ScriptLoaderEvent.ScriptUnloadEvent.class)
.forEach(eventHandler -> eventHandler.onUnload(parser, script));

for (Structure structure : script.getStructures())
structure.unload();
}
Expand Down Expand Up @@ -999,6 +1008,21 @@ public static FileFilter getDisabledScriptsFilter() {
return disabledScriptFilter;
}

/*
* Global Script Event API
*/

// ScriptLoader Events

private static final EventRegister<ScriptLoaderEvent> eventRegister = new EventRegister<>();

/**
* @return An EventRegister for the ScriptLoader's events.
*/
public static EventRegister<ScriptLoaderEvent> getEventRegister() {
return eventRegister;
}

/*
* Deprecated stuff
*
Expand Down
26 changes: 16 additions & 10 deletions src/main/java/ch/njol/skript/lang/parser/ParserInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.script.ScriptEvent;
import org.skriptlang.skript.lang.script.ScriptLoaderEvent;
import org.skriptlang.skript.lang.structure.Structure;

import java.io.File;
Expand Down Expand Up @@ -64,11 +64,11 @@ public static ParserInstance get() {
*/
public void setInactive() {
this.isActive = false;
setCurrentScript((Script) null);
setCurrentStructure(null);
deleteCurrentEvent();
getCurrentSections().clear();
setNode(null);
setCurrentScript((Script) null);
}

/**
Expand All @@ -77,8 +77,8 @@ public void setInactive() {
*/
public void setActive(Script script) {
this.isActive = true;
setCurrentScript(script);
setNode(null);
setCurrentScript(script);
}

/**
Expand Down Expand Up @@ -112,12 +112,18 @@ private void setCurrentScript(@Nullable Script currentScript) {
);

// "Script" events
if (previous != null)
previous.getEvents(ScriptEvent.ScriptInactiveEvent.class)
.forEach(eventHandler -> eventHandler.onInactive(currentScript));
if (currentScript != null)
currentScript.getEvents(ScriptEvent.ScriptActiveEvent.class)
.forEach(eventHandler -> eventHandler.onActive(previous));
if (previous != null) { // the 'previous' script is becoming inactive
ScriptLoader.getEventRegister().getEvents(ScriptLoaderEvent.ScriptActivityChangeEvent.class)
.forEach(eventHandler -> eventHandler.onActivityChange(this, previous, false, currentScript));
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
previous.getEventRegister().getEvents(ScriptLoaderEvent.ScriptActivityChangeEvent.class)
.forEach(eventHandler -> eventHandler.onActivityChange(this, previous, false, currentScript));
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
}
if (currentScript != null) { // the 'currentScript' is becoming active
ScriptLoader.getEventRegister().getEvents(ScriptLoaderEvent.ScriptActivityChangeEvent.class)
.forEach(eventHandler -> eventHandler.onActivityChange(this, currentScript, true, previous));
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
currentScript.getEventRegister().getEvents(ScriptLoaderEvent.ScriptActivityChangeEvent.class)
.forEach(eventHandler -> eventHandler.onActivityChange(this, currentScript, true, previous));
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
}
}

/**
Expand Down Expand Up @@ -421,7 +427,7 @@ protected final ParserInstance getParser() {
}

/**
* @deprecated See {@link ScriptEvent}.
* @deprecated See {@link ScriptLoaderEvent}.
*/
@Deprecated
public void onCurrentScriptChange(@Nullable Config currentScript) { }
Expand Down
85 changes: 85 additions & 0 deletions src/main/java/org/skriptlang/skript/api/event/EventRegister.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package org.skriptlang.skript.api.event;

import org.jetbrains.annotations.Unmodifiable;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
* EventRegisters are generic containers for registering events.
* They are used across Skript to provide additional API with consistent organization.
* @param <E> The umbrella class representing the type of events this register will hold.
*/
public class EventRegister<E> {

private final Set<E> events = new HashSet<>(5);

/**
* Registers the provided event with this register.
* @param event The event to register.
*/
public void registerEvent(E event) {
events.add(event);
}

/**
* Registers the provided event with.
* @param eventType The type of event being registered.
* This is useful for registering an event that is a {@link FunctionalInterface} using a lambda.
* @param event The event to register.
*/
public <T extends E> void registerEvent(Class<T> eventType, T event) {
events.add(event);
}

/**
* Unregisters the provided event.
* @param event The event to unregister.
*/
public void unregisterEvent(E event) {
events.remove(event);
}

/**
* @return An unmodifiable set of this register's events.
*/
@Unmodifiable
public Set<E> getEvents() {
return Collections.unmodifiableSet(events);
}

/**
* @param type The type of events to get.
* @return An unmodifiable subset (of the specified type) of this register's events
*/
@Unmodifiable
@SuppressWarnings("unchecked")
public <T extends E> Set<T> getEvents(Class<T> type) {
return Collections.unmodifiableSet(
(Set<T>) events.stream()
.filter(event -> type.isAssignableFrom(event.getClass()))
.collect(Collectors.toSet())
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
);
}

}
23 changes: 23 additions & 0 deletions src/main/java/org/skriptlang/skript/api/event/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
@NonNullByDefault({DefaultLocation.PARAMETER, DefaultLocation.RETURN_TYPE, DefaultLocation.FIELD})
package org.skriptlang.skript.api.event;

import org.eclipse.jdt.annotation.DefaultLocation;
import org.eclipse.jdt.annotation.NonNullByDefault;
50 changes: 5 additions & 45 deletions src/main/java/org/skriptlang/skript/lang/script/Script.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Unmodifiable;
import org.skriptlang.skript.api.event.EventRegister;
import org.skriptlang.skript.lang.structure.Structure;

import java.util.Collections;
Expand All @@ -31,7 +32,6 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
* Scripts are the primary container of all code.
Expand Down Expand Up @@ -150,53 +150,13 @@ public <Value extends ScriptData> Value getData(Class<? extends Value> dataType,

// Script Events

private final Set<ScriptEvent> eventHandlers = new HashSet<>(5);
private final EventRegister<ScriptEvent> eventRegister = new EventRegister<>();

/**
* Adds the provided event to this Script.
* @param event The event to add.
* @return An EventRegister for this Script's events.
*/
public void registerEvent(ScriptEvent event) {
eventHandlers.add(event);
}

/**
* Adds the provided event to this Script.
* @param eventType The type of event being added. This is useful for registering the event through lambdas.
* @param event The event to add.
*/
public <T extends ScriptEvent> void registerEvent(Class<T> eventType, T event) {
eventHandlers.add(event);
}

/**
* Removes the provided event from this Script.
* @param event The event to remove.
*/
public void unregisterEvent(ScriptEvent event) {
eventHandlers.remove(event);
}

/**
* @return An unmodifiable set of all events.
*/
@Unmodifiable
public Set<ScriptEvent> getEvents() {
return Collections.unmodifiableSet(eventHandlers);
}

/**
* @param type The type of events to get.
* @return An unmodifiable set of all events of the specified type.
*/
@Unmodifiable
@SuppressWarnings("unchecked")
public <T extends ScriptEvent> Set<T> getEvents(Class<T> type) {
return Collections.unmodifiableSet(
(Set<T>) eventHandlers.stream()
.filter(event -> type.isAssignableFrom(event.getClass()))
.collect(Collectors.toSet())
);
public EventRegister<ScriptEvent> getEventRegister() {
return eventRegister;
}

}
40 changes: 3 additions & 37 deletions src/main/java/org/skriptlang/skript/lang/script/ScriptEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,13 @@
*/
package org.skriptlang.skript.lang.script;

import ch.njol.skript.lang.parser.ParserInstance;
import org.eclipse.jdt.annotation.Nullable;

/**
* A ScriptEvent is used for listening to and performing actions for different Script events.
* @see Script#registerEvent(ScriptEvent)
* A ScriptEvent is used for listening to and performing actions for different Script events on a Script-specific scale.
* Note that some {@link ScriptLoaderEvent}s may be used on a Script-specific scale too.
* @see Script#getEventRegister()
*/
public interface ScriptEvent {

/**
* A ScriptEvent that is called when a Script is made active in a {@link ParserInstance}.
*/
@FunctionalInterface
interface ScriptActiveEvent extends ScriptEvent {

/**
* Called when this Script is made active in a {@link ParserInstance}.
*
* @param oldScript The Script that was just made inactive.
* Null if the {@link ParserInstance} handling this Script
* was not {@link ParserInstance#isActive()} (it is becoming active).
*/
void onActive(@Nullable Script oldScript);

}

/**
* A ScriptEvent that is called when a Script is made inactive in a {@link ParserInstance}.
*/
@FunctionalInterface
interface ScriptInactiveEvent extends ScriptEvent {

/**
* Called when this Script is made inactive in a {@link ParserInstance}.
*
* @param newScript The Script that will be made active after this one is completely inactive.
* Null if the {@link ParserInstance} handling this Script
* will not be {@link ParserInstance#isActive()} (will become inactive).
*/
void onInactive(@Nullable Script newScript);

}

}
Loading