Compare commits

...

6 Commits

Author SHA1 Message Date
Lukas Rieger (Blue)
67706b4ea8
Apply spotless fixes 2024-05-20 21:57:54 +02:00
Lukas Rieger (Blue)
c91f991dc9
Merge branch 'wip/v5' into feat/events 2024-05-20 21:45:01 +02:00
Lukas Rieger (Blue)
d43a08c92b
Implement webserver event in cli 2024-05-20 21:40:32 +02:00
Lukas Rieger (Blue)
c0c22fc6ea
Implement freeze and visibillity events 2024-05-20 21:37:58 +02:00
Lukas Rieger (Blue)
648894ee26
More event wip 2024-05-20 21:33:14 +02:00
Lukas Rieger (Blue)
bd93071d02
First draft of events 2024-05-20 21:28:53 +02:00
9 changed files with 297 additions and 4 deletions

@ -1 +1 @@
Subproject commit ec977113495dacd6f2e24239015f4b94b305fc52
Subproject commit 93f7d722759cd14855764c54124d6745a41950df

View File

@ -28,7 +28,11 @@
import de.bluecolored.bluemap.api.BlueMapMap;
import de.bluecolored.bluemap.api.BlueMapWorld;
import de.bluecolored.bluemap.api.AssetStorage;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.api.events.Events;
import de.bluecolored.bluemap.api.events.MapEvent;
import de.bluecolored.bluemap.api.markers.MarkerSet;
import de.bluecolored.bluemap.common.events.EventUtils;
import de.bluecolored.bluemap.common.plugin.Plugin;
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
import de.bluecolored.bluemap.common.rendermanager.WorldRegionRenderTask;
@ -42,6 +46,9 @@
public class BlueMapMapImpl implements BlueMapMap {
private static final EventDispatcher<MapEvent.Freeze> MAP_FREEZE_EVENT_DISPATCHER = Events.getDispatcher(MapEvent.Freeze.class);
private static final EventDispatcher<MapEvent.Unfreeze> MAP_UNFREEZE_EVENT_DISPATCHER = Events.getDispatcher(MapEvent.Unfreeze.class);
private final WeakReference<Plugin> plugin;
private final WeakReference<BmMap> map;
private final BlueMapWorldImpl world;
@ -127,6 +134,9 @@ private synchronized void unfreeze() {
plugin.startWatchingMap(map);
plugin.getPluginState().getMapState(map).setUpdateEnabled(true);
plugin.getRenderManager().scheduleRenderTask(new MapUpdateTask(map));
// event
EventUtils.dispatchAsync(MAP_UNFREEZE_EVENT_DISPATCHER, new MapEvent.Unfreeze(this));
}
private synchronized void freeze() {
@ -143,6 +153,9 @@ private synchronized void freeze() {
return false;
});
// event
EventUtils.dispatchAsync(MAP_FREEZE_EVENT_DISPATCHER, new MapEvent.Freeze(this));
}
@Override

View File

@ -25,6 +25,10 @@
package de.bluecolored.bluemap.common.api;
import de.bluecolored.bluemap.api.WebApp;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.api.events.Events;
import de.bluecolored.bluemap.api.events.PlayerVisibilityChangeEvent;
import de.bluecolored.bluemap.common.events.EventUtils;
import de.bluecolored.bluemap.common.plugin.Plugin;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.util.FileHelper;
@ -42,6 +46,8 @@
public class WebAppImpl implements WebApp {
private static final Path IMAGE_ROOT_PATH = Path.of("data", "images");
private static final EventDispatcher<PlayerVisibilityChangeEvent> VISIBILITY_CHANGE_EVENT_DISPATCHER = Events.getDispatcher(PlayerVisibilityChangeEvent.class);
private final Plugin plugin;
public WebAppImpl(Plugin plugin) {
@ -60,6 +66,9 @@ public void setPlayerVisibility(UUID player, boolean visible) {
} else {
plugin.getPluginState().addHiddenPlayer(player);
}
// event
EventUtils.dispatchAsync(VISIBILITY_CHANGE_EVENT_DISPATCHER, new PlayerVisibilityChangeEvent(player, visible));
}
@Override

View File

@ -0,0 +1,49 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.common.events;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.logger.Logger;
public final class EventUtils {
private EventUtils() {
throw new UnsupportedOperationException("Utility class");
}
public static <T> void dispatch(EventDispatcher<T> dispatcher, T event) {
try {
dispatcher.dispatch(event);
} catch (Exception e) {
Logger.global.logError("A BlueMap addon threw an exception trying to process event: '" + event.getClass() + "'", e);
}
}
public static <T> void dispatchAsync(EventDispatcher<T> dispatcher, T event) {
BlueMap.THREAD_POOL.execute(() -> dispatch(dispatcher, event));
}
}

View File

@ -0,0 +1,120 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.common.events;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.api.events.Events;
import de.bluecolored.bluemap.common.BlueMapConfiguration;
import de.bluecolored.bluemap.common.plugin.Plugin;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public abstract class PluginLifecycleEvent {
@Getter
private final Plugin plugin;
public static abstract class Load extends PluginLifecycleEvent {
public Load(Plugin plugin) {
super(plugin);
}
public static class Pre extends Load {
public static final EventDispatcher<Pre> DISPATCHER = Events.getDispatcher(Pre.class);
public Pre(Plugin plugin) {
super(plugin);
}
}
public static class Configurations extends Load {
public static final EventDispatcher<Configurations> DISPATCHER = Events.getDispatcher(Configurations.class);
@Getter
private final BlueMapConfiguration configuration;
public Configurations(Plugin plugin, BlueMapConfiguration configuration) {
super(plugin);
this.configuration = configuration;
}
}
public static class Post extends Load {
public static final EventDispatcher<Post> DISPATCHER = Events.getDispatcher(Post.class);
public Post(Plugin plugin) {
super(plugin);
}
}
}
public static class Save extends PluginLifecycleEvent {
public static final EventDispatcher<Save> DISPATCHER = Events.getDispatcher(Save.class);
public Save(Plugin plugin) {
super(plugin);
}
}
public static abstract class Unload extends PluginLifecycleEvent {
public Unload(Plugin plugin) {
super(plugin);
}
public static class Pre extends Unload {
public static final EventDispatcher<Pre> DISPATCHER = Events.getDispatcher(Pre.class);
public Pre(Plugin plugin) {
super(plugin);
}
}
public static class Post extends Unload {
public static final EventDispatcher<Post> DISPATCHER = Events.getDispatcher(Post.class);
public Post(Plugin plugin) {
super(plugin);
}
}
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.common.events;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.api.events.Events;
import de.bluecolored.bluemap.common.web.RoutingRequestHandler;
import de.bluecolored.bluemap.common.web.http.HttpServer;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public class WebserverStartEvent {
public static final EventDispatcher<WebserverStartEvent> DISPATCHER = Events.getDispatcher(WebserverStartEvent.class);
private final HttpServer webserver;
private final RoutingRequestHandler requestHandler;
}

View File

@ -30,6 +30,10 @@
import de.bluecolored.bluemap.common.MissingResourcesException;
import de.bluecolored.bluemap.common.api.BlueMapAPIImpl;
import de.bluecolored.bluemap.common.config.*;
import de.bluecolored.bluemap.common.debug.StateDumper;
import de.bluecolored.bluemap.common.events.EventUtils;
import de.bluecolored.bluemap.common.events.PluginLifecycleEvent;
import de.bluecolored.bluemap.common.events.WebserverStartEvent;
import de.bluecolored.bluemap.common.live.LivePlayersDataSupplier;
import de.bluecolored.bluemap.common.plugin.skins.PlayerSkinUpdater;
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
@ -39,7 +43,6 @@
import de.bluecolored.bluemap.common.serverinterface.ServerWorld;
import de.bluecolored.bluemap.common.web.*;
import de.bluecolored.bluemap.common.web.http.HttpServer;
import de.bluecolored.bluemap.common.debug.StateDumper;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.map.BmMap;
import de.bluecolored.bluemap.core.metrics.Metrics;
@ -119,6 +122,9 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti
if (loaded) return;
unload(); //ensure nothing is left running (from a failed load or something)
// plugin pre load event
EventUtils.dispatch(PluginLifecycleEvent.Load.Pre.DISPATCHER, new PluginLifecycleEvent.Load.Pre(this));
//load configs
BlueMapConfigManager configManager = BlueMapConfigManager.builder()
.minecraftVersion(serverInterface.getMinecraftVersion())
@ -144,6 +150,12 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti
Logger.global.remove(DEBUG_FILE_LOG_NAME);
}
// plugin configuration event
EventUtils.dispatch(
PluginLifecycleEvent.Load.Configurations.DISPATCHER,
new PluginLifecycleEvent.Load.Configurations(this, configManager)
);
//load plugin state
try {
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
@ -231,6 +243,10 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti
webserverConfig.resolveIp(),
webserverConfig.getPort()
));
// webserver start event
EventUtils.dispatch(WebserverStartEvent.DISPATCHER, new WebserverStartEvent(webServer, routingRequestHandler));
webServer.start();
} catch (UnknownHostException ex) {
throw new ConfigurationException("BlueMap failed to resolve the ip in your webserver-config.\n" +
@ -374,6 +390,10 @@ public void run() {
//done
loaded = true;
// plugin post load event
EventUtils.dispatch(PluginLifecycleEvent.Load.Post.DISPATCHER, new PluginLifecycleEvent.Load.Post(this));
}
} catch (ConfigurationException ex) {
Logger.global.logWarning(ex.getFormattedExplanation());
@ -395,6 +415,9 @@ public void unload(boolean keepWebserver) {
try {
synchronized (this) {
// plugin pre unload event
EventUtils.dispatch(PluginLifecycleEvent.Unload.Pre.DISPATCHER, new PluginLifecycleEvent.Unload.Pre(this));
//disable api
if (api != null) api.unregister();
api = null;
@ -474,6 +497,10 @@ public void unload(boolean keepWebserver) {
//done
loaded = false;
// plugin post unload event
EventUtils.dispatch(PluginLifecycleEvent.Unload.Post.DISPATCHER, new PluginLifecycleEvent.Unload.Post(this));
}
} finally {
loadingLock.unlock();
@ -513,6 +540,9 @@ public void lightReload() throws IOException {
public synchronized void save() {
if (blueMap == null) return;
// plugin save event
EventUtils.dispatch(PluginLifecycleEvent.Save.DISPATCHER, new PluginLifecycleEvent.Save(this));
if (pluginState != null) {
try {
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()

View File

@ -39,7 +39,13 @@
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.tree.LiteralCommandNode;
import de.bluecolored.bluemap.api.BlueMapAPI;
import de.bluecolored.bluemap.api.events.EventDispatcher;
import de.bluecolored.bluemap.api.events.Events;
import de.bluecolored.bluemap.api.events.MapEvent;
import de.bluecolored.bluemap.common.config.ConfigurationException;
import de.bluecolored.bluemap.common.debug.StateDumper;
import de.bluecolored.bluemap.common.events.EventUtils;
import de.bluecolored.bluemap.common.plugin.Plugin;
import de.bluecolored.bluemap.common.plugin.PluginState;
import de.bluecolored.bluemap.common.plugin.text.Text;
@ -48,7 +54,6 @@
import de.bluecolored.bluemap.common.rendermanager.*;
import de.bluecolored.bluemap.common.serverinterface.CommandSource;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.common.debug.StateDumper;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.map.BmMap;
import de.bluecolored.bluemap.core.map.renderstate.TileInfoRegion;
@ -70,6 +75,9 @@
public class Commands<S> {
private static final EventDispatcher<MapEvent.Freeze> MAP_FREEZE_EVENT_DISPATCHER = Events.getDispatcher(MapEvent.Freeze.class);
private static final EventDispatcher<MapEvent.Unfreeze> MAP_UNFREEZE_EVENT_DISPATCHER = Events.getDispatcher(MapEvent.Unfreeze.class);
private final Plugin plugin;
private final CommandDispatcher<S> dispatcher;
private final Function<S, CommandSource> commandSourceInterface;
@ -719,6 +727,14 @@ public int freezeCommand(CommandContext<S> context) {
source.sendMessage(Text.of(TextColor.GRAY, "Any currently scheduled updates for this map have been cancelled."));
plugin.save();
// event
BlueMapAPI.getInstance()
.flatMap(api -> api.getMap(map.getId()))
.ifPresent(apiMap ->
EventUtils.dispatchAsync(MAP_FREEZE_EVENT_DISPATCHER, new MapEvent.Freeze(apiMap))
);
}, "BlueMap-Plugin-FreezeCommand").start();
} else {
source.sendMessage(Text.of(TextColor.RED, "This map is already frozen!"));
@ -751,6 +767,14 @@ public int unfreezeCommand(CommandContext<S> context) {
source.sendMessage(Text.of(TextColor.GREEN, "Map ", TextColor.WHITE, mapString, TextColor.GREEN, " is no longer frozen and will be automatically updated!"));
plugin.save();
// event
BlueMapAPI.getInstance()
.flatMap(api -> api.getMap(map.getId()))
.ifPresent(apiMap ->
EventUtils.dispatchAsync(MAP_UNFREEZE_EVENT_DISPATCHER, new MapEvent.Unfreeze(apiMap))
);
}, "BlueMap-Plugin-UnfreezeCommand").start();
} else {
source.sendMessage(Text.of(TextColor.RED, "This map is not frozen!"));

View File

@ -31,6 +31,8 @@
import de.bluecolored.bluemap.common.config.ConfigurationException;
import de.bluecolored.bluemap.common.config.CoreConfig;
import de.bluecolored.bluemap.common.config.WebserverConfig;
import de.bluecolored.bluemap.common.events.EventUtils;
import de.bluecolored.bluemap.common.events.WebserverStartEvent;
import de.bluecolored.bluemap.common.plugin.RegionFileWatchService;
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
import de.bluecolored.bluemap.common.rendermanager.RenderManager;
@ -236,12 +238,15 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc
);
try {
//noinspection resource
HttpServer webServer = new HttpServer(handler);
webServer.bind(new InetSocketAddress(
config.resolveIp(),
config.getPort()
));
// webserver start event
EventUtils.dispatch(WebserverStartEvent.DISPATCHER, new WebserverStartEvent(webServer, routingRequestHandler));
webServer.start();
} catch (UnknownHostException ex) {
throw new ConfigurationException("BlueMap failed to resolve the ip in your webserver-config.\n" +