diff --git a/src/yugecin/opsudance/inject/Binder.java b/src/yugecin/opsudance/inject/Binder.java
new file mode 100644
index 00000000..2df509ba
--- /dev/null
+++ b/src/yugecin/opsudance/inject/Binder.java
@@ -0,0 +1,25 @@
+/*
+ * opsu!dance - fork of opsu! with cursordance auto
+ * Copyright (C) 2017 yugecin
+ *
+ * opsu!dance 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.
+ *
+ * opsu!dance 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 opsu!dance. If not, see .
+ */
+package yugecin.opsudance.inject;
+
+public interface Binder {
+
+ void asEagerSingleton();
+ void asLazySingleton();
+ void to(Class extends T> type);
+}
diff --git a/src/yugecin/opsudance/inject/Injector.java b/src/yugecin/opsudance/inject/Injector.java
new file mode 100644
index 00000000..5c301583
--- /dev/null
+++ b/src/yugecin/opsudance/inject/Injector.java
@@ -0,0 +1,101 @@
+/*
+ * opsu!dance - fork of opsu! with cursordance auto
+ * Copyright (C) 2017 yugecin
+ *
+ * opsu!dance 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.
+ *
+ * opsu!dance 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 opsu!dance. If not, see .
+ */
+package yugecin.opsudance.inject;
+
+import yugecin.opsudance.kernel.InstanceContainer;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+@SuppressWarnings("unchecked")
+public abstract class Injector implements InstanceContainer, Binder {
+
+ private final HashMap, Object> instances;
+ private final LinkedList> lazyInstances;
+
+ private Class> lastType;
+
+ public Injector() {
+ instances = new HashMap<>();
+ lazyInstances = new LinkedList<>();
+ instances.put(InstanceContainer.class, this);
+ configure();
+ }
+
+ protected abstract void configure();
+
+ public final T provide(Class type) {
+ Object instance = instances.get(type);
+ if (instance != null) {
+ return (T) instance;
+ }
+ ListIterator> iter = lazyInstances.listIterator();
+ while (iter.hasNext()) {
+ Class> l = iter.next();
+ if (l == type) {
+ iter.remove();
+ instance = createInstance(type);
+ instances.put(type, instance);
+ return (T) instance;
+ }
+ }
+ return createInstance(type);
+ }
+
+ private T createInstance(Class type) {
+ Constructor>[] constructors = type.getDeclaredConstructors();
+ if (constructors.length == 0) {
+ throw new RuntimeException("Cannot provide " + type.getSimpleName());
+ }
+ Constructor constructor = constructors[0];
+ Class>[] parameterTypes = constructor.getParameterTypes();
+ Object[] params = new Object[parameterTypes.length];
+ for (int i = parameterTypes.length - 1; i >= 0; i--) {
+ params[i] = provide(parameterTypes[i]);
+ }
+ try {
+ return (T) constructor.newInstance(params);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public final Binder bind(Class type) {
+ lastType = type;
+ return this;
+ }
+
+ @Override
+ public final void asEagerSingleton() {
+ instances.put(lastType, createInstance(lastType));
+ }
+
+ @Override
+ public final void asLazySingleton() {
+ lazyInstances.add(lastType);
+ }
+
+ @Override
+ public final void to(Class type) {
+ instances.put(lastType, createInstance(type));
+ }
+
+}
diff --git a/src/yugecin/opsudance/inject/OpsuDanceInjector.java b/src/yugecin/opsudance/inject/OpsuDanceInjector.java
new file mode 100644
index 00000000..e82c6d41
--- /dev/null
+++ b/src/yugecin/opsudance/inject/OpsuDanceInjector.java
@@ -0,0 +1,53 @@
+/*
+ * opsu!dance - fork of opsu! with cursordance auto
+ * Copyright (C) 2017 yugecin
+ *
+ * opsu!dance 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.
+ *
+ * opsu!dance 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 opsu!dance. If not, see .
+ */
+package yugecin.opsudance.inject;
+
+import yugecin.opsudance.PreStartupInitializer;
+import yugecin.opsudance.core.Demux;
+import yugecin.opsudance.core.DisplayContainer;
+import yugecin.opsudance.core.events.EventBus;
+import yugecin.opsudance.core.state.specialstates.FpsRenderState;
+import yugecin.opsudance.core.state.transitions.EmptyTransitionState;
+import yugecin.opsudance.core.state.transitions.FadeInTransitionState;
+import yugecin.opsudance.core.state.transitions.FadeOutTransitionState;
+import yugecin.opsudance.errorhandling.ErrorHandler;
+import yugecin.opsudance.states.EmptyRedState;
+import yugecin.opsudance.states.EmptyState;
+
+public class OpsuDanceInjector extends Injector {
+
+ protected void configure() {
+ bind(EventBus.class).asEagerSingleton();
+
+ bind(PreStartupInitializer.class).asEagerSingleton();
+ bind(Demux.class).asEagerSingleton();
+ bind(DisplayContainer.class).asEagerSingleton();
+
+ bind(ErrorHandler.class).asEagerSingleton();
+
+ bind(FpsRenderState.class).asEagerSingleton();
+
+ bind(EmptyTransitionState.class).asEagerSingleton();
+ bind(FadeInTransitionState.class).asEagerSingleton();
+ bind(FadeOutTransitionState.class).asEagerSingleton();
+
+ bind(EmptyRedState.class).asEagerSingleton();
+ bind(EmptyState.class).asEagerSingleton();
+ }
+
+}
diff --git a/src/yugecin/opsudance/kernel/Entrypoint.java b/src/yugecin/opsudance/kernel/Entrypoint.java
index 13914a6f..8676e2a4 100644
--- a/src/yugecin/opsudance/kernel/Entrypoint.java
+++ b/src/yugecin/opsudance/kernel/Entrypoint.java
@@ -18,6 +18,7 @@
package yugecin.opsudance.kernel;
import yugecin.opsudance.OpsuDance;
+import yugecin.opsudance.inject.OpsuDanceInjector;
public class Entrypoint {
@@ -25,7 +26,7 @@ public class Entrypoint {
public static void main(String[] args) {
sout("launched");
- InstanceContainerImpl.initialize().provide(OpsuDance.class).start(args);
+ (new OpsuDanceInjector()).provide(OpsuDance.class).start(args);
}
public static long runtime() {