forked from nova/jmonkey-test
Rohan Sircar
4 years ago
commit
1f55e08fa5
53 changed files with 2862 additions and 0 deletions
-
39.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/dep/src/ammonite/$file/src/main/resources/dep.scala
-
45.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello/src/ammonite/$file/src/main/resources/hello.scala
-
134.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello2/src/ammonite/$file/src/main/resources/hello2.scala
-
25.gitignore
-
1.scalafmt.conf
-
3assets.jmp
-
192build.sbt
-
BINlibbulletjme.so
-
1project/build.properties
-
2project/plugins.sbt
-
1src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
-
7src/main/resources/application.conf
-
2src/main/resources/dep.sc
-
36src/main/resources/hello.main.kts
-
35src/main/resources/hello.sc
-
5src/main/resources/hello2.main.kts
-
107src/main/resources/hello2.sc
-
19src/main/resources/weapon.json
-
62src/main/scala/com/jme3/animation/package.scala
-
16src/main/scala/com/jme3/app/package.scala
-
6src/main/scala/com/jme3/input/Action.scala
-
37src/main/scala/com/jme3/input/controls/package.scala
-
18src/main/scala/com/jme3/input/package.scala
-
11src/main/scala/com/jme3/material/package.scala
-
19src/main/scala/com/jme3/scene/debug/package.scala
-
56src/main/scala/com/jme3/scene/package.scala
-
20src/main/scala/com/jme3/scene/shape/package.scala
-
14src/main/scala/com/jme3/syntax/package.scala
-
5src/main/scala/message.txt
-
127src/main/scala/wow/doge/mygame/Main.scala
-
6src/main/scala/wow/doge/mygame/components/Position.scala
-
28src/main/scala/wow/doge/mygame/components/Tag.scala
-
11src/main/scala/wow/doge/mygame/components/Test.java
-
5src/main/scala/wow/doge/mygame/components/TestComponent.scala
-
139src/main/scala/wow/doge/mygame/events/EventBus.scala
-
17src/main/scala/wow/doge/mygame/events/Events.scala
-
3src/main/scala/wow/doge/mygame/events/EventsModule.scala
-
5src/main/scala/wow/doge/mygame/executors/ExecutorsModule.scala
-
103src/main/scala/wow/doge/mygame/executors/GUIExecutor.scala
-
10src/main/scala/wow/doge/mygame/executors/Schedulers.scala
-
109src/main/scala/wow/doge/mygame/game/GameApp.scala
-
67src/main/scala/wow/doge/mygame/game/GameAppActor.scala
-
55src/main/scala/wow/doge/mygame/implicits/EntityQuery.scala
-
175src/main/scala/wow/doge/mygame/implicits/package.scala
-
11src/main/scala/wow/doge/mygame/math/ImVector3f.scala
-
157src/main/scala/wow/doge/mygame/scriptsystem/ScriptActor.scala
-
166src/main/scala/wow/doge/mygame/scriptsystem/ScriptCachingActor.scala
-
38src/main/scala/wow/doge/mygame/state/EntityDataState.java
-
86src/main/scala/wow/doge/mygame/state/MovementActor.scala
-
63src/main/scala/wow/doge/mygame/state/MyBaseState.scala
-
286src/main/scala/wow/doge/mygame/state/PlayerMovementState2.scala
-
206src/main/scala/wow/doge/mygame/state/ScriptingEngineState.scala
-
71src/main/scala/wow/doge/mygame/state/TestAppState.scala
@ -0,0 +1,39 @@ |
|||||
|
|
||||
|
package ammonite |
||||
|
package $file.src.main.resources |
||||
|
import _root_.ammonite.interp.api.InterpBridge.{ |
||||
|
value => interp |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.InterpBridge.value.{ |
||||
|
exit |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.IvyConstructor.{ |
||||
|
ArtifactIdExt, |
||||
|
GroupIdExt |
||||
|
} |
||||
|
import _root_.ammonite.runtime.tools.{ |
||||
|
browse, |
||||
|
grep, |
||||
|
time, |
||||
|
tail |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.{ |
||||
|
desugar, |
||||
|
source |
||||
|
} |
||||
|
import _root_.ammonite.main.Router.{ |
||||
|
doc, |
||||
|
main |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.Util.{ |
||||
|
pathScoptRead |
||||
|
} |
||||
|
|
||||
|
|
||||
|
object dep{ |
||||
|
/*<script>*/class Test(x: Int) |
||||
|
/*</script>*/ /*<generated>*/ |
||||
|
def $main() = { scala.Iterator[String]() } |
||||
|
override def toString = "dep" |
||||
|
/*</generated>*/ |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
|
||||
|
package ammonite |
||||
|
package $file.src.main.resources |
||||
|
import _root_.ammonite.interp.api.InterpBridge.{ |
||||
|
value => interp |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.InterpBridge.value.{ |
||||
|
exit |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.IvyConstructor.{ |
||||
|
ArtifactIdExt, |
||||
|
GroupIdExt |
||||
|
} |
||||
|
import _root_.ammonite.runtime.tools.{ |
||||
|
browse, |
||||
|
grep, |
||||
|
time, |
||||
|
tail |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.{ |
||||
|
desugar, |
||||
|
source |
||||
|
} |
||||
|
import _root_.ammonite.main.Router.{ |
||||
|
doc, |
||||
|
main |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.Util.{ |
||||
|
pathScoptRead |
||||
|
} |
||||
|
import ammonite.$file.src.main.resources.{ |
||||
|
dep |
||||
|
} |
||||
|
|
||||
|
|
||||
|
object hello{ |
||||
|
/*<script>*/import $file.$ |
||||
|
import dep.Test |
||||
|
|
||||
|
/*<amm>*/val res_2 = /*</amm>*/new Test(1) |
||||
|
/*</script>*/ /*<generated>*/ |
||||
|
def $main() = { scala.Iterator[String]() } |
||||
|
override def toString = "hello" |
||||
|
/*</generated>*/ |
||||
|
} |
@ -0,0 +1,134 @@ |
|||||
|
|
||||
|
package ammonite |
||||
|
package $file.src.main.resources |
||||
|
import _root_.ammonite.interp.api.InterpBridge.{ |
||||
|
value => interp |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.InterpBridge.value.{ |
||||
|
exit |
||||
|
} |
||||
|
import _root_.ammonite.interp.api.IvyConstructor.{ |
||||
|
ArtifactIdExt, |
||||
|
GroupIdExt |
||||
|
} |
||||
|
import _root_.ammonite.runtime.tools.{ |
||||
|
browse, |
||||
|
grep, |
||||
|
time, |
||||
|
tail |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.{ |
||||
|
desugar, |
||||
|
source |
||||
|
} |
||||
|
import _root_.ammonite.main.Router.{ |
||||
|
doc, |
||||
|
main |
||||
|
} |
||||
|
import _root_.ammonite.repl.tools.Util.{ |
||||
|
pathScoptRead |
||||
|
} |
||||
|
|
||||
|
|
||||
|
object hello2{ |
||||
|
/*<script>*/import $repo.$ |
||||
|
// import $repo.`https://bintray.com/jmonkeyengine/com.jme3` |
||||
|
// import $file.dep |
||||
|
import $ivy.$ |
||||
|
// import $ivy.`wow.doge:game:1.0-SNAPSHOT` |
||||
|
import $ivy.$ |
||||
|
// import wow.doge.game.types.GameScript |
||||
|
import com.jme3.scene.control.Control |
||||
|
|
||||
|
// println("hello from script") |
||||
|
|
||||
|
// class Scr extends GameScript { |
||||
|
// def start(): Unit = println("hello from start") |
||||
|
|
||||
|
// def stop(): Unit = println("hello from stop") |
||||
|
// } |
||||
|
|
||||
|
// // class SomeClass extends Control {} |
||||
|
|
||||
|
// @main |
||||
|
// def main(): GameScript = new Scr() |
||||
|
import com.simsilica.es.base.DefaultEntityData |
||||
|
import com.simsilica.es.EntityData |
||||
|
import com.jme3.app.Application |
||||
|
import wow.doge.mygame.game.Implicits._ |
||||
|
import wow.doge.mygame.components.TestComponent |
||||
|
import com.jme3.scene.shape.Box |
||||
|
import com.jme3.scene.Geometry |
||||
|
import com.jme3.material.Material |
||||
|
import com.jme3.math.ColorRGBA |
||||
|
import com.jme3.asset.AssetManager |
||||
|
import com.jme3.math.Vector3f |
||||
|
import wow.doge.mygame.state._ |
||||
|
class TestAppState( |
||||
|
// private var _entity: Option[EntityData] = Some(new DefaultEntityData()) |
||||
|
) extends MyBaseState { |
||||
|
protected lazy val b = new Box(1, 1, 1) |
||||
|
protected lazy val geom = new Geometry("Box", b) |
||||
|
protected lazy val mat = Material( |
||||
|
assetManager = assetManager, |
||||
|
path = "Common/MatDefs/Misc/Unshaded.j3md" |
||||
|
) |
||||
|
|
||||
|
// def entity = _entity |
||||
|
// override def initialize(app: Application): Unit = { |
||||
|
// super.initialize(app) |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
override def init() = { |
||||
|
entityData |
||||
|
.createEntity() |
||||
|
.withComponents(TestComponent()) |
||||
|
// entityData.setComponents(x, TestComponent()) |
||||
|
val es = entityData.getEntities(classOf[TestComponent]) |
||||
|
println(es) |
||||
|
geom.setMaterial(mat) |
||||
|
rootNode.attachChild(geom) |
||||
|
|
||||
|
// geom.foreach(e => { |
||||
|
|
||||
|
// }) |
||||
|
} |
||||
|
|
||||
|
override def update(tpf: Float) = { |
||||
|
geom.rotate(0, 0.5f * tpf, 0) |
||||
|
geom.move(new Vector3f(0, 1 * tpf, 0)) |
||||
|
} |
||||
|
|
||||
|
override def cleanup(app: Application): Unit = { |
||||
|
// _entity.map(_.close()) |
||||
|
// _entity = None |
||||
|
} |
||||
|
|
||||
|
override def onEnable(): Unit = {} |
||||
|
|
||||
|
override def onDisable(): Unit = {} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object Material { |
||||
|
def apply( |
||||
|
color: String = "Color", |
||||
|
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue, |
||||
|
assetManager: AssetManager, |
||||
|
path: String |
||||
|
): Material = { |
||||
|
val mat = |
||||
|
new Material(assetManager, path) |
||||
|
mat.setColor(color, colorType) |
||||
|
mat |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@main |
||||
|
def main(): MyBaseState = new TestAppState() |
||||
|
/*</script>*/ /*<generated>*/ |
||||
|
def $main() = { scala.Iterator[String]() } |
||||
|
override def toString = "hello2" |
||||
|
/*</generated>*/ |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
*.class |
||||
|
*.log |
||||
|
|
||||
|
# sbt specific |
||||
|
.cache/ |
||||
|
.history/ |
||||
|
.lib/ |
||||
|
dist/* |
||||
|
target/ |
||||
|
lib_managed/ |
||||
|
src_managed/ |
||||
|
project/boot/ |
||||
|
project/plugins/project/ |
||||
|
metals.sbt |
||||
|
.metals |
||||
|
.bloop |
||||
|
|
||||
|
# Scala-IDE specific |
||||
|
.scala_dependencies |
||||
|
.worksheet |
||||
|
|
||||
|
.idea/ |
||||
|
.vscode |
||||
|
assets/ |
||||
|
*.j3o |
@ -0,0 +1 @@ |
|||||
|
version = "2.6.4" |
@ -0,0 +1,3 @@ |
|||||
|
#assets properties |
||||
|
#Fri Oct 23 22:34:43 IST 2020 |
||||
|
assets.folder.name=src/main/resources/assets |
@ -0,0 +1,192 @@ |
|||||
|
// The simplest possible sbt build file is just one line: |
||||
|
|
||||
|
scalaVersion := "2.13.3" |
||||
|
// That is, to create a valid sbt build, all you've got to do is define the |
||||
|
// version of Scala you'd like your project to use. |
||||
|
|
||||
|
// ============================================================================ |
||||
|
|
||||
|
// Lines like the above defining `scalaVersion` are called "settings". Settings |
||||
|
// are key/value pairs. In the case of `scalaVersion`, the key is "scalaVersion" |
||||
|
// and the value is "2.13.1" |
||||
|
|
||||
|
// It's possible to define many kinds of settings, such as: |
||||
|
|
||||
|
// Note, it's not required for you to define these three settings. These are |
||||
|
// mostly only necessary if you intend to publish your library's binaries on a |
||||
|
// place like Sonatype or Bintray. |
||||
|
|
||||
|
// Want to use a published library in your project? |
||||
|
// You can define other libraries as dependencies in your build like this: |
||||
|
|
||||
|
resolvers += "Jcenter" at "https://jcenter.bintray.com/" |
||||
|
resolvers += "JME Bintray" at "https://bintray.com/jmonkeyengine/com.jme3" |
||||
|
|
||||
|
resolvers += Resolver.mavenLocal |
||||
|
resolvers += Resolver.sonatypeRepo("snapshots") |
||||
|
|
||||
|
lazy val jmeVersion = "3.3.2-stable" |
||||
|
|
||||
|
lazy val osName = System.getProperty("os.name") match { |
||||
|
case n if n.startsWith("Linux") => "linux" |
||||
|
case n if n.startsWith("Mac") => "mac" |
||||
|
case n if n.startsWith("Windows") => "win" |
||||
|
case _ => throw new Exception("Unknown platform!") |
||||
|
} |
||||
|
lazy val javaFXModules = |
||||
|
Seq("base", "controls", "fxml", "graphics", "media", "swing", "web") |
||||
|
|
||||
|
lazy val root = (project in file(".")).settings( |
||||
|
inThisBuild( |
||||
|
List( |
||||
|
scalaVersion := scalaVersion.value, // 2.11.12, or 2.13.3 |
||||
|
semanticdbEnabled := true, // enable SemanticDB |
||||
|
semanticdbVersion := "4.3.24" // use Scalafix compatible version |
||||
|
) |
||||
|
), |
||||
|
name := "mygame", |
||||
|
organization := "wow.doge", |
||||
|
version := "1.0-SNAPSHOT", |
||||
|
libraryDependencies ++= Seq( |
||||
|
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2", |
||||
|
// https://mvnrepository.com/artifact/org.jmonkeyengine/jme3-core |
||||
|
"org.jmonkeyengine" % "jme3-core" % jmeVersion, |
||||
|
// https://mvnrepository.com/artifact/org.jmonkeyengine/jme3-desktop |
||||
|
"org.jmonkeyengine" % "jme3-desktop" % jmeVersion, |
||||
|
// https://mvnrepository.com/artifact/org.jmonkeyengine/jme3-lwjgl3 |
||||
|
"org.jmonkeyengine" % "jme3-lwjgl3" % jmeVersion, |
||||
|
"org.jmonkeyengine" % "jme3-effects" % jmeVersion, |
||||
|
"org.jmonkeyengine" % "jme3-plugins" % jmeVersion, |
||||
|
"org.jmonkeyengine" % "jme3-blender" % jmeVersion, |
||||
|
// https://mvnrepository.com/artifact/com.github.stephengold/Minie |
||||
|
"com.github.stephengold" % "Minie" % "3.0.0", |
||||
|
// https://mvnrepository.com/artifact/com.simsilica/zay-es |
||||
|
"com.simsilica" % "zay-es" % "1.2.1", |
||||
|
"org.typelevel" %% "cats-core" % "2.1.1", |
||||
|
"com.lihaoyi" % "ammonite" % "2.2.0" cross CrossVersion.full, |
||||
|
"org.jetbrains.kotlin" % "kotlin-main-kts" % "1.4.10", |
||||
|
"org.jetbrains.kotlin" % "kotlin-scripting-jsr223" % "1.4.10", |
||||
|
// "wow.doge" % "game" % "1.0-SNAPSHOT", |
||||
|
"org.scalafx" %% "scalafx" % "14-R19", |
||||
|
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.10", |
||||
|
"ch.qos.logback" % "logback-classic" % "1.2.3", |
||||
|
"org.typelevel" %% "cats-core" % "2.1.1", |
||||
|
"org.typelevel" %% "cats-effect" % "2.1.4", |
||||
|
"io.monix" %% "monix" % "3.2.2", |
||||
|
"io.monix" %% "monix-bio" % "1.0.0", |
||||
|
"io.circe" %% "circe-core" % "0.13.0", |
||||
|
"io.circe" %% "circe-generic" % "0.13.0", |
||||
|
"com.softwaremill.sttp.client" %% "core" % "2.2.5", |
||||
|
"com.softwaremill.sttp.client" %% "monix" % "2.2.5", |
||||
|
"com.softwaremill.sttp.client" %% "circe" % "2.2.5", |
||||
|
"com.softwaremill.sttp.client" %% "async-http-client-backend-monix" % "2.2.5", |
||||
|
"com.github.valskalla" %% "odin-monix" % "0.8.1", |
||||
|
"com.softwaremill.macwire" %% "util" % "2.3.7", |
||||
|
"com.softwaremill.macwire" %% "macros" % "2.3.6" % "provided", |
||||
|
"com.softwaremill.macwire" %% "macrosakka" % "2.3.6" % "provided", |
||||
|
"com.github.valskalla" %% "odin-slf4j" % "0.8.1", |
||||
|
"com.softwaremill.quicklens" %% "quicklens" % "1.6.1" |
||||
|
), |
||||
|
// Determine OS version of JavaFX binaries |
||||
|
|
||||
|
// Add JavaFX dependencies |
||||
|
libraryDependencies ++= javaFXModules.map(m => |
||||
|
"org.openjfx" % s"javafx-$m" % "14.0.1" classifier osName |
||||
|
), |
||||
|
scalacOptions ++= Seq( |
||||
|
"-encoding", |
||||
|
"UTF-8", |
||||
|
"-deprecation", |
||||
|
"-feature", |
||||
|
"-unchecked", |
||||
|
"-Xlint", |
||||
|
"-Ywarn-numeric-widen", |
||||
|
"-Ymacro-annotations", |
||||
|
// "utf-8", // Specify character encoding used by source files. |
||||
|
"-explaintypes" // Explain type errors in more detail. |
||||
|
), |
||||
|
javacOptions ++= Seq("-source", "11", "-target", "11"), |
||||
|
javaOptions ++= Seq("-Xmx2G", "-Xms2G"), |
||||
|
fork := true, |
||||
|
assemblyMergeStrategy in assembly := { |
||||
|
case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first |
||||
|
case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first |
||||
|
case "application.conf" => MergeStrategy.concat |
||||
|
case "unwanted.txt" => MergeStrategy.discard |
||||
|
case x if Assembly.isConfigFile(x) => |
||||
|
MergeStrategy.concat |
||||
|
case PathList("META-INF", xs @ _*) => |
||||
|
(xs map { _.toLowerCase }) match { |
||||
|
case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | |
||||
|
("dependencies" :: Nil) => |
||||
|
MergeStrategy.discard |
||||
|
case ps @ (x :: xs) |
||||
|
if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") => |
||||
|
MergeStrategy.discard |
||||
|
case "plexus" :: xs => |
||||
|
MergeStrategy.discard |
||||
|
case "services" :: xs => |
||||
|
MergeStrategy.filterDistinctLines |
||||
|
case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) => |
||||
|
MergeStrategy.filterDistinctLines |
||||
|
case _ => MergeStrategy.first // Changed deduplicate to first |
||||
|
} |
||||
|
case PathList(_*) => MergeStrategy.first |
||||
|
// case x => |
||||
|
// val oldStrategy = (assemblyMergeStrategy in assembly).value |
||||
|
// oldStrategy(x) |
||||
|
} |
||||
|
// scalaVersion := "2.13.2", // 2.11.12, or 2.13.3 |
||||
|
// semanticdbEnabled := true, // enable SemanticDB |
||||
|
// semanticdbVersion := scalafixSemanticdb.revision // use Scalafix compatible version |
||||
|
// semanticdbVersion := "4.3.24", |
||||
|
) |
||||
|
|
||||
|
// Here, `libraryDependencies` is a set of dependencies, and by using `+=`, |
||||
|
// we're adding the scala-parser-combinators dependency to the set of dependencies |
||||
|
// that sbt will go and fetch when it starts up. |
||||
|
// Now, in any Scala file, you can import classes, objects, etc., from |
||||
|
// scala-parser-combinators with a regular import. |
||||
|
|
||||
|
// TIP: To find the "dependency" that you need to add to the |
||||
|
// `libraryDependencies` set, which in the above example looks like this: |
||||
|
|
||||
|
// "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" |
||||
|
|
||||
|
// You can use Scaladex, an index of all known published Scala libraries. There, |
||||
|
// after you find the library you want, you can just copy/paste the dependency |
||||
|
// information that you need into your build file. For example, on the |
||||
|
// scala/scala-parser-combinators Scaladex page, |
||||
|
// https://index.scala-lang.org/scala/scala-parser-combinators, you can copy/paste |
||||
|
// the sbt dependency from the sbt box on the right-hand side of the screen. |
||||
|
|
||||
|
// IMPORTANT NOTE: while build files look _kind of_ like regular Scala, it's |
||||
|
// important to note that syntax in *.sbt files doesn't always behave like |
||||
|
// regular Scala. For example, notice in this build file that it's not required |
||||
|
// to put our settings into an enclosing object or class. Always remember that |
||||
|
// sbt is a bit different, semantically, than vanilla Scala. |
||||
|
|
||||
|
// ============================================================================ |
||||
|
|
||||
|
// Most moderately interesting Scala projects don't make use of the very simple |
||||
|
// build file style (called "bare style") used in this build.sbt file. Most |
||||
|
// intermediate Scala projects make use of so-called "multi-project" builds. A |
||||
|
// multi-project build makes it possible to have different folders which sbt can |
||||
|
// be configured differently for. That is, you may wish to have different |
||||
|
// dependencies or different testing frameworks defined for different parts of |
||||
|
// your codebase. Multi-project builds make this possible. |
||||
|
|
||||
|
// Here's a quick glimpse of what a multi-project build looks like for this |
||||
|
// build, with only one "subproject" defined, called `root`: |
||||
|
|
||||
|
// lazy val root = (project in file(".")). |
||||
|
// settings( |
||||
|
// inThisBuild(List( |
||||
|
// organization := "ch.epfl.scala", |
||||
|
// scalaVersion := "2.13.1" |
||||
|
// )), |
||||
|
// name := "hello-world" |
||||
|
// ) |
||||
|
|
||||
|
// To learn more about multi-project builds, head over to the official sbt |
||||
|
// documentation at http://www.scala-sbt.org/documentation.html |
@ -0,0 +1 @@ |
|||||
|
sbt.version=1.3.13 |
@ -0,0 +1,2 @@ |
|||||
|
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
||||
|
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
@ -0,0 +1 @@ |
|||||
|
org.jetbrains.kotlin.mainKts.jsr223.KotlinJsr223MainKtsScriptEngineFactory |
@ -0,0 +1,7 @@ |
|||||
|
jme-dispatcher { |
||||
|
type = "Dispatcher" |
||||
|
name = "JME-Thread" |
||||
|
executor = "wow.doge.mygame.executors.JMEThreadExecutorServiceConfigurator" |
||||
|
throughput = 1 |
||||
|
} |
||||
|
akka.jvm-exit-on-fatal-error = on |
@ -0,0 +1,2 @@ |
|||||
|
// println("hello from dep") |
||||
|
class Test(x: Int) |
@ -0,0 +1,36 @@ |
|||||
|
// @file:Import("src/main/resources/hello2.main.kts") |
||||
|
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1") |
||||
|
@file:DependsOn("/home/rohan/.m2/repository/wow/doge/game/1.0-SNAPSHOT/game-1.0-SNAPSHOT.jar") |
||||
|
@file:DependsOn("/home/rohan/.ivy2/local/wow.doge/mygame_2.13/1.0-SNAPSHOT/jars/mygame_2.13.jar") |
||||
|
|
||||
|
import wow.doge.game.types.GameScript |
||||
|
|
||||
|
import kotlinx.coroutines.delay |
||||
|
import kotlinx.coroutines.launch |
||||
|
import kotlinx.coroutines.runBlocking |
||||
|
import kotlin.random.Random |
||||
|
|
||||
|
import wow.doge.mygame.components.Test |
||||
|
|
||||
|
|
||||
|
//println(x * 2) |
||||
|
|
||||
|
println("hello from main script") |
||||
|
|
||||
|
class GameScriptImpl : GameScript { |
||||
|
override fun start() = runBlocking { |
||||
|
for(x in 0 until 5) { |
||||
|
launch { |
||||
|
val del = Random.nextLong(20, 100) |
||||
|
|
||||
|
delay(del) |
||||
|
println("hello from start $x, delay is $del") |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
override fun stop() {println("hello from stop")} |
||||
|
} |
||||
|
|
||||
|
GameScriptImpl() |
||||
|
|
||||
|
class MyTest : Test() |
@ -0,0 +1,35 @@ |
|||||
|
// #!/usr/bin/env amm |
||||
|
|
||||
|
// import coursierapi.MavenRepository |
||||
|
|
||||
|
// interp.repositories.update( |
||||
|
// interp.repositories() ::: List( |
||||
|
// MavenRepository.of("file://home/rohan/.m2/repository") |
||||
|
// ) |
||||
|
// ) |
||||
|
|
||||
|
// @ |
||||
|
// import $repo.`https://jcenter.bintray.com` |
||||
|
// // import $repo.`https://bintray.com/jmonkeyengine/com.jme3` |
||||
|
// import $file.dep |
||||
|
// import $ivy.`org.jmonkeyengine:jme3-core:3.2.4-stable` |
||||
|
// import $ivy.`wow.doge:game:1.0-SNAPSHOT` |
||||
|
// import wow.doge.game.types.GameScript |
||||
|
// import com.jme3.scene.control.Control |
||||
|
|
||||
|
// println("hello from script") |
||||
|
|
||||
|
// class Scr extends GameScript { |
||||
|
// def start(): Unit = println("hello from start") |
||||
|
|
||||
|
// def stop(): Unit = println("hello from stop") |
||||
|
// } |
||||
|
|
||||
|
// // class SomeClass extends Control {} |
||||
|
|
||||
|
// @main |
||||
|
// def main(): GameScript = new Scr() |
||||
|
import $file.dep |
||||
|
import dep.Test |
||||
|
|
||||
|
new Test(1) |
@ -0,0 +1,5 @@ |
|||||
|
println("hello from dep") |
||||
|
|
||||
|
class Test(val x: Int) |
||||
|
|
||||
|
var x = 2 |
@ -0,0 +1,107 @@ |
|||||
|
#!/usr/bin/env amm |
||||
|
|
||||
|
// import coursierapi.MavenRepository |
||||
|
|
||||
|
// interp.repositories.update( |
||||
|
// interp.repositories() ::: List( |
||||
|
// MavenRepository.of("file://home/rohan/.m2/repository") |
||||
|
// ) |
||||
|
// ) |
||||
|
|
||||
|
// @ |
||||
|
import $repo.`https://jcenter.bintray.com` |
||||
|
// import $repo.`https://bintray.com/jmonkeyengine/com.jme3` |
||||
|
// import $file.dep |
||||
|
import $ivy.`org.jmonkeyengine:jme3-core:3.2.4-stable` |
||||
|
// import $ivy.`wow.doge:game:1.0-SNAPSHOT` |
||||
|
import $ivy.`wow.doge::mygame:1.0-SNAPSHOT` |
||||
|
// import wow.doge.game.types.GameScript |
||||
|
import com.jme3.scene.control.Control |
||||
|
|
||||
|
// println("hello from script") |
||||
|
|
||||
|
// class Scr extends GameScript { |
||||
|
// def start(): Unit = println("hello from start") |
||||
|
|
||||
|
// def stop(): Unit = println("hello from stop") |
||||
|
// } |
||||
|
|
||||
|
// // class SomeClass extends Control {} |
||||
|
|
||||
|
// @main |
||||
|
// def main(): GameScript = new Scr() |
||||
|
import com.simsilica.es.base.DefaultEntityData |
||||
|
import com.simsilica.es.EntityData |
||||
|
import com.jme3.app.Application |
||||
|
import wow.doge.mygame.game.Implicits._ |
||||
|
import wow.doge.mygame.components.TestComponent |
||||
|
import com.jme3.scene.shape.Box |
||||
|
import com.jme3.scene.Geometry |
||||
|
import com.jme3.material.Material |
||||
|
import com.jme3.math.ColorRGBA |
||||
|
import com.jme3.asset.AssetManager |
||||
|
import com.jme3.math.Vector3f |
||||
|
import wow.doge.mygame.state._ |
||||
|
class TestAppState( |
||||
|
// private var _entity: Option[EntityData] = Some(new DefaultEntityData()) |
||||
|
) extends MyBaseState { |
||||
|
protected lazy val b = new Box(1, 1, 1) |
||||
|
protected lazy val geom = new Geometry("Box", b) |
||||
|
protected lazy val mat = Material( |
||||
|
assetManager = assetManager, |
||||
|
path = "Common/MatDefs/Misc/Unshaded.j3md" |
||||
|
) |
||||
|
|
||||
|
// def entity = _entity |
||||
|
// override def initialize(app: Application): Unit = { |
||||
|
// super.initialize(app) |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
override def init() = { |
||||
|
entityData |
||||
|
.createEntity() |
||||
|
.withComponents(TestComponent()) |
||||
|
// entityData.setComponents(x, TestComponent()) |
||||
|
val es = entityData.getEntities(classOf[TestComponent]) |
||||
|
println(es) |
||||
|
geom.setMaterial(mat) |
||||
|
rootNode.attachChild(geom) |
||||
|
|
||||
|
// geom.foreach(e => { |
||||
|
|
||||
|
// }) |
||||
|
} |
||||
|
|
||||
|
override def update(tpf: Float) = { |
||||
|
geom.rotate(0, 0.5f * tpf, 0) |
||||
|
geom.move(new Vector3f(0, 1 * tpf, 0)) |
||||
|
} |
||||
|
|
||||
|
override def cleanup(app: Application): Unit = { |
||||
|
// _entity.map(_.close()) |
||||
|
// _entity = None |
||||
|
} |
||||
|
|
||||
|
override def onEnable(): Unit = {} |
||||
|
|
||||
|
override def onDisable(): Unit = {} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object Material { |
||||
|
def apply( |
||||
|
color: String = "Color", |
||||
|
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue, |
||||
|
assetManager: AssetManager, |
||||
|
path: String |
||||
|
): Material = { |
||||
|
val mat = |
||||
|
new Material(assetManager, path) |
||||
|
mat.setColor(color, colorType) |
||||
|
mat |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@main |
||||
|
def main(): MyBaseState = new TestAppState() |
@ -0,0 +1,19 @@ |
|||||
|
{ |
||||
|
"record": "Weapon", |
||||
|
"values": { |
||||
|
"baseId": "4F00000062", |
||||
|
"weaponType": "sword", |
||||
|
"name": "Exquisite Steel Sword", |
||||
|
"attack": "40", |
||||
|
"weight": "20" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
val entity = ed.createEntity() |
||||
|
entity.setComponents( |
||||
|
Record("Weapon"), |
||||
|
WeaponType("Sword"), |
||||
|
Name("Exquisite Steel Sword"), |
||||
|
Attack(40), |
||||
|
Weight(20) |
||||
|
) |
@ -0,0 +1,62 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
import com.jme3.input.Action |
||||
|
|
||||
|
package object animation { |
||||
|
|
||||
|
implicit class AnimChannelWrap(val uval: AnimChannel) extends AnyVal { |
||||
|
|
||||
|
/** |
||||
|
* Set the current animation that is played by this AnimChannel. |
||||
|
* <p> |
||||
|
* See {@link #setAnim(java.lang.String, float)}. |
||||
|
* The blendTime argument by default is 150 milliseconds. |
||||
|
* |
||||
|
* @param action The action (name) of the animation to play |
||||
|
*/ |
||||
|
def setAnim(action: Action): Unit = uval.setAnim(action.name) |
||||
|
|
||||
|
/** |
||||
|
* Set the current animation that is played by this AnimChannel. |
||||
|
* <p> |
||||
|
* This resets the time to zero, and optionally blends the animation |
||||
|
* over <code>blendTime</code> seconds with the currently playing animation. |
||||
|
* Notice that this method will reset the control's speed to 1.0. |
||||
|
* |
||||
|
* @param action The action (name) of the animation to play |
||||
|
* @param blendTime The blend time over which to blend the new animation |
||||
|
* with the old one. If zero, then no blending will occur and the new |
||||
|
* animation will be applied instantly. |
||||
|
*/ |
||||
|
def setAnim(action: Action, blendTime: Float): Unit = uval.setAnim(action.name, blendTime) |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
implicit class AnimEventListenerWrap(val uval: AnimEventListener) extends AnyVal { |
||||
|
|
||||
|
/** |
||||
|
* Invoked when an animation "cycle" is done. For non-looping animations, |
||||
|
* this event is invoked when the animation is finished playing. For |
||||
|
* looping animations, this even is invoked each time the animation is restarted. |
||||
|
* |
||||
|
* @param control The control to which the listener is assigned. |
||||
|
* @param channel The channel being altered |
||||
|
* @param action The new animation action that is done. |
||||
|
*/ |
||||
|
def onAnimCycleDone(control: AnimControl, channel: AnimChannel, action: Action): Unit = |
||||
|
uval.onAnimCycleDone(control, channel, action.name) |
||||
|
|
||||
|
/** |
||||
|
* Invoked when a animation is set to play by the user on the given channel. |
||||
|
* |
||||
|
* @param control The control to which the listener is assigned. |
||||
|
* @param channel The channel being altered |
||||
|
* @param action The new animation action set. |
||||
|
*/ |
||||
|
def onAnimChange(control: AnimControl, channel: AnimChannel, action: Action): Unit = |
||||
|
uval.onAnimChange(control, channel, action.name) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/19/17. |
||||
|
*/ |
||||
|
package object app { |
||||
|
|
||||
|
implicit class SimpleApplicationWrap(val uval: SimpleApplication) extends AnyVal { |
||||
|
|
||||
|
//FIXME: proof of concept, remove later |
||||
|
def testWrap: String = uval.hashCode().toString |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
package com.jme3.input |
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/19/17. |
||||
|
*/ |
||||
|
final case class Action(name: String) extends AnyVal |
@ -0,0 +1,37 @@ |
|||||
|
package com.jme3.input |
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/19/17. |
||||
|
*/ |
||||
|
package object controls { |
||||
|
|
||||
|
implicit class ActionListenerWrap(val uval: ActionListener) extends AnyVal { |
||||
|
|
||||
|
/** |
||||
|
* Called when an input to which this listener is registered to is invoked. |
||||
|
* |
||||
|
* @param action The action (name) of the mapping that was invoked |
||||
|
* @param isPressed True if the action is "pressed", false otherwise |
||||
|
* @param tpf The time per frame value. |
||||
|
*/ |
||||
|
def onAction(action: Action, keyPressed: Boolean, tpf: Float): Unit = |
||||
|
uval.onAction(action.name, keyPressed, tpf) |
||||
|
} |
||||
|
|
||||
|
implicit class AnalogListenerWrap(val uval: AnalogListener) extends AnyVal { |
||||
|
|
||||
|
/** |
||||
|
* Called to notify the implementation that an analog event has occurred. |
||||
|
* |
||||
|
* The results of KeyTrigger and MouseButtonTrigger events will have tpf |
||||
|
* == value. |
||||
|
* |
||||
|
* @param action The action (name) of the mapping that was invoked |
||||
|
* @param value Value of the axis, from 0 to 1. |
||||
|
* @param tpf The time per frame value. |
||||
|
*/ |
||||
|
def onAnalog(action: Action, value: Float, tpf: Float): Unit = |
||||
|
uval.onAnalog(action.name, value, tpf) |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
import com.jme3.input.controls.{InputListener, Trigger} |
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/21/17. |
||||
|
*/ |
||||
|
package object input { |
||||
|
|
||||
|
implicit class InputManagerWrap(val uval: InputManager) extends AnyVal { |
||||
|
def addMapping(action: Action, triggers: Trigger*): Unit = |
||||
|
uval.addMapping(action.name, triggers: _*) |
||||
|
def addListener(listener: InputListener, actions: Action*): Unit = |
||||
|
uval.addListener(listener, actions.map(act => act.name): _*) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
import com.jme3.asset.AssetManager |
||||
|
|
||||
|
package object material { |
||||
|
|
||||
|
object Material { |
||||
|
def apply(contentMan: AssetManager, defName: String): Material = |
||||
|
new Material(contentMan, defName) |
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
package com.jme3.scene |
||||
|
|
||||
|
import com.jme3.animation.Skeleton |
||||
|
|
||||
|
package object debug { |
||||
|
|
||||
|
object SkeletonDebugger { |
||||
|
|
||||
|
/** |
||||
|
* Creates a debugger with no length data. The wires will be a connection between the bones' heads only. |
||||
|
* The points will show the bones' heads only and no dotted line of inter bones connection will be visible. |
||||
|
* @param name |
||||
|
* the name of the debugger's node |
||||
|
* @param skeleton |
||||
|
* the skeleton that will be shown |
||||
|
*/ |
||||
|
def apply(name: String, skeleton: Skeleton) = new SkeletonDebugger(name, skeleton) |
||||
|
} |
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
import com.jme3.scene.control.Control |
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/19/17. |
||||
|
*/ |
||||
|
package object scene { |
||||
|
|
||||
|
object Geometry { |
||||
|
|
||||
|
/** |
||||
|
* Create a geometry node with mesh data. |
||||
|
* The material of the geometry is null, it cannot |
||||
|
* be rendered until it is set. |
||||
|
* |
||||
|
* @param name The name of this geometry |
||||
|
* @param mesh The mesh data for this geometry |
||||
|
*/ |
||||
|
def apply(name: String, mesh: Mesh): Geometry = new Geometry(name, mesh) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object Node { |
||||
|
|
||||
|
/** |
||||
|
* Constructor instantiates a new <code>Node</code> with a default empty |
||||
|
* list for containing children. |
||||
|
* |
||||
|
* @param name the name of the scene element. This is required for |
||||
|
* identification and comparison purposes. |
||||
|
*/ |
||||
|
def apply(name: String): Node = new Node(name) |
||||
|
} |
||||
|
|
||||
|
implicit class NodeWrap(val uval: Node) extends AnyVal { |
||||
|
|
||||
|
def getControlMaybe[T <: Control](controlType: Class[T]): Option[T] = |
||||
|
Option(uval.getControl(controlType)) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
implicit class SpatialWrap(val uval: Spatial) extends AnyVal { |
||||
|
|
||||
|
def toNode: Either[ClassCastException, Node] = |
||||
|
uval match { |
||||
|
case ul: Node => Right(ul) |
||||
|
case ul => |
||||
|
Left( |
||||
|
new ClassCastException(s"Couldn't convert ${ul.getName} to Node") |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
package com.jme3.scene |
||||
|
|
||||
|
package object shape { |
||||
|
|
||||
|
object Box { |
||||
|
|
||||
|
/** |
||||
|
* Creates a new box. |
||||
|
* <p> |
||||
|
* The box has a center of 0,0,0 and extends in the out from the center by |
||||
|
* the given amount in <em>each</em> direction. So, for example, a box |
||||
|
* with extent of 0.5 would be the unit cube. |
||||
|
* |
||||
|
* @param xs the size of the box along the x axis, in both directions. |
||||
|
* @param ys the size of the box along the y axis, in both directions. |
||||
|
* @param zs the size of the box along the z axis, in both directions. |
||||
|
*/ |
||||
|
def apply(xs: Float, ys: Float, zs: Float): Box = new Box(xs, ys, zs) |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package com.jme3 |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Created by Brandon Barker on 6/21/17. |
||||
|
*/ |
||||
|
package object syntax { |
||||
|
|
||||
|
@specialized def discard[A](evaluateForSideEffectOnly: A): Unit = { |
||||
|
val _: A = evaluateForSideEffectOnly |
||||
|
() //Return unit to prevent warning due to discarding value |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
Hey guys, few days ago I discovered I could load objects created in scripts at runtime, and cast them to an interface to call their methods provided |
||||
|
1. both host program and script have access to the same interface via a common library |
||||
|
2. script object implements that interface |
||||
|
|
||||
|
I was thinking, maybe I could implement appstates in scripts to implement game mechanics and attach them to the state manager at runtime, and similarly for components of an ECS. What do you guys think? |
@ -0,0 +1,127 @@ |
|||||
|
package wow.doge.mygame |
||||
|
|
||||
|
import game.GameApp |
||||
|
import com.jme3.app.StatsAppState |
||||
|
|
||||
|
import akka.actor.typed.ActorSystem |
||||
|
import akka.actor.typed.SpawnProtocol |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.util.Timeout |
||||
|
import com.jme3.system.AppSettings |
||||
|
import wow.doge.mygame.game.GameAppActor |
||||
|
import wow.doge.mygame.scriptsystem.ScriptCachingActor |
||||
|
object Main extends App { |
||||
|
import java.util.logging.{Logger, Level} |
||||
|
Logger.getLogger("").setLevel(Level.SEVERE) |
||||
|
|
||||
|
// runner.runCode("""|println("starting scala script engine")""".stripMargin) |
||||
|
val gameApp = new GameApp( |
||||
|
// new EntityDataState(), |
||||
|
// new TestAppState(), |
||||
|
// new PlayerMovementState(), |
||||
|
// new FlyCamAppState(), |
||||
|
new StatsAppState() |
||||
|
) |
||||
|
val settings = new AppSettings(true) |
||||
|
// settings.setVSync(true) |
||||
|
settings.setFrameRate(144) |
||||
|
gameApp.setSettings(settings) |
||||
|
val actorSystem = ActorSystem(RootActor(gameApp), "rootActor") |
||||
|
// actorSystem.eventStream |
||||
|
// gameApp.start() |
||||
|
println("here 1") |
||||
|
// actorSystem.terminate() |
||||
|
// JMEExecutorService.shutdown() |
||||
|
// println("here 2") |
||||
|
//FIXME remove this |
||||
|
// System.exit(0) |
||||
|
} |
||||
|
|
||||
|
object RootActor { |
||||
|
def apply(app: GameApp): Behavior[SpawnProtocol.Command] = |
||||
|
Behaviors.setup { ctx => |
||||
|
ctx.log.debug("Starting root actor") |
||||
|
val testActor = ctx.spawn(TestActor(), "testActor") |
||||
|
val _ = ctx.spawn(GameAppActor(app), "gameAppActor") |
||||
|
|
||||
|
testActor ! TestActor.Test |
||||
|
SpawnProtocol() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object TestActor { |
||||
|
sealed trait Command |
||||
|
case object Test extends Command |
||||
|
private case object Done extends Command |
||||
|
// sealed trait Result |
||||
|
// case object Done extends Result |
||||
|
|
||||
|
import scala.concurrent.duration._ |
||||
|
implicit val timeout = Timeout(15.seconds) |
||||
|
// implicit val scheduler = |
||||
|
|
||||
|
def apply(): Behavior[Command] = |
||||
|
Behaviors.setup { ctx => |
||||
|
ctx.spawn(ScriptCachingActor(), "scriptCacher") |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Test => |
||||
|
// ctx.ask( |
||||
|
// router, |
||||
|
// ScriptActor.Compile( |
||||
|
// // os.pwd / "some.sc", |
||||
|
// os.pwd / "src" / "main" / "resources" / "hello2.main.kts", |
||||
|
// _ |
||||
|
// ) |
||||
|
// ) { |
||||
|
// case Success(value) => |
||||
|
// ctx.log.debug("Received Value") |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// Done |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(s"Received Error ${exception.getMessage()}") |
||||
|
// Done |
||||
|
// } |
||||
|
// val x = scriptStorer |
||||
|
// .askT( |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// )(timeout, ctx.system.scheduler) |
||||
|
|
||||
|
// ctx.ask( |
||||
|
// scriptStorer, |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// ) { |
||||
|
// case Success(value) => { |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// ctx.ask( |
||||
|
// scriptStorer, |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// ) { |
||||
|
// case Success(value) => { |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// Done |
||||
|
// } |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(exception.getMessage()) |
||||
|
// Done |
||||
|
// } |
||||
|
// Done |
||||
|
// } |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(exception.getMessage()) |
||||
|
// Done |
||||
|
// } |
||||
|
|
||||
|
Behaviors.same |
||||
|
case Done => Behaviors.same |
||||
|
} |
||||
|
|
||||
|
// SpawnProtocol() |
||||
|
// Behaviors.same |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
package wow.doge.mygame.components |
||||
|
|
||||
|
import com.simsilica.es.EntityComponent; |
||||
|
import wow.doge.mygame.math.ImVector3f |
||||
|
|
||||
|
final case class Position(location: ImVector3f) extends EntityComponent |
@ -0,0 +1,28 @@ |
|||||
|
package wow.doge.mygame.components |
||||
|
|
||||
|
import com.simsilica.es.EntityComponent |
||||
|
|
||||
|
final case class Tag(name: String) extends EntityComponent |
||||
|
|
||||
|
object Tag { |
||||
|
val SpaceShip = "SpaceShip" |
||||
|
val BasicInvader = "BasicInvader" |
||||
|
} |
||||
|
// public class Model implements EntityComponent { |
||||
|
// private final String name; |
||||
|
// public final static String SpaceShip = "SpaceShip"; |
||||
|
// public final static String BasicInvader = "BasicInvader"; |
||||
|
|
||||
|
// public Model(String name) { |
||||
|
// this.name = name; |
||||
|
// } |
||||
|
|
||||
|
// public String getName() { |
||||
|
// return name; |
||||
|
// } |
||||
|
|
||||
|
// @Override |
||||
|
// public String toString() { |
||||
|
// return "Model[" + name + "]"; |
||||
|
// } |
||||
|
// } |
@ -0,0 +1,11 @@ |
|||||
|
package wow.doge.mygame.components; |
||||
|
|
||||
|
import com.jme3.math.Vector3f; |
||||
|
import wow.doge.mygame.math.ImVector3f; |
||||
|
|
||||
|
//test java final case class instantiation |
||||
|
public class Test { |
||||
|
public void test() { |
||||
|
var pos = Position.apply(ImVector3f.apply(1, 1, 1)); |
||||
|
} |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
package wow.doge.mygame.components |
||||
|
|
||||
|
import com.simsilica.es.EntityComponent |
||||
|
|
||||
|
final case class TestComponent() extends EntityComponent |
@ -0,0 +1,139 @@ |
|||||
|
package wow.doge.mygame.events |
||||
|
|
||||
|
// import akka.event.ActorEventBus |
||||
|
// import akka.event.ManagedActorClassification |
||||
|
// import akka.event.ActorClassifier |
||||
|
import akka.actor.typed.ActorRef |
||||
|
// import akka.actor.ActorSystem |
||||
|
// import akka.event.EventBus |
||||
|
// import akka.util.Subclassification |
||||
|
// import java.util.concurrent.atomic.AtomicReference |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import scala.reflect.ClassTag |
||||
|
import akka.event.EventStream |
||||
|
|
||||
|
// private[events] final case class ClassificationMessage(ref: ActorRef, id: Int) |
||||
|
|
||||
|
// class ActorBusImpl(val system: ActorSystem, val busSize: Int) |
||||
|
// extends ActorEventBus |
||||
|
// with ActorClassifier |
||||
|
// with ManagedActorClassification { |
||||
|
// type Event = ClassificationMessage |
||||
|
|
||||
|
// // is used for extracting the classifier from the incoming events |
||||
|
// override protected def classify(event: Event): ActorRef = event.ref |
||||
|
|
||||
|
// // determines the initial size of the index data structure |
||||
|
// // used internally (i.e. the expected number of different classifiers) |
||||
|
// override protected def mapSize: Int = busSize |
||||
|
// } |
||||
|
|
||||
|
// class StartsWithSubclassification extends Subclassification[String] { |
||||
|
// override def isEqual(x: String, y: String): Boolean = |
||||
|
// x == y |
||||
|
|
||||
|
// override def isSubclass(x: String, y: String): Boolean = |
||||
|
// x.startsWith(y) |
||||
|
// } |
||||
|
|
||||
|
// import akka.event.SubchannelClassification |
||||
|
|
||||
|
// final case class MsgEnvelope(topic: String, payload: Any) |
||||
|
// import akka.actor.typed.scaladsl.adapter._ |
||||
|
|
||||
|
// /** |
||||
|
// * Publishes the payload of the MsgEnvelope when the topic of the |
||||
|
// * MsgEnvelope starts with the String specified when subscribing. |
||||
|
// */ |
||||
|
// class SubchannelBusImpl extends EventBus with SubchannelClassification { |
||||
|
// type Event = Any |
||||
|
// type Classifier = Class[_] |
||||
|
// type Subscriber = ActorRef |
||||
|
|
||||
|
// // Subclassification is an object providing `isEqual` and `isSubclass` |
||||
|
// // to be consumed by the other methods of this classifier |
||||
|
// // override protected val subclassification: Subclassification[Classifier] = |
||||
|
// // new StartsWithSubclassification |
||||
|
|
||||
|
// private val initiallySubscribedOrUnsubscriber = |
||||
|
// new AtomicReference[Either[Set[ActorRef], ActorRef]](Left(Set.empty)) |
||||
|
|
||||
|
// override protected implicit val subclassification |
||||
|
// : Subclassification[Classifier] = new Subclassification[Class[_]] { |
||||
|
// def isEqual(x: Class[_], y: Class[_]) = x == y |
||||
|
// def isSubclass(x: Class[_], y: Class[_]) = y.isAssignableFrom(x) |
||||
|
// } |
||||
|
|
||||
|
// // is used for extracting the classifier from the incoming events |
||||
|
// override protected def classify(event: Event): Classifier = event.getClass() |
||||
|
|
||||
|
// // will be invoked for each event for all subscribers which registered |
||||
|
// // themselves for the event’s classifier |
||||
|
// override protected def publish(event: Event, subscriber: Subscriber): Unit = { |
||||
|
// // subscriber ! event.payload |
||||
|
// subscriber ! event |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
object EventBus { |
||||
|
sealed trait Command[A] |
||||
|
final case class Publish[A, E <: A](event: E, publisher: ActorRef[_]) |
||||
|
extends Command[A] |
||||
|
|
||||
|
/** |
||||
|
* Subscribe a typed actor to listen for types or subtypes of E |
||||
|
* by sending this command to the [[akka.actor.typed.ActorSystem.eventStream]]. |
||||
|
* |
||||
|
* ==Simple example== |
||||
|
* {{{ |
||||
|
* sealed trait A |
||||
|
* case object A1 extends A |
||||
|
* //listen for all As |
||||
|
* def subscribe(actorSystem: ActorSystem[_], actorRef: ActorRef[A]) = |
||||
|
* actorSystem.eventStream ! EventStream.Subscribe(actorRef) |
||||
|
* //listen for A1s only |
||||
|
* def subscribe(actorSystem: ActorSystem[_], actorRef: ActorRef[A]) = |
||||
|
* actorSystem.eventStream ! EventStream.Subscribe[A1](actorRef) |
||||
|
* }}} |
||||
|
*/ |
||||
|
final case class Subscribe[A, E <: A](subscriber: ActorRef[E])(implicit |
||||
|
classTag: ClassTag[E] |
||||
|
) extends Command[A] { |
||||
|
|
||||
|
def topic: Class[_] = classTag.runtimeClass |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Unsubscribe an actor ref from the event stream |
||||
|
* by sending this command to the [[akka.actor.typed.ActorSystem.eventStream]]. |
||||
|
*/ |
||||
|
final case class Unsubscribe[A, E <: A](subscriber: ActorRef[E]) |
||||
|
extends Command[A] |
||||
|
|
||||
|
def apply[A](): Behavior[EventBus.Command[A]] = |
||||
|
Behaviors.setup { ctx => |
||||
|
val eventStream = new EventStream(ctx.system.classicSystem) |
||||
|
new EventBus().eventStreamBehavior(eventStream) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class EventBus[B] { |
||||
|
import akka.actor.typed.scaladsl.adapter._ |
||||
|
|
||||
|
private def eventStreamBehavior( |
||||
|
eventStream: akka.event.EventStream |
||||
|
): Behavior[EventBus.Command[B]] = |
||||
|
Behaviors.receiveMessage { |
||||
|
case EventBus.Publish(event, publisher) => |
||||
|
eventStream.publish(event) |
||||
|
Behaviors.same |
||||
|
case s @ EventBus.Subscribe(subscriber) => |
||||
|
eventStream.subscribe(subscriber.toClassic, s.topic) |
||||
|
Behaviors.same |
||||
|
case EventBus.Unsubscribe(subscriber) => |
||||
|
eventStream.unsubscribe(subscriber.toClassic) |
||||
|
Behaviors.same |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
package wow.doge.mygame.events |
||||
|
|
||||
|
// object Test { |
||||
|
|
||||
|
// Events.BulletFired |
||||
|
// } |
||||
|
|
||||
|
object Events { |
||||
|
sealed trait Event |
||||
|
case object BulletFired extends Event |
||||
|
// type BulletFired = BulletFired.type |
||||
|
case class EventWithData(data: Int) extends Event |
||||
|
|
||||
|
sealed trait Tick extends Event |
||||
|
case object RenderTick extends Tick |
||||
|
case object PhysicsTick extends Tick |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
package wow.doge.mygame.events |
||||
|
|
||||
|
trait EventsModule {} |
@ -0,0 +1,5 @@ |
|||||
|
package wow.doge.mygame.executors |
||||
|
|
||||
|
trait ExecutorsModule { |
||||
|
lazy val schedulers = new Schedulers() |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
package wow.doge.mygame.executors |
||||
|
|
||||
|
import akka.dispatch.{ |
||||
|
DispatcherPrerequisites, |
||||
|
ExecutorServiceFactory, |
||||
|
ExecutorServiceConfigurator |
||||
|
} |
||||
|
import com.typesafe.config.Config |
||||
|
import java.util.concurrent.{ |
||||
|
ExecutorService, |
||||
|
AbstractExecutorService, |
||||
|
ThreadFactory, |
||||
|
TimeUnit |
||||
|
} |
||||
|
import java.util.Collections |
||||
|
import javax.swing.SwingUtilities |
||||
|
import javafx.application.Platform |
||||
|
import monix.execution.Scheduler |
||||
|
import scala.concurrent.ExecutionContext |
||||
|
import java.util.concurrent.Executor |
||||
|
import wow.doge.mygame.Main |
||||
|
|
||||
|
// First we wrap invokeLater/runLater as an ExecutorService |
||||
|
trait GUIExecutorService extends AbstractExecutorService { |
||||
|
def execute(command: Runnable): Unit |
||||
|
|
||||
|
def shutdown(): Unit = () |
||||
|
|
||||
|
def shutdownNow() = Collections.emptyList[Runnable] |
||||
|
|
||||
|
def isShutdown = false |
||||
|
|
||||
|
def isTerminated = false |
||||
|
|
||||
|
def awaitTermination(l: Long, timeUnit: TimeUnit) = true |
||||
|
} |
||||
|
|
||||
|
object JavaFXExecutorService extends GUIExecutorService { |
||||
|
override def execute(command: Runnable) = Platform.runLater(command) |
||||
|
} |
||||
|
|
||||
|
object SwingExecutorService extends GUIExecutorService { |
||||
|
override def execute(command: Runnable) = SwingUtilities.invokeLater(command) |
||||
|
} |
||||
|
|
||||
|
object JMEExecutorService extends GUIExecutorService { |
||||
|
override def execute(command: Runnable) = Main.gameApp.enqueue(command) |
||||
|
} |
||||
|
|
||||
|
class JavaFXEventThreadExecutorServiceConfigurator( |
||||
|
config: Config, |
||||
|
prerequisites: DispatcherPrerequisites |
||||
|
) extends ExecutorServiceConfigurator(config, prerequisites) { |
||||
|
private val f = new ExecutorServiceFactory { |
||||
|
def createExecutorService: ExecutorService = JavaFXExecutorService |
||||
|
} |
||||
|
|
||||
|
def createExecutorServiceFactory( |
||||
|
id: String, |
||||
|
threadFactory: ThreadFactory |
||||
|
): ExecutorServiceFactory = f |
||||
|
} |
||||
|
|
||||
|
class JMEThreadExecutorServiceConfigurator( |
||||
|
config: Config, |
||||
|
prerequisites: DispatcherPrerequisites |
||||
|
) extends ExecutorServiceConfigurator(config, prerequisites) { |
||||
|
private val f = new ExecutorServiceFactory { |
||||
|
def createExecutorService: ExecutorService = JMEExecutorService |
||||
|
} |
||||
|
|
||||
|
def createExecutorServiceFactory( |
||||
|
id: String, |
||||
|
threadFactory: ThreadFactory |
||||
|
): ExecutorServiceFactory = f |
||||
|
} |
||||
|
|
||||
|
// Then we create an ExecutorServiceConfigurator so that Akka can use our SwingExecutorService for the dispatchers |
||||
|
class SwingEventThreadExecutorServiceConfigurator( |
||||
|
config: Config, |
||||
|
prerequisites: DispatcherPrerequisites |
||||
|
) extends ExecutorServiceConfigurator(config, prerequisites) { |
||||
|
private val f = new ExecutorServiceFactory { |
||||
|
def createExecutorService: ExecutorService = SwingExecutorService |
||||
|
} |
||||
|
|
||||
|
def createExecutorServiceFactory( |
||||
|
id: String, |
||||
|
threadFactory: ThreadFactory |
||||
|
): ExecutorServiceFactory = f |
||||
|
} |
||||
|
|
||||
|
object JFXExecutionContexts { |
||||
|
val javaFxExecutionContext: ExecutionContext = |
||||
|
ExecutionContext.fromExecutor(new Executor { |
||||
|
def execute(command: Runnable): Unit = { |
||||
|
Platform.runLater(command) |
||||
|
} |
||||
|
}) |
||||
|
val fxScheduler = |
||||
|
Scheduler(javaFxExecutionContext) |
||||
|
|
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
package wow.doge.mygame.executors |
||||
|
|
||||
|
import monix.execution.Scheduler |
||||
|
|
||||
|
final case class Schedulers( |
||||
|
blockingIO: Scheduler = Scheduler.io(), |
||||
|
cpu: Scheduler = Scheduler.global, |
||||
|
fx: Scheduler = JFXExecutionContexts.fxScheduler, |
||||
|
jme: Option[Scheduler] = None |
||||
|
) |
@ -0,0 +1,109 @@ |
|||||
|
package wow.doge.mygame.game |
||||
|
|
||||
|
import com.jme3.app.SimpleApplication |
||||
|
|
||||
|
import com.jme3.app.state.AppState |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
|
||||
|
object Greeter { |
||||
|
final case class Greet(whom: String, replyTo: ActorRef[Greeted]) |
||||
|
final case class Greeted(whom: String, from: ActorRef[Greet]) |
||||
|
|
||||
|
def apply(): Behavior[Greet] = |
||||
|
Behaviors.receive { (context, message) => |
||||
|
// context.log.info("Hello {}!", message.whom) |
||||
|
//#greeter-send-messages |
||||
|
message.replyTo ! Greeted(message.whom, context.self) |
||||
|
//#greeter-send-messages |
||||
|
Behaviors.same |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class GameApp( |
||||
|
// actorSystem: ActorSystem[SpawnProtocol.Command], |
||||
|
appStates: AppState* |
||||
|
) extends SimpleApplication(appStates: _*) { |
||||
|
// implicit val timeout = Timeout(10.seconds) |
||||
|
// implicit val scheduler = actorSystem.scheduler |
||||
|
|
||||
|
override def simpleInitApp(): Unit = { |
||||
|
|
||||
|
// val ship = ed.createEntity() |
||||
|
// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData()) |
||||
|
// val mbState = Try( |
||||
|
// stateManager() |
||||
|
// .state[TestAppState]() |
||||
|
// .entity |
||||
|
// ).toOption.flatten.toRight(println("empty")) |
||||
|
// // .flatMap(_.entity) |
||||
|
// val x = mbState.flatMap( |
||||
|
// _.query |
||||
|
// .filter[TestComponent]("name", new Object()) |
||||
|
// // .filterOr[TestEntity]( |
||||
|
// // Filters |
||||
|
// // .fieldEquals(classOf[TestEntity], "", null) |
||||
|
// // ) |
||||
|
// .component[Tag]() |
||||
|
// .component[TestComponent]() |
||||
|
// .result |
||||
|
// .toRight(println("failed")) |
||||
|
// ) |
||||
|
|
||||
|
// rootNode |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// .child(geom) |
||||
|
// Future(println("hello"))(jmeEC(this)) |
||||
|
// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask( |
||||
|
// SpawnProtocol.Spawn( |
||||
|
// behavior = Greeter(), |
||||
|
// name = "listener", |
||||
|
// DispatcherSelector.fromConfig("jme-dispatcher"), |
||||
|
// _ |
||||
|
// ) |
||||
|
// ) |
||||
|
|
||||
|
// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println)) |
||||
|
|
||||
|
} |
||||
|
override def simpleUpdate(tpf: Float): Unit = { |
||||
|
// val rot2 = rot.fromAngleAxis(FastMath.PI, new Vector3f(0, 0, 1)) |
||||
|
// val rotation = geom.getLocalRotation() |
||||
|
// rotation.add(rot2) |
||||
|
// geom.rotate(rot2) |
||||
|
|
||||
|
// geom.updateModelBound() |
||||
|
// geom.updateGeometricState() |
||||
|
} |
||||
|
|
||||
|
// override def stop(): Unit = { |
||||
|
// actorSystem.terminate() |
||||
|
// super.stop() |
||||
|
// } |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object GameApp { |
||||
|
// def myExec(app: SimpleApplication, command: Runnable) = { |
||||
|
// app.enqueue(command) |
||||
|
// } |
||||
|
// val javaFxExecutionContext: ExecutionContext = |
||||
|
// ExecutionContext.fromExecutor(new Executor { |
||||
|
// def execute(command: Runnable): Unit = { |
||||
|
// Platform.runLater(command) |
||||
|
// } |
||||
|
// }) |
||||
|
// def jmeEC(app: SimpleApplication): ExecutionContext = |
||||
|
// ExecutionContext.fromExecutor(new Executor { |
||||
|
// override def execute(command: Runnable): Unit = app.enqueue(command) |
||||
|
// }) |
||||
|
|
||||
|
// def jmeScheduler(app: SimpleApplication) = Sch |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
package wow.doge.mygame.game |
||||
|
|
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import wow.doge.mygame.state.MovementActor |
||||
|
import wow.doge.mygame.state.PlayerMovementState2 |
||||
|
import wow.doge.mygame.state.MovementActorTimer |
||||
|
import com.jme3.scene.shape.Box |
||||
|
import com.jme3.scene.Geometry |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
import wow.doge.mygame.events.EventBus |
||||
|
import wow.doge.mygame.events.Events |
||||
|
import wow.doge.mygame.state.ImMovementActor |
||||
|
|
||||
|
object GameAppActor { |
||||
|
|
||||
|
sealed trait Command |
||||
|
def apply(app: GameApp) = |
||||
|
Behaviors.setup[Command] { ctx => |
||||
|
lazy val b = new Box(1, 1, 1) |
||||
|
lazy val geom = new Geometry("Box", b) |
||||
|
val movementActor = |
||||
|
ctx.spawn( |
||||
|
MovementActor(MovementActor.Props(app, geom)), |
||||
|
"movementActor" |
||||
|
// DispatcherSelector.fromConfig("jme-dispatcher") |
||||
|
) |
||||
|
|
||||
|
val movementActorTimer = ctx.spawn( |
||||
|
MovementActorTimer(movementActor), |
||||
|
"movementActorTimer" |
||||
|
) |
||||
|
val imMovementActor = ctx.spawn( |
||||
|
ImMovementActor(ImMovementActor.Props(app, geom)), |
||||
|
"imMovementActor" |
||||
|
) |
||||
|
|
||||
|
val subscribingActor = ctx.spawn(SubscribingActor(), "subscriber-1") |
||||
|
|
||||
|
val eventBus = |
||||
|
ctx.spawn(Behaviors.logMessages(EventBus[Events.Tick]()), "eventBus1") |
||||
|
|
||||
|
eventBus ! EventBus.Subscribe(subscribingActor) |
||||
|
|
||||
|
eventBus ! EventBus.Publish(Events.PhysicsTick, ctx.self) |
||||
|
|
||||
|
app |
||||
|
.getStateManager() |
||||
|
.attach( |
||||
|
new PlayerMovementState2( |
||||
|
movementActor, |
||||
|
movementActorTimer, |
||||
|
imMovementActor, |
||||
|
geom |
||||
|
) |
||||
|
) |
||||
|
app.start() |
||||
|
Behaviors.stopped |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object SubscribingActor { |
||||
|
def apply() = |
||||
|
Behaviors.receive[Events.PhysicsTick.type] { (ctx, msg) => |
||||
|
ctx.log.debug(s"received event $msg") |
||||
|
Behaviors.same |
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
package wow.doge.mygame.implicits |
||||
|
|
||||
|
import com.simsilica.es.ComponentFilter |
||||
|
import com.simsilica.es.EntityComponent |
||||
|
import com.simsilica.es.EntityData |
||||
|
import com.simsilica.es.EntitySet |
||||
|
import com.simsilica.es.Filters |
||||
|
import scala.reflect.ClassTag |
||||
|
import scala.util.Try |
||||
|
|
||||
|
class EntityQuery(ed: EntityData) { |
||||
|
private var cfilter: Option[ComponentFilter[_ <: EntityComponent]] = None |
||||
|
private val buf = collection.mutable.ListBuffer.empty[Class[_]] |
||||
|
|
||||
|
def filter[T <: EntityComponent](field: String, value: Object)(implicit |
||||
|
ev: ClassTag[T] |
||||
|
): EntityQuery = { |
||||
|
val c = ev.runtimeClass.asInstanceOf[Class[T]] |
||||
|
cfilter = Try(Filters.fieldEquals(c, field, value)).toOption |
||||
|
this |
||||
|
} |
||||
|
|
||||
|
def filterOr[T <: EntityComponent](operands: ComponentFilter[_ <: T]*)( |
||||
|
implicit ev: ClassTag[T] |
||||
|
): EntityQuery = { |
||||
|
val c = ev.runtimeClass.asInstanceOf[Class[T]] |
||||
|
cfilter = Try(Filters.or(c, operands: _*)).toOption |
||||
|
this |
||||
|
} |
||||
|
|
||||
|
def filterAnd[T <: EntityComponent](operands: ComponentFilter[_ <: T]*)( |
||||
|
implicit ev: ClassTag[T] |
||||
|
): EntityQuery = { |
||||
|
val c = ev.runtimeClass.asInstanceOf[Class[T]] |
||||
|
cfilter = Try(Filters.and(c, operands: _*)).toOption |
||||
|
this |
||||
|
} |
||||
|
|
||||
|
def component[T <: EntityComponent]()(implicit |
||||
|
ev: ClassTag[T] |
||||
|
): EntityQuery = { |
||||
|
val c = ev.runtimeClass |
||||
|
buf += c |
||||
|
this |
||||
|
} |
||||
|
|
||||
|
def components[T <: EntityComponent](lst: Class[T]*): EntitySet = { |
||||
|
ed.getEntities(lst: _*) |
||||
|
} |
||||
|
|
||||
|
def result: EntitySet = |
||||
|
cfilter.fold(ed.getEntities(buf.toList: _*)) { filters => |
||||
|
ed.getEntities(filters, buf.toList: _*) |
||||
|
} |
||||
|
} |
@ -0,0 +1,175 @@ |
|||||
|
package wow.doge.mygame |
||||
|
|
||||
|
import com.jme3.app.SimpleApplication |
||||
|
import com.jme3.app.state.AppStateManager |
||||
|
import scala.reflect.ClassTag |
||||
|
import com.jme3.app.state.AppState |
||||
|
import com.jme3.scene.Node |
||||
|
import com.jme3.scene.Spatial |
||||
|
import com.simsilica.es.EntityData |
||||
|
import com.simsilica.es.EntityComponent |
||||
|
import com.simsilica.es.EntityId |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import akka.util.Timeout |
||||
|
import akka.actor.typed.Scheduler |
||||
|
import monix.eval.Task |
||||
|
import com.jme3.input.InputManager |
||||
|
import com.jme3.input.controls.Trigger |
||||
|
import com.jme3.input.controls.InputListener |
||||
|
import com.jme3.math.Vector3f |
||||
|
import wow.doge.mygame.math.ImVector3f |
||||
|
import com.jme3.scene.Geometry |
||||
|
import wow.doge.mygame.state.CardinalDirection |
||||
|
import wow.doge.mygame.state.CanMove |
||||
|
import com.jme3.renderer.Camera |
||||
|
|
||||
|
package object implicits { |
||||
|
implicit class StateManagerExt(val sm: AppStateManager) extends AnyVal { |
||||
|
def state[S <: AppState]()(implicit c: ClassTag[S]): S = |
||||
|
sm.getState(c.runtimeClass.asInstanceOf[Class[S]]) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
implicit class SimpleApplicationExt(val sa: SimpleApplication) |
||||
|
extends AnyVal { |
||||
|
def stateManager() = sa.getStateManager() |
||||
|
} |
||||
|
|
||||
|
implicit class NodeExt(val n: Node) extends AnyVal { |
||||
|
def child(s: Spatial): Node = { |
||||
|
n.attachChild(s) |
||||
|
n |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
implicit class EntityDataExt(val ed: EntityData) extends AnyVal { |
||||
|
|
||||
|
def query = new EntityQuery(ed) |
||||
|
|
||||
|
// def entities[T <: EntityComponent](entities: Seq[T]) |
||||
|
} |
||||
|
|
||||
|
implicit class EntityExt(val e: EntityId) extends AnyVal { |
||||
|
def withComponents(classes: EntityComponent*)(implicit |
||||
|
ed: EntityData |
||||
|
): EntityId = { |
||||
|
ed.setComponents(e, classes: _*) |
||||
|
e |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
implicit class ActorRefExt[Req](val a: ActorRef[Req]) extends AnyVal { |
||||
|
import akka.actor.typed.scaladsl.AskPattern._ |
||||
|
def askT[Res]( |
||||
|
replyTo: ActorRef[Res] => Req |
||||
|
)(implicit timeout: Timeout, scheduler: Scheduler): Task[Res] = { |
||||
|
Task.deferFuture(a.ask(replyTo)(timeout, scheduler)) |
||||
|
} |
||||
|
} |
||||
|
// def ?[Res](replyTo: ActorRef[Res] => Req)(implicit timeout: Timeout, scheduler: Scheduler): Future[Res] = { |
||||
|
// ask(replyTo)(timeout, scheduler) |
||||
|
// } |
||||
|
|
||||
|
implicit class InputManagerExt(val inputManager: InputManager) |
||||
|
extends AnyVal { |
||||
|
def withMapping(mapping: String, triggers: Trigger*): InputManager = { |
||||
|
inputManager.addMapping(mapping, triggers: _*) |
||||
|
inputManager |
||||
|
} |
||||
|
|
||||
|
def withListener(listener: InputListener, mappings: String*) = { |
||||
|
inputManager.addListener(listener, mappings: _*) |
||||
|
inputManager |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
implicit class Vector3fExt(val v: Vector3f) extends AnyVal { |
||||
|
def +=(that: Vector3f) = v.addLocal(that) |
||||
|
def *=(that: Vector3f) = v.multLocal(that) |
||||
|
def -=(that: Vector3f) = v.subtractLocal(that) |
||||
|
def /=(that: Vector3f) = v.divideLocal(that) |
||||
|
def unary_- = v.negateLocal() |
||||
|
def immutable = ImVector3f(v.x, v.y, v.z) |
||||
|
} |
||||
|
|
||||
|
implicit class ImVector3fExt(val v: ImVector3f) extends AnyVal { |
||||
|
def +(that: ImVector3f) = v.copy(v.x + that.x, v.y + that.y, v.z + that.z) |
||||
|
def *(that: ImVector3f) = v.copy(v.x * that.x, v.y * that.y, v.z * that.z) |
||||
|
def *(f: Float): ImVector3f = |
||||
|
// v.copy(v.x * f, v.y * f, v.x * f) |
||||
|
v * ImVector3f(f, f, f) |
||||
|
def -(that: ImVector3f) = v.copy(v.x - that.x, v.y - that.y, v.z - that.z) |
||||
|
def /(that: ImVector3f) = v.copy(v.x / that.x, v.y / that.y, v.z / that.z) |
||||
|
def unary_- = v.copy(-v.x, -v.y, -v.z) |
||||
|
// def unary_-(that: ImVector3f) = this.copy(this.x, this.y, this.z) |
||||
|
def mutable = new Vector3f(v.x, v.y, v.z) |
||||
|
} |
||||
|
|
||||
|
// implicit val implVector3fForVector3 = new Vector3[Vector3f] { |
||||
|
// override def +(implicit v: Vector3f, that: com.jme3.math.Vector3f): Unit = |
||||
|
// v += that |
||||
|
|
||||
|
// override def *(implicit v: Vector3f, that: Vector3f): Unit = v *= that |
||||
|
|
||||
|
// override def -(implicit v: Vector3f, that: Vector3f): Unit = v -= that |
||||
|
|
||||
|
// override def /(implicit v: Vector3f, that: Vector3f): Unit = v /= that |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
// implicit val implImVector3fForVector3 = new Vector3[ImVector3f] { |
||||
|
// override def +(implicit v: ImVector3f, that: ImVector3f): Unit = |
||||
|
// v + that |
||||
|
|
||||
|
// override def *(implicit v: ImVector3f, that: ImVector3f): Unit = v * that |
||||
|
|
||||
|
// override def -(implicit v: ImVector3f, that: ImVector3f): Unit = v - that |
||||
|
|
||||
|
// override def /(implicit v: ImVector3f, that: ImVector3f): Unit = v / that |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
// def test[T](v: T)(implicit ev: Vector3[T]) = { |
||||
|
// import ev._ |
||||
|
// ev.+ |
||||
|
// } |
||||
|
|
||||
|
implicit val implCanMoveForGeom = new CanMove[Geometry] { |
||||
|
override def getDirection( |
||||
|
cam: Camera, |
||||
|
cardinalDir: CardinalDirection |
||||
|
): ImVector3f = { |
||||
|
val camDir = |
||||
|
cam.getDirection().immutable * 0.6f |
||||
|
val camLeft = cam.getLeft().immutable * 0.4f |
||||
|
|
||||
|
val zero = ImVector3f.ZERO |
||||
|
val dir = cardinalDir |
||||
|
val walkDir = { |
||||
|
val mutWalkDir = new Vector3f() |
||||
|
if (dir.left) { |
||||
|
// ctx.log.trace("left") |
||||
|
mutWalkDir += (zero + camLeft).mutable |
||||
|
} |
||||
|
if (dir.right) { |
||||
|
// ctx.log.trace("right") |
||||
|
mutWalkDir += (zero + -camLeft).mutable |
||||
|
} |
||||
|
if (dir.up) { |
||||
|
// ctx.log.trace("up") |
||||
|
mutWalkDir += (zero + camDir).mutable |
||||
|
} |
||||
|
if (dir.down) { |
||||
|
// ctx.log.trace("down") |
||||
|
mutWalkDir += (zero + -camDir).mutable |
||||
|
} |
||||
|
mutWalkDir.immutable |
||||
|
} |
||||
|
walkDir |
||||
|
} |
||||
|
override def move(geom: Geometry, direction: ImVector3f): Unit = { |
||||
|
val v = geom.getLocalTranslation() |
||||
|
geom.setLocalTranslation(v += direction.mutable) |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
package wow.doge.mygame.math |
||||
|
|
||||
|
case class ImVector3f(x: Float = 0f, y: Float = 0f, z: Float = 0f) |
||||
|
|
||||
|
object ImVector3f { |
||||
|
val ZERO = ImVector3f(0, 0, 0) |
||||
|
val UNIT_X = ImVector3f(1, 0, 0) |
||||
|
val UNIT_Y = ImVector3f(0, 1, 0) |
||||
|
val UNIT_Z = ImVector3f(0, 0, 1) |
||||
|
|
||||
|
} |
@ -0,0 +1,157 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import ammonite.Main |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import com.jme3.app.state.AppState |
||||
|
import ammonite.runtime.Storage.Folder |
||||
|
import ammonite.main.Defaults |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import ammonite.util.Res.Success |
||||
|
import javax.script.ScriptEngine |
||||
|
import javax.script.ScriptEngineManager |
||||
|
import scala.util.Try |
||||
|
import cats.implicits._ |
||||
|
|
||||
|
object ScriptActor { |
||||
|
sealed trait Result |
||||
|
final case class AppStateResult(state: AppState) extends Result |
||||
|
final case class Error(reason: String) extends Result |
||||
|
|
||||
|
sealed trait Command |
||||
|
final case class Compile(path: os.Path, sender: ActorRef[Result]) |
||||
|
extends Command |
||||
|
|
||||
|
final case class CompileAny( |
||||
|
path: os.Path, |
||||
|
result: ActorRef[Either[Error, Any]] |
||||
|
) extends Command |
||||
|
|
||||
|
def defaultScalaRunner() = |
||||
|
ammonite |
||||
|
.Main( |
||||
|
storageBackend = new Folder( |
||||
|
// os.pwd / "target" |
||||
|
Defaults.ammoniteHome, |
||||
|
isRepl = false |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
def defaultKotlinRunner(): ScriptEngine = { |
||||
|
val manager = new ScriptEngineManager() |
||||
|
val engine = manager.getEngineByExtension("main.kts") |
||||
|
engine |
||||
|
} |
||||
|
|
||||
|
def apply( |
||||
|
scalaRunner: Main = defaultScalaRunner(), |
||||
|
kotlinRunner: ScriptEngine = defaultKotlinRunner() |
||||
|
// parent: ActorRef[ScriptStoringActor.Command] |
||||
|
): Behavior[ScriptActor.Command] = |
||||
|
Behaviors.setup(ctx => |
||||
|
new ScriptActor(scalaRunner, kotlinRunner, ctx).receiveMessage |
||||
|
) |
||||
|
|
||||
|
sealed trait ScriptType |
||||
|
case object ScalaType extends ScriptType |
||||
|
case object KotlinType extends ScriptType |
||||
|
case object GroovyType extends ScriptType |
||||
|
|
||||
|
def determineScriptType(path: os.Path): Either[Error, ScriptType] = |
||||
|
path.toString match { |
||||
|
case s if s.endsWith(".sc") => Right(ScalaType) |
||||
|
case s if s.endsWith(".main.kts") => Right(KotlinType) |
||||
|
case s if s.endsWith(".groovy") => Right(GroovyType) |
||||
|
case _ => Left(Error("Unknown script type")) |
||||
|
} |
||||
|
|
||||
|
def runScala(path: os.Path, scalaRunner: ammonite.Main): Either[Error, Any] = |
||||
|
scalaRunner |
||||
|
.runScript( |
||||
|
path, |
||||
|
Seq.empty |
||||
|
) |
||||
|
._1 match { |
||||
|
case ammonite.util.Res.Exception(t, msg) => Left(Error(msg)) |
||||
|
|
||||
|
case Success(obj) => Right(obj) |
||||
|
|
||||
|
case _ => Left(Error("Failed to run script")) |
||||
|
} |
||||
|
|
||||
|
def runKotlin(path: os.Path, kotlinRunner: ScriptEngine): Either[Error, Any] = |
||||
|
Try(kotlinRunner.eval(os.read(path))).toEither.leftMap(t => |
||||
|
Error(t.getMessage()) |
||||
|
) |
||||
|
|
||||
|
def runGroovy(path: os.Path): Either[Error, Any] = |
||||
|
Left(Error("Not implemented yet")) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class ScriptActor( |
||||
|
val scalaRunner: Main, |
||||
|
val kotlinRunner: ScriptEngine, |
||||
|
// parent: ActorRef[ScriptStoringActor.Command], |
||||
|
context: ActorContext[ScriptActor.Command] |
||||
|
) { |
||||
|
import ScriptActor._ |
||||
|
|
||||
|
def receiveMessage: Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Compile(path, sender) => |
||||
|
context.log.debug(s"Received $path") |
||||
|
val res = getScript(path) |
||||
|
sender ! res |
||||
|
Behaviors.same |
||||
|
// case CompileScripts(sender, paths) => |
||||
|
case CompileAny(path, requester) => |
||||
|
context.log.debug(s"Received $path") |
||||
|
val res = getScript2(path) |
||||
|
context.log.debug(s"result = $res") |
||||
|
requester ! res |
||||
|
// parent ! ScriptStoringActor.Put(path, res) |
||||
|
Behaviors.same |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def getScript(path: os.Path) = { |
||||
|
val res = determineScriptType(path) match { |
||||
|
case Right(ScalaType) => runScala(path, scalaRunner) |
||||
|
case Right(KotlinType) => runKotlin(path, kotlinRunner) |
||||
|
case Right(GroovyType) => runGroovy(path) |
||||
|
case l @ Left(err) => l |
||||
|
} |
||||
|
|
||||
|
res match { |
||||
|
case Left(err) => err |
||||
|
case Right(obj) => |
||||
|
obj match { |
||||
|
case s: MyBaseState => AppStateResult(s) |
||||
|
case _ => Error("Class in script does not match known types") |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def getScript2(path: os.Path): Either[Error, Any] = { |
||||
|
val res = determineScriptType(path) match { |
||||
|
case Right(ScalaType) => runScala(path, scalaRunner) |
||||
|
case Right(KotlinType) => runKotlin(path, kotlinRunner) |
||||
|
case Right(GroovyType) => runGroovy(path) |
||||
|
case l @ Left(err) => l |
||||
|
} |
||||
|
|
||||
|
// res match { |
||||
|
// case Left(err) => err |
||||
|
// case Right(obj) => |
||||
|
// obj match { |
||||
|
// case s: MyBaseState => AppStateResult(s) |
||||
|
// case _ => Error("Class in script does not match known types") |
||||
|
// } |
||||
|
// } |
||||
|
res |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,166 @@ |
|||||
|
package wow.doge.mygame.scriptsystem |
||||
|
|
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import akka.actor.typed.scaladsl.PoolRouter |
||||
|
import akka.actor.typed.scaladsl.Routers |
||||
|
import wow.doge.mygame.state.ScriptActor |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.util.Timeout |
||||
|
import scala.util.Success |
||||
|
import scala.util.Failure |
||||
|
import akka.actor.typed.SupervisorStrategy |
||||
|
|
||||
|
object ScriptCachingActor { |
||||
|
|
||||
|
/** |
||||
|
* aka script representation |
||||
|
*/ |
||||
|
type ScriptRepr = Any |
||||
|
type ScriptsMap = Map[os.Path, ScriptRepr] |
||||
|
type ScriptResult = Either[ScriptActor.Error, ScriptRepr] |
||||
|
|
||||
|
sealed trait Command |
||||
|
final case class Get( |
||||
|
scriptPath: os.Path, |
||||
|
requester: ActorRef[ScriptResult] |
||||
|
) extends Command |
||||
|
final case class GetMap(requester: ActorRef[ScriptsMap]) extends Command |
||||
|
final case class Put(scriptPath: os.Path, script: ScriptRepr) extends Command |
||||
|
private final case object NoOp extends Command |
||||
|
|
||||
|
private final case class DelegateToChild( |
||||
|
scriptActor: ActorRef[ScriptActor.Command], |
||||
|
scriptPath: os.Path, |
||||
|
requester: ActorRef[ScriptResult] |
||||
|
) extends Command |
||||
|
|
||||
|
final case class Props( |
||||
|
ctx: ActorContext[Command], |
||||
|
scriptActor: ActorRef[ScriptActor.Command] |
||||
|
) |
||||
|
final case class State(scriptsMap: ScriptsMap) |
||||
|
def apply(state: State = State(Map.empty)): Behavior[Command] = |
||||
|
Behaviors.logMessages { |
||||
|
Behaviors.setup { ctx => |
||||
|
val pool = ScriptActorPool(4) |
||||
|
val scriptsRouter = ctx.spawn(pool, "script-actors-pool") |
||||
|
new ScriptCachingActor(Props(ctx, scriptsRouter)).receiveMessage(state) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private def getOrCompileScript( |
||||
|
ctx: ActorContext[Command], |
||||
|
scriptPath: os.Path, |
||||
|
scriptsMap: ScriptsMap, |
||||
|
scriptActor: ActorRef[ScriptActor.Command], |
||||
|
requester: ActorRef[ScriptResult] |
||||
|
) = { |
||||
|
scriptsMap |
||||
|
.get(scriptPath) |
||||
|
.fold { |
||||
|
ctx.log.debug("Delegating to child") |
||||
|
ctx.self ! DelegateToChild( |
||||
|
scriptActor, |
||||
|
scriptPath, |
||||
|
requester |
||||
|
) |
||||
|
} { s => |
||||
|
ctx.log.debug("Getting script from cache") |
||||
|
requester ! Right(s) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private def askChildForScriptCompilation( |
||||
|
ctx: ActorContext[Command], |
||||
|
scriptActor: ActorRef[ScriptActor.Command], |
||||
|
scriptPath: os.Path, |
||||
|
requester: ActorRef[ScriptResult] |
||||
|
)(implicit timeout: Timeout) = { |
||||
|
ctx.ask(scriptActor, ScriptActor.CompileAny(scriptPath, _)) { |
||||
|
case Success(value) => |
||||
|
requester ! value |
||||
|
value.fold( |
||||
|
err => { |
||||
|
ctx.log.error(err.reason) |
||||
|
NoOp |
||||
|
}, |
||||
|
res => { |
||||
|
Put(scriptPath, res) |
||||
|
} |
||||
|
) |
||||
|
case Failure(exception) => { |
||||
|
ctx.log.error(exception.getMessage()) |
||||
|
NoOp |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class ScriptCachingActor(props: ScriptCachingActor.Props) { |
||||
|
import com.softwaremill.quicklens._ |
||||
|
import ScriptCachingActor._ |
||||
|
def receiveMessage(state: State): Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Get(scriptPath, requester) => |
||||
|
getOrCompileScript( |
||||
|
props.ctx, |
||||
|
scriptPath, |
||||
|
state.scriptsMap, |
||||
|
props.scriptActor, |
||||
|
requester |
||||
|
) |
||||
|
Behaviors.same |
||||
|
|
||||
|
case DelegateToChild(scriptActor, scriptPath, requester) => |
||||
|
import scala.concurrent.duration._ |
||||
|
implicit val timeout = Timeout(15.seconds) |
||||
|
// child ! ScriptActor.CompileAny(scriptPath, requester) |
||||
|
askChildForScriptCompilation( |
||||
|
props.ctx, |
||||
|
scriptActor, |
||||
|
scriptPath, |
||||
|
requester |
||||
|
) |
||||
|
Behaviors.same |
||||
|
|
||||
|
case GetMap(requester) => |
||||
|
requester ! state.scriptsMap |
||||
|
Behaviors.same |
||||
|
|
||||
|
case Put(scriptPath, script) => |
||||
|
props.ctx.log.debug(s"Putting $script at path $scriptPath") |
||||
|
val newState = |
||||
|
state.modify(_.scriptsMap).using(_ + (scriptPath -> script)) |
||||
|
props.ctx.log.debug(newState.toString()) |
||||
|
receiveMessage(state = newState) |
||||
|
|
||||
|
case NoOp => Behaviors.same |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object ScriptActorPool { |
||||
|
def apply( |
||||
|
poolSize: Int |
||||
|
): PoolRouter[ScriptActor.Command] = |
||||
|
Routers.pool(poolSize = poolSize)( |
||||
|
// make sure the workers are restarted if they fail |
||||
|
Behaviors |
||||
|
.supervise(ScriptActor()) |
||||
|
.onFailure[Exception](SupervisorStrategy.restart) |
||||
|
) |
||||
|
|
||||
|
// def apply( |
||||
|
// poolSize: Int, |
||||
|
// parent: ActorRef[ScriptStoringActor.Command] |
||||
|
// ): PoolRouter[ScriptActor.Command] = |
||||
|
// Routers.pool(poolSize = poolSize)( |
||||
|
// // make sure the workers are restarted if they fail |
||||
|
// Behaviors |
||||
|
// .supervise(ScriptActor(parent = parent)) |
||||
|
// .onFailure[Exception](SupervisorStrategy.restart) |
||||
|
// ) |
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
package wow.doge.mygame.state; |
||||
|
|
||||
|
import com.jme3.app.state.AbstractAppState; |
||||
|
import com.simsilica.es.EntityData; |
||||
|
import com.simsilica.es.base.DefaultEntityData; |
||||
|
import com.jme3.app.state.BaseAppState; |
||||
|
import com.jme3.app.Application; |
||||
|
|
||||
|
public class EntityDataState extends BaseAppState { |
||||
|
private EntityData entityData; |
||||
|
|
||||
|
public EntityDataState() { |
||||
|
this(new DefaultEntityData()); |
||||
|
} |
||||
|
|
||||
|
public EntityDataState(EntityData ed) { |
||||
|
this.entityData = ed; |
||||
|
} |
||||
|
|
||||
|
public EntityData getEntityData() { |
||||
|
return entityData; |
||||
|
} |
||||
|
|
||||
|
public void onEnable() { |
||||
|
} |
||||
|
|
||||
|
public void onDisable() { |
||||
|
} |
||||
|
|
||||
|
// @Override |
||||
|
public void cleanup(Application application) { |
||||
|
entityData.close(); |
||||
|
entityData = null; // cannot be reused |
||||
|
} |
||||
|
|
||||
|
public void initialize(Application application) { |
||||
|
} |
||||
|
} |
@ -0,0 +1,86 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import com.softwaremill.quicklens._ |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
import com.jme3.renderer.Camera |
||||
|
import wow.doge.mygame.math.ImVector3f |
||||
|
|
||||
|
trait CanMove[T] { |
||||
|
def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f |
||||
|
def move(inst: T, direction: ImVector3f): Unit |
||||
|
} |
||||
|
|
||||
|
object ImMovementActor { |
||||
|
sealed trait Command |
||||
|
// final case class Tick(tpf: Float) extends Command |
||||
|
final case class Tick(tpf: Float) extends Command |
||||
|
|
||||
|
sealed trait Movement extends Command |
||||
|
final case class MovedLeft(pressed: Boolean) extends Movement |
||||
|
final case class MovedUp(pressed: Boolean) extends Movement |
||||
|
final case class MovedRight(pressed: Boolean) extends Movement |
||||
|
final case class MovedDown(pressed: Boolean) extends Movement |
||||
|
|
||||
|
final case class Props[T: CanMove]( |
||||
|
app: com.jme3.app.Application, |
||||
|
movable: T |
||||
|
) |
||||
|
|
||||
|
/** |
||||
|
* Internal state of the actor |
||||
|
* |
||||
|
* @param cardinalDir Immutable, can be shared as is |
||||
|
* @param walkDirection Immutable |
||||
|
*/ |
||||
|
final case class State( |
||||
|
cardinalDir: CardinalDirection = CardinalDirection() |
||||
|
) |
||||
|
|
||||
|
def apply[T: CanMove](props: Props[T]): Behavior[Command] = |
||||
|
Behaviors.setup(ctx => new ImMovementActor(ctx, props).receive(State())) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class ImMovementActor[T]( |
||||
|
ctx: ActorContext[ImMovementActor.Command], |
||||
|
props: ImMovementActor.Props[T] |
||||
|
) { |
||||
|
import ImMovementActor._ |
||||
|
|
||||
|
def receive( |
||||
|
state: ImMovementActor.State |
||||
|
)(implicit cm: CanMove[T]): Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case m: Movement => |
||||
|
m match { |
||||
|
case MovedLeft(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.left).setTo(pressed)) |
||||
|
case MovedUp(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.up).setTo(pressed)) |
||||
|
case MovedRight(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.right).setTo(pressed)) |
||||
|
case MovedDown(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.down).setTo(pressed)) |
||||
|
} |
||||
|
|
||||
|
case Tick(tpf) => |
||||
|
val walkDir = |
||||
|
cm.getDirection(props.app.getCamera(), state.cardinalDir) |
||||
|
if (walkDir != ImVector3f.ZERO) { |
||||
|
val tmp = walkDir * 2f |
||||
|
props.app.enqueue(new Runnable { |
||||
|
override def run(): Unit = { |
||||
|
cm.move(props.movable, tmp) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
Behaviors.same |
||||
|
// receive(state = state.modify(_.walkDirection).setTo(walkDir)) |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
import com.jme3.app.Application |
||||
|
import com.jme3.app.SimpleApplication |
||||
|
import com.jme3.app.state.AppState |
||||
|
import com.jme3.scene.Node |
||||
|
import com.jme3.app.state.BaseAppState |
||||
|
import com.simsilica.es.EntityData |
||||
|
import com.simsilica.es.base.DefaultEntityData |
||||
|
|
||||
|
trait MyBaseState extends BaseAppState { |
||||
|
|
||||
|
var simpleApp: SimpleApplication = null |
||||
|
implicit val entityData: EntityData = new DefaultEntityData() |
||||
|
def stateManager = simpleApp.getStateManager |
||||
|
def guiNode = simpleApp.getGuiNode |
||||
|
def rootNode = simpleApp.getRootNode |
||||
|
def assetManager = simpleApp.getAssetManager |
||||
|
def inputManager = simpleApp.getInputManager |
||||
|
def cam = simpleApp.getCamera |
||||
|
|
||||
|
override protected final def initialize(app: Application): Unit = { |
||||
|
simpleApp = app.asInstanceOf[SimpleApplication] |
||||
|
init() |
||||
|
// stateManager.getState(classOf[FlyCamAppState]).getCamera().setMoveSpeed(100) |
||||
|
} |
||||
|
|
||||
|
protected def init(): Unit |
||||
|
|
||||
|
override protected def cleanup(app: Application): Unit = { |
||||
|
entityData.close() |
||||
|
} |
||||
|
|
||||
|
protected def getOrCreateNode(parent: Node, id: String) = |
||||
|
Option(parent.getChild(id)).fold { |
||||
|
val node = new Node(id) |
||||
|
parent.attachChild(node) |
||||
|
node |
||||
|
}(node => node.asInstanceOf[Node]) |
||||
|
|
||||
|
protected def enableStates(classes: Class[_ <: AppState]*) = |
||||
|
setEnabledToStates(true, classes: _*) |
||||
|
protected def disableStates(classes: Class[_ <: AppState]*) = |
||||
|
setEnabledToStates(false, classes: _*) |
||||
|
|
||||
|
protected def setEnabledToStates( |
||||
|
enabled: Boolean, |
||||
|
classes: Class[_ <: AppState]* |
||||
|
) = { |
||||
|
for (clazz <- classes) { |
||||
|
val st = stateManager.getState(clazz) |
||||
|
if (st != null) st.setEnabled(enabled) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected def removeStates(classes: Class[_ <: AppState]*) = { |
||||
|
for (clazz <- classes) { |
||||
|
val st = stateManager.getState(clazz) |
||||
|
if (st != null) stateManager.detach(st) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,286 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
|
||||
|
import scala.concurrent.duration.DurationInt |
||||
|
|
||||
|
import com.jme3.input.InputManager |
||||
|
import com.jme3.input.KeyInput |
||||
|
import com.jme3.input.controls.ActionListener |
||||
|
import com.jme3.input.controls.KeyTrigger |
||||
|
import com.jme3.math.Vector3f |
||||
|
|
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import com.jme3.scene.Geometry |
||||
|
import akka.actor.typed.scaladsl.TimerScheduler |
||||
|
|
||||
|
import wow.doge.mygame.implicits._ |
||||
|
|
||||
|
class PlayerMovementState2( |
||||
|
movementActor: ActorRef[MovementActor.Command], |
||||
|
movementActorTimer: ActorRef[MovementActorTimer.Command], |
||||
|
imMovementActor: ActorRef[ImMovementActor.Command], |
||||
|
geom: Geometry |
||||
|
) extends MyBaseState |
||||
|
with ActionListener { |
||||
|
|
||||
|
protected lazy val mat = MyMaterial( |
||||
|
assetManager = assetManager, |
||||
|
path = "Common/MatDefs/Misc/Unshaded.j3md" |
||||
|
) |
||||
|
|
||||
|
override protected[state] def onEnable(): Unit = {} |
||||
|
|
||||
|
override protected[state] def onDisable(): Unit = {} |
||||
|
|
||||
|
override protected def init(): Unit = { |
||||
|
|
||||
|
setupKeys(inputManager) |
||||
|
geom.setMaterial(mat) |
||||
|
rootNode.attachChild(geom) |
||||
|
// movementActorTimer ! MovementActorTimer.Start(geom, cam) |
||||
|
// movementActorTimer ! MovementActorTimer.Start |
||||
|
} |
||||
|
|
||||
|
// def system = |
||||
|
// simpleApp.getStateManager.getState(classOf[ActorSystemState]).system |
||||
|
// def player = system.actorSelection("/user/player") //.resolveOne(1.second) |
||||
|
|
||||
|
var lastDir: Vector3f = Vector3f.UNIT_X |
||||
|
|
||||
|
override def update(tpf: Float) = { |
||||
|
// val direction = new Vector3f() |
||||
|
// direction.multLocal(10 * tpf) |
||||
|
// if (direction.length() > 0f) { |
||||
|
// // player ! PlayerMove(direction) |
||||
|
// lastDir = direction.normalize |
||||
|
// } |
||||
|
// if (shoot) { |
||||
|
// shoot = false |
||||
|
// // player ! Shoot(lastDir) |
||||
|
// } |
||||
|
// movementActor ! MovementActor.Tick(tpf, geom, cam) |
||||
|
imMovementActor ! ImMovementActor.Tick(tpf) |
||||
|
// movementActorTimer ! MovementActorTimer.Update(tpf) |
||||
|
} |
||||
|
|
||||
|
def setupKeys(inputManager: InputManager) = { |
||||
|
|
||||
|
inputManager |
||||
|
.withMapping( |
||||
|
"Left", |
||||
|
// new KeyTrigger(KeyInput.KEY_A), |
||||
|
new KeyTrigger(KeyInput.KEY_LEFT) |
||||
|
) |
||||
|
.withMapping( |
||||
|
"Right", |
||||
|
// new KeyTrigger(KeyInput.KEY_D), |
||||
|
new KeyTrigger(KeyInput.KEY_RIGHT) |
||||
|
) |
||||
|
inputManager.addMapping( |
||||
|
"Up", |
||||
|
// new KeyTrigger(KeyInput.KEY_W), |
||||
|
new KeyTrigger(KeyInput.KEY_UP) |
||||
|
) |
||||
|
inputManager.addMapping( |
||||
|
"Down", |
||||
|
// new KeyTrigger(KeyInput.KEY_S), |
||||
|
new KeyTrigger(KeyInput.KEY_DOWN) |
||||
|
) |
||||
|
inputManager.addMapping( |
||||
|
"Space", |
||||
|
new KeyTrigger(KeyInput.KEY_SPACE), |
||||
|
new KeyTrigger(KeyInput.KEY_H) |
||||
|
) |
||||
|
inputManager.addMapping( |
||||
|
"Reset", |
||||
|
new KeyTrigger(KeyInput.KEY_R), |
||||
|
new KeyTrigger(KeyInput.KEY_RETURN) |
||||
|
) |
||||
|
inputManager |
||||
|
.withListener(this, "Left") |
||||
|
.withListener(this, "Right") |
||||
|
inputManager.addListener(this, "Up") |
||||
|
inputManager.addListener(this, "Down") |
||||
|
inputManager.addListener(this, "Space") |
||||
|
inputManager.addListener(this, "Reset") |
||||
|
} |
||||
|
|
||||
|
def onAction(binding: String, value: Boolean, tpf: Float) = |
||||
|
binding match { |
||||
|
case "Left" => imMovementActor ! ImMovementActor.MovedLeft(value) |
||||
|
case "Right" => imMovementActor ! ImMovementActor.MovedRight(value) |
||||
|
case "Up" => imMovementActor ! ImMovementActor.MovedUp(value) |
||||
|
case "Down" => imMovementActor ! ImMovementActor.MovedDown(value) |
||||
|
case "Space" => |
||||
|
case _ => |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
final case class CardinalDirection( |
||||
|
left: Boolean = false, |
||||
|
right: Boolean = false, |
||||
|
up: Boolean = false, |
||||
|
down: Boolean = false |
||||
|
) |
||||
|
|
||||
|
object MovementActor { |
||||
|
sealed trait Command |
||||
|
// final case class Tick(tpf: Float, geom: Geometry, cam: Camera) extends Command |
||||
|
// final case class Tick(tpf: Float) extends Command |
||||
|
final case object Tick extends Command |
||||
|
|
||||
|
sealed trait Movement extends Command |
||||
|
final case class MovedLeft(pressed: Boolean) extends Movement |
||||
|
final case class MovedUp(pressed: Boolean) extends Movement |
||||
|
final case class MovedRight(pressed: Boolean) extends Movement |
||||
|
final case class MovedDown(pressed: Boolean) extends Movement |
||||
|
|
||||
|
final case class Props(app: com.jme3.app.Application, geom: Geometry) |
||||
|
|
||||
|
/** |
||||
|
* Internal state of the actor |
||||
|
* |
||||
|
* @param cardinalDir Immutable, can be shared as is |
||||
|
* @param walkDirection scratch space to avoid allocations on every tick. Do not share outside the actor |
||||
|
*/ |
||||
|
final case class State( |
||||
|
cardinalDir: CardinalDirection = CardinalDirection(), |
||||
|
walkDirection: Vector3f = Vector3f.UNIT_X |
||||
|
) |
||||
|
|
||||
|
def apply(props: Props): Behavior[Command] = |
||||
|
Behaviors.setup(ctx => new MovementActor(ctx, props).receive(State())) |
||||
|
|
||||
|
} |
||||
|
class MovementActor( |
||||
|
ctx: ActorContext[MovementActor.Command], |
||||
|
props: MovementActor.Props |
||||
|
) { |
||||
|
import MovementActor._ |
||||
|
import com.softwaremill.quicklens._ |
||||
|
def receive(state: MovementActor.State): Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case m: Movement => |
||||
|
m match { |
||||
|
case MovedLeft(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.left).setTo(pressed)) |
||||
|
case MovedUp(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.up).setTo(pressed)) |
||||
|
case MovedRight(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.right).setTo(pressed)) |
||||
|
case MovedDown(pressed) => |
||||
|
receive(state = state.modify(_.cardinalDir.down).setTo(pressed)) |
||||
|
} |
||||
|
|
||||
|
case Tick => |
||||
|
val camDir = |
||||
|
props.app.getCamera.getDirection().clone().multLocal(0.6f) |
||||
|
val camLeft = props.app.getCamera.getLeft().clone().multLocal(0.4f) |
||||
|
val walkDir = state.walkDirection.set(0, 0, 0) |
||||
|
// val walkDir = new Vector3f |
||||
|
val dir = state.cardinalDir |
||||
|
if (dir.up) { |
||||
|
ctx.log.debug("up") |
||||
|
// ctx.log.debug(Thread.currentThread().getName()) |
||||
|
// walkDir.addLocal(0, 0, -1) |
||||
|
walkDir += camDir |
||||
|
} |
||||
|
if (dir.left) { |
||||
|
ctx.log.debug("left") |
||||
|
// walkDir.addLocal(-1, 0, 0) |
||||
|
walkDir.addLocal(camLeft) |
||||
|
} |
||||
|
if (dir.right) { |
||||
|
ctx.log.debug("right") |
||||
|
// walkDir.addLocal(1, 0, 0) |
||||
|
walkDir.addLocal(camLeft.negateLocal()) |
||||
|
} |
||||
|
if (dir.down) { |
||||
|
ctx.log.debug("down") |
||||
|
walkDir.addLocal(camDir.negateLocal()) |
||||
|
// walkDir.addLocal(0, 0, 1) |
||||
|
} |
||||
|
// (dir.up, dir.down, dir.left, dir.right) match { |
||||
|
// case (true, false, true, false) => |
||||
|
// case _ => |
||||
|
// } |
||||
|
|
||||
|
walkDir.multLocal(2f) |
||||
|
|
||||
|
// walkDir.multLocal(100f) |
||||
|
// .multLocal(tpf) |
||||
|
|
||||
|
// val v = props.geom.getLocalTranslation() |
||||
|
// props.geom.setLocalTranslation( |
||||
|
// (v += walkDir) |
||||
|
// ) |
||||
|
props.app.enqueue(new Runnable { |
||||
|
override def run(): Unit = { |
||||
|
// geom.setLocalTranslation(walkDir) |
||||
|
|
||||
|
val v = props.geom.getLocalTranslation() |
||||
|
props.geom.setLocalTranslation( |
||||
|
(v += walkDir) |
||||
|
) |
||||
|
} |
||||
|
}) |
||||
|
Behaviors.same |
||||
|
// receive(state = state.modify(_.walkDirection).setTo(walkDir)) |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object MovementActorTimer { |
||||
|
sealed trait Command |
||||
|
final case object Start extends Command |
||||
|
final case object Update extends Command |
||||
|
private case object Send extends Command |
||||
|
case object TimerKey |
||||
|
|
||||
|
final case class Props( |
||||
|
timers: TimerScheduler[MovementActorTimer.Command], |
||||
|
target: ActorRef[MovementActor.Command] |
||||
|
) |
||||
|
final case class State() |
||||
|
def apply(target: ActorRef[MovementActor.Command]) = |
||||
|
Behaviors.withTimers[Command] { timers => |
||||
|
new MovementActorTimer(Props(timers, target)).idle() |
||||
|
} |
||||
|
} |
||||
|
class MovementActorTimer( |
||||
|
props: MovementActorTimer.Props |
||||
|
) { |
||||
|
import MovementActorTimer._ |
||||
|
// import com.softwaremill.quicklens._ |
||||
|
|
||||
|
def idle(): Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Start => |
||||
|
props.timers.startTimerWithFixedDelay( |
||||
|
Send, |
||||
|
10.millis |
||||
|
) |
||||
|
active() |
||||
|
case _ => Behaviors.unhandled |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def active(): Behavior[Command] = |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Update => active() |
||||
|
case Send => |
||||
|
props.target ! MovementActor.Tick |
||||
|
Behaviors.same |
||||
|
case _ => Behaviors.unhandled |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,206 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
import ammonite.runtime.Storage.Folder |
||||
|
import ammonite.main.Defaults |
||||
|
import ammonite.Main |
||||
|
import javax.script.ScriptEngine |
||||
|
import com.jme3.app.Application |
||||
|
import com.jme3.app.state.AppState |
||||
|
import akka.actor.typed.scaladsl.AbstractBehavior |
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.ActorRef |
||||
|
import ammonite.util.Res.Success |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import akka.actor.typed.SpawnProtocol |
||||
|
|
||||
|
class ScriptingEngineState( |
||||
|
sse: ScalaScriptingEngine, |
||||
|
kse: KotlinScriptingEngine |
||||
|
) extends MyBaseState { |
||||
|
|
||||
|
// implicit val actorSystem = |
||||
|
// ActorSystem.create(MyActorSystem(), "rootActor") |
||||
|
// implicit val timeout: Timeout = Timeout(3.seconds) |
||||
|
// val scalaScriptActor: Future[ActorRef[ScalaScriptBehavior.Command]] = |
||||
|
// actorSystem.ask( |
||||
|
// SpawnProtocol.Spawn( |
||||
|
// ScalaScriptBehavior(sse.runner), |
||||
|
// name = "ScalaScriptCompilerActor", |
||||
|
// Props.empty, |
||||
|
// _ |
||||
|
// ) |
||||
|
// ) |
||||
|
|
||||
|
override protected def cleanup(app: Application): Unit = { |
||||
|
// actorSystem.terminate() |
||||
|
} |
||||
|
|
||||
|
// override protected def initialize(app: Application): Unit = { |
||||
|
// super.initialize(app) |
||||
|
|
||||
|
// } |
||||
|
override def init() = { |
||||
|
// Future { |
||||
|
// while (true) { |
||||
|
// // super.update(tpf) |
||||
|
// val (res, k) = sse.runner.runScript( |
||||
|
// // os.Path(getClass().getResource("/hello.sc").getPath), |
||||
|
// os.pwd / "src" / "main" / "resources" / "hello.sc", |
||||
|
// Seq.empty |
||||
|
// // Seq(("start", None)) |
||||
|
// // Scripts.groupArgs(List("")) |
||||
|
// ) |
||||
|
// val ms = res.map(_.asInstanceOf[GameScript]) |
||||
|
// ms.map(_.start()) |
||||
|
|
||||
|
// val res2 = kse.engine.eval( |
||||
|
// os.read(os.pwd / "src" / "main" / "resources" / "hello.main.kts") |
||||
|
// ) |
||||
|
// // val res2 = engine.eval(getClass().getResource("/hello.main.kts").getPath) |
||||
|
// // val invoker = engine.asInstanceOf[Invocable] |
||||
|
// // val scr = invoker.getInterface(res2, classOf[GameScript]) |
||||
|
// val scr = res2.asInstanceOf[GameScript] |
||||
|
// scr.start() |
||||
|
// Thread.sleep(2000) |
||||
|
// } |
||||
|
// } |
||||
|
// Future { |
||||
|
// sse.runner |
||||
|
// .runScript( |
||||
|
// os.pwd / "src" / "main" / "resources" / "hello2.sc", |
||||
|
// Seq.empty |
||||
|
// ) |
||||
|
// ._1 |
||||
|
// .map(_.asInstanceOf[MyBaseState]) |
||||
|
// .map(s => stateManager.attach(s)) |
||||
|
|
||||
|
// () |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
// val res = scalaScriptActor |
||||
|
// .map( |
||||
|
// _.ask(ref => |
||||
|
// ScalaScriptBehavior.Compile( |
||||
|
// ref, |
||||
|
// os.pwd / "src" / "main" / "resources" / "hello2.sc" |
||||
|
// // os.Path(getClass().getResource("/hello2.sc").getPath) |
||||
|
// ) |
||||
|
// )(Timeout(10.seconds), actorSystem.scheduler) |
||||
|
// ) |
||||
|
// .flatten |
||||
|
|
||||
|
// res.foreach(_ match { |
||||
|
// case AppStateResult(state) => { |
||||
|
// stateManager.attach(state) |
||||
|
// } |
||||
|
// case wow.doge.mygame.state.ScalaScriptBehavior.Error(reason) => |
||||
|
// println("error") |
||||
|
// }) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
override def update(tpf: Float): Unit = {} |
||||
|
|
||||
|
override protected def onEnable(): Unit = {} |
||||
|
|
||||
|
override protected def onDisable(): Unit = {} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object MyActorSystem { |
||||
|
def apply(): Behavior[SpawnProtocol.Command] = |
||||
|
Behaviors.setup { context => |
||||
|
// Start initial tasks |
||||
|
// context.spawn(...) |
||||
|
|
||||
|
SpawnProtocol() |
||||
|
} |
||||
|
} |
||||
|
class ScalaScriptingEngine( |
||||
|
val runner: Main = ammonite |
||||
|
.Main( |
||||
|
// predefCode = """ |
||||
|
// import coursierapi.MavenRepository |
||||
|
|
||||
|
// interp.repositories.update( |
||||
|
// interp.repositories() ::: List( |
||||
|
// MavenRepository.of("file://home/rohan/.m2/repository") |
||||
|
// ) |
||||
|
// ) |
||||
|
|
||||
|
// @ |
||||
|
|
||||
|
// """, |
||||
|
defaultPredef = false, |
||||
|
storageBackend = new Folder(Defaults.ammoniteHome, isRepl = false) |
||||
|
) |
||||
|
) {} |
||||
|
|
||||
|
class KotlinScriptingEngine(val engine: ScriptEngine) { |
||||
|
// val manager = new ScriptEngineManager() |
||||
|
// val engine = manager.getEngineByExtension("main.kts") |
||||
|
} |
||||
|
|
||||
|
object ScalaScriptBehavior { |
||||
|
sealed trait Result |
||||
|
final case class AppStateResult(state: AppState) extends Result |
||||
|
final case class Error(reason: String) extends Result |
||||
|
|
||||
|
sealed trait Command |
||||
|
final case class Compile(sender: ActorRef[Result], path: os.Path) |
||||
|
extends Command |
||||
|
// final case class CompileScripts(sender: ActorRef[Result], paths: os.Path*) |
||||
|
// extends Command |
||||
|
def apply( |
||||
|
runner: Main = ammonite |
||||
|
.Main( |
||||
|
storageBackend = new Folder( |
||||
|
// os.pwd / "target" |
||||
|
Defaults.ammoniteHome, |
||||
|
isRepl = false |
||||
|
) |
||||
|
) |
||||
|
) = |
||||
|
Behaviors.setup(ctx => new ScalaScriptActor(runner, ctx)) |
||||
|
private class ScalaScriptActor( |
||||
|
val runner: Main, |
||||
|
context: ActorContext[Command] |
||||
|
) extends AbstractBehavior[Command](context) { |
||||
|
|
||||
|
override def onMessage(msg: Command): Behavior[Command] = { |
||||
|
msg match { |
||||
|
case Compile(sender, path) => |
||||
|
context.log.debug(s"Received $path") |
||||
|
val res = getScript(path) |
||||
|
println(res) |
||||
|
sender ! res |
||||
|
Behaviors.same |
||||
|
// case CompileScripts(sender, paths) => |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def getScript(path: os.Path): Result = { |
||||
|
runner |
||||
|
.runScript( |
||||
|
path, |
||||
|
Seq.empty |
||||
|
) |
||||
|
._1 match { |
||||
|
case ammonite.util.Res.Exception(t, msg) => Error(msg) |
||||
|
|
||||
|
case Success(obj) => |
||||
|
obj match { |
||||
|
case s: MyBaseState => AppStateResult(s) |
||||
|
case _ => Error("Unknown script type") |
||||
|
// AppStateResult(s.asInstanceOf[AppState]) |
||||
|
} |
||||
|
|
||||
|
case _ => Error("Failed to run script") |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
package wow.doge.mygame.state |
||||
|
|
||||
|
import com.jme3.app.Application |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
import wow.doge.mygame.components.TestComponent |
||||
|
import com.jme3.scene.shape.Box |
||||
|
import com.jme3.scene.Geometry |
||||
|
import com.jme3.material.Material |
||||
|
import com.jme3.math.ColorRGBA |
||||
|
import com.jme3.asset.AssetManager |
||||
|
import com.jme3.math.Vector3f |
||||
|
class TestAppState( |
||||
|
// private var _entity: Option[EntityData] = Some(new DefaultEntityData()) |
||||
|
) extends MyBaseState { |
||||
|
var geom: Option[Geometry] = None |
||||
|
|
||||
|
// def entity = _entity |
||||
|
// override def initialize(app: Application): Unit = { |
||||
|
// super.initialize(app) |
||||
|
|
||||
|
// } |
||||
|
|
||||
|
override def init() = { |
||||
|
entityData |
||||
|
.createEntity() |
||||
|
.withComponents(TestComponent()) |
||||
|
// entityData.setComponents(x, TestComponent()) |
||||
|
val es = entityData.getEntities(classOf[TestComponent]) |
||||
|
println(es) |
||||
|
val b = new Box(1, 1, 1) |
||||
|
geom = Some(new Geometry("Box", b)) |
||||
|
|
||||
|
val mat = MyMaterial( |
||||
|
assetManager = assetManager, |
||||
|
path = "Common/MatDefs/Misc/Unshaded.j3md" |
||||
|
) |
||||
|
geom.foreach(e => { |
||||
|
e.setMaterial(mat) |
||||
|
rootNode.attachChild(e) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
override def update(tpf: Float) = { |
||||
|
geom.foreach(_.rotate(0, 0.5f * tpf, 0)) |
||||
|
geom.foreach(_.move(new Vector3f(0, 1 * tpf, 0))) |
||||
|
} |
||||
|
|
||||
|
override def cleanup(app: Application): Unit = { |
||||
|
// _entity.map(_.close()) |
||||
|
// _entity = None |
||||
|
} |
||||
|
|
||||
|
override def onEnable(): Unit = {} |
||||
|
|
||||
|
override def onDisable(): Unit = {} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object MyMaterial { |
||||
|
def apply( |
||||
|
color: String = "Color", |
||||
|
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue, |
||||
|
assetManager: AssetManager, |
||||
|
path: String |
||||
|
): Material = { |
||||
|
val mat = |
||||
|
new Material(assetManager, path) |
||||
|
mat.setColor(color, colorType) |
||||
|
mat |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue