-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a new hook system (right now only with Hologram support)
My plans with this hook system are to make it easier to understand and maintain – Hopefully it is also more flexible Hooks now have a dedicated activation-life-cycle – I think this allows it to contain all the logic to do what it needs to do but also provide some helper methods like `#canBeActivated`. The activation should be used by the hooks to reduce the memory and performancec impact when not used. The de-activation also allows hooks to clean up themselves and not rely on the plugins used by the hook or the plugin using the hook to clean up. For example: You can see that the `DecentHologramsHook` has few class variables and they are kept as small as possible and reasonable when not activated. In `#deactivate` I call `#removeAll` to remove all holograms that still exist and I call `ArrayList#trimToSize` to reduce it's size again. This has a similar effect to setting the class varaible null or to a new List but with this I can make that field *final*. The exact implementation details and capabilities vary on the third-party plugins being supported by hooks, so it needs to be flexible and easy to understand, so we can easily add support for more plugins and especially new plugin categories like Maps (dynmap, BlueMap, PlexMap, ...).
- Loading branch information
Showing
10 changed files
with
456 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
Core/src/main/java/com/craftaro/core/hooks/BaseHookRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package com.craftaro.core.hooks; | ||
|
||
import com.craftaro.core.hooks.holograms.Hook; | ||
import org.bukkit.plugin.Plugin; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* This hook registry makes use of priorities to automatically activate the highest priority hook that is available if no hook has been activated programmatically. | ||
*/ | ||
public abstract class BaseHookRegistry<T extends Hook> extends HookRegistry<T> { | ||
private final Plugin plugin; | ||
|
||
private final Map<T, Integer> hooksWithPriority = new HashMap<>(); | ||
protected T activeHook = null; | ||
|
||
public BaseHookRegistry(Plugin plugin) { | ||
this.plugin = plugin; | ||
} | ||
|
||
public abstract void registerDefaultHooks(); | ||
|
||
public Optional<T> getActive() { | ||
if (this.activeHook == null) { | ||
T hook = findFirstAvailableHook(); | ||
if (hook != null) { | ||
setActive(hook); | ||
this.plugin.getLogger().info("Activated hook '" + hook.getName() + "'"); | ||
} | ||
|
||
checkDependenciesOfAllHooksAndLogMissingOnes(); | ||
} | ||
return Optional.ofNullable(this.activeHook); | ||
} | ||
|
||
public void setActive(@Nullable T hook) { | ||
if (this.activeHook == hook) { | ||
return; | ||
} | ||
|
||
if (this.activeHook != null) { | ||
this.activeHook.deactivate(); | ||
} | ||
|
||
this.activeHook = hook; | ||
if (this.activeHook != null) { | ||
this.activeHook.activate(this.plugin); | ||
} | ||
} | ||
|
||
@Override | ||
public @Nullable T get(String name) { | ||
for (T hook : this.hooksWithPriority.keySet()) { | ||
if (hook.getName().equalsIgnoreCase(name)) { | ||
return hook; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public @NotNull List<T> getAll() { | ||
// Use List.copyOf() when we upgrade to Java 10+ | ||
return Collections.unmodifiableList(new ArrayList<>(this.hooksWithPriority.keySet())); | ||
} | ||
|
||
@Override | ||
public @NotNull List<String> getAllNames() { | ||
return this.hooksWithPriority | ||
.keySet() | ||
.stream() | ||
.map(Hook::getName) | ||
.sorted() | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Override | ||
public void register(@NotNull T hook) { | ||
register(hook, 0); | ||
} | ||
|
||
/** | ||
* @see HookPriority | ||
*/ | ||
public void register(@NotNull T hook, int priority) { | ||
if (get(hook.getName()) != null) { | ||
throw new IllegalArgumentException("Hook with name '" + hook.getName() + "' already registered"); | ||
} | ||
this.hooksWithPriority.put(hook, priority); | ||
} | ||
|
||
@Override | ||
public void unregister(@NotNull T hook) { | ||
if (this.activeHook == hook) { | ||
this.activeHook = null; | ||
hook.deactivate(); | ||
} | ||
this.hooksWithPriority.remove(hook); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
this.hooksWithPriority.clear(); | ||
} | ||
|
||
protected @Nullable T findFirstAvailableHook() { | ||
return this.hooksWithPriority | ||
.entrySet() | ||
.stream() | ||
.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())) | ||
.filter((entry) -> entry.getKey().canBeActivated()) | ||
.map(Map.Entry::getKey) | ||
.findFirst() | ||
.orElse(null); | ||
} | ||
|
||
protected void checkDependenciesOfAllHooksAndLogMissingOnes() { | ||
List<String> missingDependencies = new ArrayList<>(0); | ||
|
||
for (T hook : getAll()) { | ||
for (String pluginName : hook.getPluginDependencies()) { | ||
if (this.plugin.getDescription().getDepend().contains(pluginName)) { | ||
continue; | ||
} | ||
if (this.plugin.getDescription().getSoftDepend().contains(pluginName)) { | ||
continue; | ||
} | ||
|
||
missingDependencies.add(pluginName); | ||
} | ||
} | ||
|
||
if (!missingDependencies.isEmpty()) { | ||
this.plugin.getLogger().warning("Nag author(s): Plugin accesses hooks that it does not declare dependance on: " + String.join(", ", missingDependencies)); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
Core/src/main/java/com/craftaro/core/hooks/HookPriority.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.craftaro.core.hooks; | ||
|
||
/** | ||
* Some handy constants for hook priorities intended to be used in | ||
* {@link BaseHookRegistry#register(com.craftaro.core.hooks.holograms.Hook, int)} | ||
*/ | ||
public final class HookPriority { | ||
public static final int HIGHEST = 100; | ||
public static final int HIGHER = 50; | ||
public static final int HIGH = 10; | ||
public static final int NORMAL = 0; | ||
public static final int LOW = -10; | ||
public static final int LOWER = -50; | ||
|
||
private HookPriority() { | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
Core/src/main/java/com/craftaro/core/hooks/HookRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.craftaro.core.hooks; | ||
|
||
import com.craftaro.core.hooks.holograms.Hook; | ||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
public abstract class HookRegistry<T extends Hook> { | ||
public abstract Optional<T> getActive(); | ||
|
||
public abstract void setActive(@Nullable T hook); | ||
|
||
public abstract @NotNull List<String> getAllNames(); | ||
|
||
public abstract void register(@NotNull T hook); | ||
|
||
public abstract void unregister(@NotNull T hook); | ||
|
||
public abstract void clear(); | ||
|
||
@ApiStatus.Internal | ||
public abstract @Nullable T get(String name); | ||
|
||
@ApiStatus.Internal | ||
public abstract @NotNull List<T> getAll(); | ||
} |
36 changes: 36 additions & 0 deletions
36
Core/src/main/java/com/craftaro/core/hooks/HookRegistryManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.craftaro.core.hooks; | ||
|
||
import com.craftaro.core.hooks.hologram.HologramHook; | ||
import com.craftaro.core.hooks.hologram.HologramHookRegistry; | ||
import org.bukkit.plugin.Plugin; | ||
|
||
import java.util.Optional; | ||
|
||
public class HookRegistryManager { | ||
private final Plugin plugin; | ||
|
||
private HologramHookRegistry hologramRegistry; | ||
|
||
public HookRegistryManager(Plugin plugin) { | ||
this.plugin = plugin; | ||
} | ||
|
||
public Optional<HologramHook> holograms() { | ||
return getHologramRegistry().getActive(); | ||
} | ||
|
||
public HologramHookRegistry getHologramRegistry() { | ||
if (this.hologramRegistry == null) { | ||
this.hologramRegistry = new HologramHookRegistry(this.plugin); | ||
this.hologramRegistry.registerDefaultHooks(); | ||
} | ||
|
||
return this.hologramRegistry; | ||
} | ||
|
||
public void deactivateAllActiveHooks() { | ||
if (this.hologramRegistry != null) { | ||
this.hologramRegistry.setActive(null); | ||
} | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
Core/src/main/java/com/craftaro/core/hooks/hologram/HologramHook.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package com.craftaro.core.hooks.hologram; | ||
|
||
import com.craftaro.core.hooks.holograms.Hook; | ||
import com.craftaro.core.utils.LocationUtils; | ||
import org.bukkit.Location; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public abstract class HologramHook implements Hook { | ||
public abstract boolean exists(@NotNull String id); | ||
|
||
/** | ||
* @throws IllegalStateException if the hologram already exists | ||
* @see #createOrUpdateText(String, Location, List) | ||
*/ | ||
public abstract void create(@NotNull String id, @NotNull Location location, @NotNull List<String> lines); | ||
|
||
/** | ||
* @throws IllegalStateException if the hologram does not exist | ||
*/ | ||
public abstract void update(@NotNull String id, @NotNull List<String> lines); | ||
|
||
public abstract void updateBulk(@NotNull Map<String, List<String>> hologramData); | ||
|
||
public abstract void remove(@NotNull String id); | ||
|
||
public abstract void removeAll(); | ||
|
||
/** | ||
* @see #create(String, Location, List) | ||
*/ | ||
public void create(@NotNull String id, @NotNull Location location, @NotNull String text) { | ||
create(id, location, Collections.singletonList(text)); | ||
} | ||
|
||
public void createOrUpdateText(@NotNull String id, @NotNull Location location, @NotNull List<String> lines) { | ||
if (exists(id)) { | ||
update(id, lines); | ||
return; | ||
} | ||
|
||
create(id, location, lines); | ||
} | ||
|
||
/** | ||
* @see #createOrUpdateText(String, Location, List) | ||
*/ | ||
public void createOrUpdateText(@NotNull String id, @NotNull Location location, @NotNull String text) { | ||
createOrUpdateText(id, location, Collections.singletonList(text)); | ||
} | ||
|
||
/** | ||
* @see #update(String, List) | ||
*/ | ||
public void update(@NotNull String id, @NotNull String text) { | ||
update(id, Collections.singletonList(text)); | ||
} | ||
|
||
protected double getYOffset() { | ||
return 1.5; | ||
} | ||
|
||
protected @NotNull Location getNormalizedLocation(Location location) { | ||
return LocationUtils | ||
.getCenter(location) | ||
.add(0, getYOffset(), 0); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
Core/src/main/java/com/craftaro/core/hooks/hologram/HologramHookRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.craftaro.core.hooks.hologram; | ||
|
||
import com.craftaro.core.hooks.BaseHookRegistry; | ||
import com.craftaro.core.hooks.HookPriority; | ||
import com.craftaro.core.hooks.hologram.adapter.DecentHologramsHook; | ||
import org.bukkit.plugin.Plugin; | ||
|
||
public class HologramHookRegistry extends BaseHookRegistry<HologramHook> { | ||
public HologramHookRegistry(Plugin plugin) { | ||
super(plugin); | ||
} | ||
|
||
@Override | ||
public void registerDefaultHooks() { | ||
register(new DecentHologramsHook(), HookPriority.HIGH); | ||
} | ||
} |
Oops, something went wrong.