package loon.action.scripting;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import loon.action.scripting.pack.PackAnimation;
import loon.action.scripting.pack.PackFrame;
import loon.action.scripting.pack.PackTileFactory;
import loon.action.scripting.pack.PackTileMap;
import loon.core.LRelease;
import loon.core.graphics.Screen;
import loon.core.graphics.opengl.LTexturePack;
import loon.core.graphics.opengl.LTexturePack.PackEntry;
import loon.core.resource.Resources;
import loon.utils.StringUtils;
import loon.utils.xml.XMLElement;
import loon.utils.xml.XMLParser;
/**
* Copyright 2008 - 2011
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loonframework
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class ScriptFactory implements LRelease {
private PackTileFactory tileFactory;
private HashMap<String, Script> scripts;
private HashMap<String, LTexturePack> packs;
private HashMap<String, PackTileMap> maps;
private HashMap<String, PackAnimation> animations;
private ArrayList<Stack<StackFrame>> executionStacks;
private Callback callback;
String packName;
String mapName;
int packCount;
private InputStream inputStream;
private Screen screen;
public ScriptFactory(InputStream in) {
this(null, in);
}
public ScriptFactory(String res) {
this(null, res);
}
public ScriptFactory(Screen screen, String res) {
this.screen = screen;
try {
this.inputStream = Resources.openResource(res);
} catch (IOException e) {
e.printStackTrace();
}
this.init();
}
public ScriptFactory(Screen screen, InputStream in) {
this.screen = screen;
this.inputStream = in;
this.init();
}
private void init() {
this.scripts = new HashMap<String, Script>(10);
this.packs = new HashMap<String, LTexturePack>(10);
this.maps = new HashMap<String, PackTileMap>(10);
this.animations = new HashMap<String, PackAnimation>(10);
this.executionStacks = new ArrayList<Stack<StackFrame>>(10);
}
public void setMapName(String name) {
this.mapName = name;
}
public String getMapName() {
return mapName;
}
public void setPackName(String name) {
this.packName = name;
}
public String getPackName() {
return packName;
}
public void load() {
if (inputStream == null) {
return;
}
XMLElement root = XMLParser.parse(inputStream).getRoot();
for (Iterator<?> itr = root.elements(); itr.hasNext();) {
Object o = itr.next();
if (o instanceof XMLElement) {
XMLElement ele = (XMLElement) o;
if ("packs".equalsIgnoreCase(ele.getName())) {
for (Iterator<?> it = ele.elements("pack"); it.hasNext();) {
LTexturePack pack = new LTexturePack((XMLElement) it
.next());
packs.put(pack.getName(), pack);
if (packName == null) {
packName = pack.getName();
}
}
} else if ("scripts".equalsIgnoreCase(ele.getName())) {
for (Iterator<?> it = ele.elements("script"); it.hasNext();) {
XMLElement child = (XMLElement) it.next();
String name = child.getAttribute("name").getValue();
Script script = new Script(name);
for (Iterator<?> it1 = child.elements(); it1.hasNext();) {
Object obj = it1.next();
if (obj instanceof XMLElement) {
XMLElement child3 = (XMLElement) obj;
if (child3.getName().equals("function")) {
if (child3.hasAttribute("x")) {
script.add(new WithPosition(child3
.getAttribute("name")
.getValue(), child3
.getAttribute("x")
.getIntValue(), child3
.getAttribute("y")
.getIntValue()));
} else {
if (child3.hasAttribute("text")) {
script.add(new WithText(child3
.getAttribute("name")
.getValue(), child3
.getAttribute("text")
.getValue()));
} else {
script.add(new UserFunction(child3
.getAttribute("name")
.getValue()));
}
}
}
if (child3.getName().equals("wait")) {
script
.add(new WaitFunction(child3
.getAttribute("time")
.getIntValue()));
}
if (child3.getName().equals("jump")) {
script
.add(new JumpFunction(child3
.getAttribute("script")
.getValue()));
}
if (child3.getName().equals("execute")) {
script.add(new Execute(child3.getAttribute(
"script").getValue()));
}
if (child3.getName().equals("call")) {
script
.add(new CallFunction(child3
.getAttribute("script")
.getValue()));
}
}
}
scripts.put(name, script);
}
} else if ("animations".equalsIgnoreCase(ele.getName())) {
String packName = ele.getAttribute("pack", null);
for (Iterator<?> it = ele.elements("animation"); it.hasNext();) {
XMLElement child = (XMLElement) it.next();
String name = child.getAttribute("name", "");
boolean looped = true;
if (child.hasAttribute("noloop")) {
looped = false;
}
LTexturePack pack = null;
if (packName != null) {
pack = packs.get(packName);
} else {
if (packName == null) {
Set<String> set = packs.keySet();
pack = packs.get(set.iterator().next());
}
}
String context = child.getContents();
String[] strings = StringUtils.split(context, ",");
PackAnimation animation = new PackAnimation(name,
looped);
for (String res : strings) {
PackEntry entry = pack.getEntry(res);
if (entry == null) {
try {
entry = pack
.getEntry(Integer.parseInt(res));
} catch (Exception e) {
}
}
if (entry != null) {
animation.addFrame(new PackFrame(entry));
}
}
animations.put(name, animation);
}
} else if ("maps".equalsIgnoreCase(ele.getName())) {
for (Iterator<?> it = ele.elements("map"); it.hasNext();) {
XMLElement child = (XMLElement) it.next();
String name = child.getAttribute("name", String
.valueOf(System.currentTimeMillis()));
if (mapName == null) {
mapName = name;
}
maps.put(name, new PackTileMap(tileFactory, child,
screen));
}
}
}
}
this.packCount = packs.size();
if (inputStream != null) {
try {
inputStream.close();
inputStream = null;
} catch (Exception e) {
}
}
}
int update(Stack<StackFrame> stack, StackFrame frame, Callback callback) {
if (frame.isComplete()) {
return Script.COMPLETE_SCRIPT;
}
for (; frame.hasNext();) {
Function command = frame.next();
command.update(this, stack, callback);
}
if (frame.hasNext()) {
return Script.UNCOMPLETE_FUNCTION;
}
return Script.COMPLETE_FUNCTION;
}
public void update(Stack<StackFrame> stack) {
StackFrame frame = stack.peek();
frame.newTick();
switch (update(stack, frame, callback)) {
case Script.COMPLETE_SCRIPT:
stack.pop();
update();
break;
case Script.COMPLETE_FUNCTION:
break;
case Script.UNCOMPLETE_FUNCTION:
update();
break;
}
}
public void update() {
for (int i = 0; i < executionStacks.size(); i++) {
Stack<StackFrame> stack = executionStacks.get(i);
if (stack.empty()) {
executionStacks.remove(stack);
} else {
update(stack);
}
}
}
public int getPackCount() {
return packCount;
}
public void setCallback(Callback callback) {
this.callback = callback;
}
void jump(Stack<StackFrame> stack, String name) {
stack.pop();
execute(stack, name);
}
void execute(Stack<StackFrame> stack, String name) {
Script script = scripts.get(name);
stack.push(new StackFrame(script));
}
public void call(String name) {
Stack<StackFrame> stack = new Stack<StackFrame>();
executionStacks.add(stack);
execute(stack, name);
}
public void clear() {
executionStacks.clear();
}
public PackTileFactory getTileFactory() {
return tileFactory;
}
public void setTileFactory(PackTileFactory tileFactory) {
this.tileFactory = tileFactory;
}
public PackAnimation getAnimation(String name) {
PackAnimation animation = animations.get(name);
if (animation != null) {
return animations.get(name);
}
PackEntry entry = packs.get(packName).getEntry(name);
if (entry != null) {
animation = new PackAnimation(name, false);
animation.addFrame(new PackFrame(entry));
} else {
try {
entry = packs.get(packName).getEntry(Integer.parseInt(name));
if (entry != null) {
animation = new PackAnimation(name, false);
animation.addFrame(new PackFrame(entry));
}
} catch (Exception e) {
}
}
if (animation != null) {
animations.put(name, animation);
}
return animation;
}
public Screen getScreen() {
return screen;
}
public LTexturePack getPack(String name) {
return packs.get(name);
}
public Script getScript(String name) {
return scripts.get(name);
}
public PackTileMap getMap(String name) {
return getMap(name, null);
}
public PackTileMap getMap(String name, PackTileFactory factory) {
PackTileMap map = maps.get(name);
if (map != null && map.isDirty()) {
map.init(factory);
map.update();
}
return map;
}
@Override
public void dispose() {
if (packs != null) {
for (LTexturePack pack : packs.values()) {
if (pack != null) {
pack.dispose();
pack = null;
}
}
packs.clear();
}
if (scripts != null) {
scripts.clear();
scripts = null;
}
if (packs != null) {
packs.clear();
packs = null;
}
if (maps != null) {
maps.clear();
maps = null;
}
if (animations != null) {
animations.clear();
animations = null;
}
if (executionStacks != null) {
executionStacks.clear();
executionStacks = null;
}
if (inputStream != null) {
try {
inputStream.close();
inputStream = null;
} catch (Exception e) {
}
}
}
}