parent
2398a4ee6a
commit
8e9a658098
@ -0,0 +1,168 @@ |
|||||||
|
package mightypork.gamecore.core.init; |
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import mightypork.utils.Reflect; |
||||||
|
import mightypork.utils.logging.Log; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* initialization sequence that takes care of task dependencies and ordering. |
||||||
|
* |
||||||
|
* @author Ondřej Hruška (MightyPork) |
||||||
|
*/ |
||||||
|
public class InitSequence { |
||||||
|
|
||||||
|
private final Map<String, InitTask> taskMap = new HashMap<>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add a task. If a task with the name already exists, replace it. |
||||||
|
* |
||||||
|
* @param task task to add |
||||||
|
*/ |
||||||
|
public void addTask(InitTask task) |
||||||
|
{ |
||||||
|
final String name = task.getName(); |
||||||
|
|
||||||
|
// detailed logging
|
||||||
|
// if (taskMap.containsKey(name)) {
|
||||||
|
// Log.f3("REPL init " + Str.pad("\"" + name + "\"", 20) + " <" + Str.val(task) + ">");
|
||||||
|
// } else {
|
||||||
|
// Log.f3("ADD init " + Str.pad("\"" + name + "\"", 20) + " <" + Str.val(task) + ">");
|
||||||
|
// }
|
||||||
|
|
||||||
|
taskMap.put(name, task); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get task sequence in proper order. |
||||||
|
* |
||||||
|
* @return initialization sequence |
||||||
|
*/ |
||||||
|
public List<InitTask> getSequence() |
||||||
|
{ |
||||||
|
final List<InitTask> remainingTasks = new ArrayList<>(taskMap.values()); |
||||||
|
|
||||||
|
final List<InitTask> orderedTasks = new ArrayList<>(); |
||||||
|
final Set<String> loadedTaskNames = new HashSet<>(); |
||||||
|
|
||||||
|
// resolve task order
|
||||||
|
InitTask taskToAdd = null; |
||||||
|
do { |
||||||
|
taskToAdd = null; |
||||||
|
|
||||||
|
for (final InitTask task : remainingTasks) { |
||||||
|
|
||||||
|
String[] deps = task.getDependencies(); |
||||||
|
if (deps == null) deps = new String[] {}; |
||||||
|
|
||||||
|
int missingDeps = deps.length; |
||||||
|
|
||||||
|
for (final String d : deps) { |
||||||
|
if (loadedTaskNames.contains(d)) missingDeps--; |
||||||
|
} |
||||||
|
|
||||||
|
if (missingDeps == 0) { |
||||||
|
if (taskToAdd == null || taskToAdd.getPriority() < task.getPriority()) { |
||||||
|
taskToAdd = task; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (taskToAdd != null) { |
||||||
|
orderedTasks.add(taskToAdd); |
||||||
|
loadedTaskNames.add(taskToAdd.getName()); |
||||||
|
remainingTasks.remove(taskToAdd); |
||||||
|
} |
||||||
|
|
||||||
|
} while (taskToAdd != null); |
||||||
|
|
||||||
|
checkLeftovers(loadedTaskNames, remainingTasks); |
||||||
|
|
||||||
|
return orderedTasks; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public List<InitTask> getSequenceOldImpl() |
||||||
|
{ |
||||||
|
final List<InitTask> remainingTasks = new ArrayList<>(taskMap.values()); |
||||||
|
|
||||||
|
final List<InitTask> orderedTasks = new ArrayList<>(); |
||||||
|
final Set<String> loadedTaskNames = new HashSet<>(); |
||||||
|
|
||||||
|
// resolve task order
|
||||||
|
int addedThisIteration = 0; |
||||||
|
do { |
||||||
|
addedThisIteration = 0; |
||||||
|
for (final Iterator<InitTask> i = remainingTasks.iterator(); i.hasNext();) { |
||||||
|
final InitTask task = i.next(); |
||||||
|
|
||||||
|
String[] deps = task.getDependencies(); |
||||||
|
if (deps == null) deps = new String[] {}; |
||||||
|
|
||||||
|
int missingDeps = deps.length; |
||||||
|
|
||||||
|
for (final String d : deps) { |
||||||
|
if (loadedTaskNames.contains(d)) missingDeps--; |
||||||
|
} |
||||||
|
|
||||||
|
if (missingDeps == 0) { |
||||||
|
orderedTasks.add(task); |
||||||
|
loadedTaskNames.add(task.getName()); |
||||||
|
i.remove(); |
||||||
|
addedThisIteration++; |
||||||
|
} |
||||||
|
} |
||||||
|
} while (addedThisIteration > 0); |
||||||
|
|
||||||
|
checkLeftovers(loadedTaskNames, remainingTasks); |
||||||
|
|
||||||
|
return orderedTasks; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void checkLeftovers(Collection<String> loadedTaskNames, Collection<InitTask> remainingTasks) |
||||||
|
{ |
||||||
|
// check if any tasks are left out
|
||||||
|
if (remainingTasks.size() > 0) { |
||||||
|
|
||||||
|
// build error message for each bad task
|
||||||
|
int badInitializers = 0; |
||||||
|
for (final InitTask task : remainingTasks) { |
||||||
|
|
||||||
|
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
badInitializers++; |
||||||
|
|
||||||
|
String notSatisfied = ""; |
||||||
|
|
||||||
|
for (final String d : task.getDependencies()) { |
||||||
|
if (!loadedTaskNames.contains(d)) { |
||||||
|
|
||||||
|
if (!notSatisfied.isEmpty()) { |
||||||
|
notSatisfied += ", "; |
||||||
|
} |
||||||
|
|
||||||
|
notSatisfied += d; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied); |
||||||
|
} |
||||||
|
|
||||||
|
if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package mightypork.gamecore.core.init; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.gamecore.core.App; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Initialize backend. The main point of postponing this is to make sure the |
||||||
|
* init is logged properly. |
||||||
|
* |
||||||
|
* @author Ondřej Hruška (MightyPork) |
||||||
|
*/ |
||||||
|
public class InitTaskBackend extends InitTask { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() |
||||||
|
{ |
||||||
|
App.instance().getBackend().initialize(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String getName() |
||||||
|
{ |
||||||
|
return "backend"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] getDependencies() |
||||||
|
{ |
||||||
|
return new String[] { "log" }; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getPriority() |
||||||
|
{ |
||||||
|
return PRIO_EARLY; |
||||||
|
} |
||||||
|
} |
@ -1,42 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Task to init renderable screens (part of the main loop).<br> |
|
||||||
* Resources must already be ready. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class InitTaskScreens extends InitTask { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
app.setMainRenderable(getMainRenderableImpl()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a loader impl |
|
||||||
* |
|
||||||
* @return loader |
|
||||||
*/ |
|
||||||
protected abstract Renderable getMainRenderableImpl(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "renderables"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] { "resources", "main_loop" }; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,51 @@ |
|||||||
|
package mightypork.gamecore.core.init; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.gamecore.graphics.Renderable; |
||||||
|
import mightypork.gamecore.resources.Res; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Task to init main renderable (UI).<br> |
||||||
|
* Resources are already registered in {@link Res}. |
||||||
|
* |
||||||
|
* @author Ondřej Hruška (MightyPork) |
||||||
|
*/ |
||||||
|
public abstract class InitTaskUI extends InitTask { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() |
||||||
|
{ |
||||||
|
app.setMainRenderable(createMainRenderable()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a loader impl |
||||||
|
* |
||||||
|
* @return loader |
||||||
|
*/ |
||||||
|
protected abstract Renderable createMainRenderable(); |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String getName() |
||||||
|
{ |
||||||
|
return "ui"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] getDependencies() |
||||||
|
{ |
||||||
|
// main loop queues layout change events, would lose them otherwise
|
||||||
|
return new String[] { "resources", "main_loop" }; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getPriority() |
||||||
|
{ |
||||||
|
return PRIO_LAST; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue