feat(module): Add DemoModule with audio playback functionality and module service integration

This commit is contained in:
extio-de
2025-12-24 21:32:15 +01:00
parent eb8d08f418
commit b07f957041
7 changed files with 87 additions and 22 deletions

BIN
data/audio/race.ogg Normal file

Binary file not shown.

View File

@@ -12,10 +12,12 @@ public abstract class AbstractModule {
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractModule.class); protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractModule.class);
private ModuleService moduleService;
public AbstractModule() { public AbstractModule() {
} }
public void onLoad() { public void onLoad() {
} }
@@ -39,7 +41,15 @@ public abstract class AbstractModule {
public void run() { public void run() {
} }
public ModuleService getModuleService() {
return moduleService;
}
public void setModuleService(ModuleService moduleService) {
this.moduleService = moduleService;
}
@Override @Override
public String toString() { public String toString() {
return this.getClass().getSimpleName(); return this.getClass().getSimpleName();

View File

@@ -15,7 +15,7 @@ public class ModuleServiceAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
ModuleService moduleManager(final List<AbstractModule> initialModules, final RendererWorkingSet rendererWorkingSet) { ModuleService moduleService(final List<AbstractModule> initialModules, final RendererWorkingSet rendererWorkingSet) {
return new ModuleServiceImpl(initialModules, rendererWorkingSet); return new ModuleServiceImpl(initialModules, rendererWorkingSet);
} }

View File

@@ -85,8 +85,6 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
} }
} }
LOGGER.debug("Loading module " + clazz.getName());
try { try {
final AbstractModule module = AbstractModule.class.cast(clazz.getDeclaredConstructor().newInstance()); final AbstractModule module = AbstractModule.class.cast(clazz.getDeclaredConstructor().newInstance());
this.load(module); this.load(module);
@@ -97,12 +95,14 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
} }
private void load(final AbstractModule module) { private void load(final AbstractModule module) {
this.invokeSafe(module, m -> m.onLoad()); module.setModuleService(this);
this.modulesAll.add(module); this.modulesAll.add(module);
this.sortModules(this.modulesAll); this.sortModules(this.modulesAll);
synchronized (this.modulesAll) { synchronized (this.modulesAll) {
this.modulesAllView = List.copyOf(this.modulesAll); this.modulesAllView = List.copyOf(this.modulesAll);
} }
LOGGER.info("Loaded module " + module.getClass().getName());
this.invokeSafe(module, m -> m.onLoad());
} }
@Override @Override
@@ -130,7 +130,7 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
this.rendererWorkingSet.clear(clientModule.getClass()); this.rendererWorkingSet.clear(clientModule.getClass());
} }
LOGGER.debug("Unloaded module " + clazz.getName()); LOGGER.info("Unloaded module " + clazz.getName());
} }
catch (final Exception e) { catch (final Exception e) {
LOGGER.error("Error unloading module " + clazz.getName(), e); LOGGER.error("Error unloading module " + clazz.getName(), e);
@@ -158,15 +158,14 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
if (module instanceof final AbstractClientModule clientModule) { if (module instanceof final AbstractClientModule clientModule) {
this.changeDisplayState(clientModule.getClass(), false); this.changeDisplayState(clientModule.getClass(), false);
} }
this.invokeSafe(module, AbstractModule::onDeactivate);
this.modulesActive.remove(module); this.modulesActive.remove(module);
this.sortModules(this.modulesActive); this.sortModules(this.modulesActive);
synchronized (this.modulesActive) { synchronized (this.modulesActive) {
this.modulesActiveView = List.copyOf(this.modulesActive); this.modulesActiveView = List.copyOf(this.modulesActive);
this.modulesActiveClientModulesView = this.modulesActive.stream() this.modulesActiveClientModulesView = this.modulesActive.stream()
.filter(m -> m instanceof AbstractClientModule) .filter(m -> m instanceof AbstractClientModule)
.map(m -> (AbstractClientModule) m) .map(m -> (AbstractClientModule) m)
.toList(); .toList();
} }
if (module instanceof final AbstractClientModule clientModule) { if (module instanceof final AbstractClientModule clientModule) {
this.rendererWorkingSet.clear(clientModule.getClass()); this.rendererWorkingSet.clear(clientModule.getClass());
@@ -179,8 +178,9 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
} }
} }
} }
this.invokeSafe(module, AbstractModule::onDeactivate);
LOGGER.debug("Deactivated " + clazz.getName()); LOGGER.info("Deactivated " + clazz.getName());
} }
}, () -> { }, () -> {
if (active) { if (active) {
@@ -189,7 +189,6 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
.filter(module -> clazz.isAssignableFrom(module.getClass())) .filter(module -> clazz.isAssignableFrom(module.getClass()))
.findFirst() .findFirst()
.ifPresent(module -> { .ifPresent(module -> {
this.invokeSafe(module, AbstractModule::onActivate);
if (module instanceof final AbstractClientModule clientModule && clientModule.isAlwaysDisplay()) { if (module instanceof final AbstractClientModule clientModule && clientModule.isAlwaysDisplay()) {
this.changeDisplayState(clientModule.getClass(), true); this.changeDisplayState(clientModule.getClass(), true);
} }
@@ -198,9 +197,9 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
synchronized (this.modulesActive) { synchronized (this.modulesActive) {
this.modulesActiveView = List.copyOf(this.modulesActive); this.modulesActiveView = List.copyOf(this.modulesActive);
this.modulesActiveClientModulesView = this.modulesActive.stream() this.modulesActiveClientModulesView = this.modulesActive.stream()
.filter(m -> m instanceof AbstractClientModule) .filter(m -> m instanceof AbstractClientModule)
.map(m -> (AbstractClientModule) m) .map(m -> (AbstractClientModule) m)
.toList(); .toList();
} }
synchronized (this.executorCallbackMap) { synchronized (this.executorCallbackMap) {
final var subscriptions = module.executorCallbackSubscriptions(); final var subscriptions = module.executorCallbackSubscriptions();
@@ -210,8 +209,9 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
} }
} }
} }
this.invokeSafe(module, AbstractModule::onActivate);
LOGGER.debug("Activated " + clazz.getName()); LOGGER.info("Activated " + clazz.getName());
}); });
} }
} }
@@ -249,11 +249,13 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService {
if (doDisplay && !curDisplayed) { if (doDisplay && !curDisplayed) {
this.modulesDisplayed.add(clientModule); this.modulesDisplayed.add(clientModule);
clientModule.setDisplayed(true); clientModule.setDisplayed(true);
LOGGER.info("Displayed {}", clazz.getName());
this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onShow()); this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onShow());
} }
else if (!doDisplay && curDisplayed) { else if (!doDisplay && curDisplayed) {
clientModule.setDisplayed(false); clientModule.setDisplayed(false);
this.modulesDisplayed.removeIf(mod -> clazz.isAssignableFrom(mod.getClass())); this.modulesDisplayed.removeIf(mod -> clazz.isAssignableFrom(mod.getClass()));
LOGGER.info("Hidden {}", clazz.getName());
this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onHide()); this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onHide());
} }
this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed); this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed);

View File

@@ -6,7 +6,6 @@ import java.util.UUID;
/** /**
* Random implementation using the Xorshift+ (xorshift128plus) algorithm * Random implementation using the Xorshift+ (xorshift128plus) algorithm
*/ */
@SuppressWarnings("serial")
public final class XorShift128Random extends Random { public final class XorShift128Random extends Random {
private long state0; private long state0;

View File

@@ -1,13 +1,17 @@
package de.extio.game_engine; package de.extio.game_engine;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
import de.extio.game_engine.demo.DemoModule;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
public class Main { public class Main {
public static void main(final String[] args) { public static void main(final String[] args) {
@@ -28,4 +32,22 @@ public class Main {
builder.run(args); builder.run(args);
} }
@Configuration
@Conditional(de.extio.game_engine.Main.StandaloneConfig.StandaloneCondition.class)
static class StandaloneConfig {
@Bean
DemoModule demoModule() {
return new DemoModule();
}
static class StandaloneCondition implements Condition {
@Override
public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
final String env = context.getEnvironment().getProperty("game-engine.env");
return "standalone".equals(env);
}
}
}
} }

View File

@@ -0,0 +1,32 @@
package de.extio.game_engine.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import de.extio.game_engine.audio.AudioController;
import de.extio.game_engine.module.AbstractClientModule;
import de.extio.game_engine.resource.StaticResource;
public class DemoModule extends AbstractClientModule {
@Autowired
private AudioController audioController;
@Override
public void onLoad() {
this.getModuleService().changeActiveState(this.getClass(), true);
this.getModuleService().changeDisplayState(this.getClass(), true);
}
@Override
public void onShow() {
this.audioController.playMusic(null, List.of(new StaticResource(List.of("audio"), "race.ogg")), true);
}
@Override
public void onHide() {
this.audioController.stopMusic();
}
}