Rohan Sircar
3 years ago
34 changed files with 1292 additions and 927 deletions
-
18build.sbt
-
1project/plugins.sbt
-
17src/main/scala/wow/doge/mygame/AppError.scala
-
250src/main/scala/wow/doge/mygame/MainApp.scala
-
56src/main/scala/wow/doge/mygame/game/GameApp.scala
-
12src/main/scala/wow/doge/mygame/game/GameAppActor.scala
-
11src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
-
294src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala
-
71src/main/scala/wow/doge/mygame/game/controls/CameraMovementControls.scala
-
42src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala
-
295src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
-
149src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor2.scala
-
15src/main/scala/wow/doge/mygame/game/entities/player/PlayerCameraActor.scala
-
116src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala
-
8src/main/scala/wow/doge/mygame/game/entities/player/PlayerEventListeners.scala
-
55src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
-
10src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
-
296src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
-
163src/main/scala/wow/doge/mygame/implicits/package.scala
-
6src/main/scala/wow/doge/mygame/math/ImVector3f.scala
-
64src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
-
12src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
-
29src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
-
18src/main/scala/wow/doge/mygame/subsystems/events/PlayerEvents.scala
-
18src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
-
4src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
-
17src/main/scala/wow/doge/mygame/types/package.scala
-
7src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
-
4src/main/scala/wow/doge/mygame/utils/GenericTimerActor.scala
-
7src/main/scala/wow/doge/mygame/utils/IOUtils.scala
-
18src/main/scala/wow/doge/mygame/utils/wrappers/jme/Node.scala
-
90src/main/scala/wow/doge/mygame/utils/wrappers/jme/PhysicsSpace.scala
-
5src/test/scala/wow/doge/mygame/ActorTimeoutTest.scala
-
41src/test/scala/wow/doge/mygame/ReaderT_Test.scala
@ -1,3 +1,2 @@ |
|||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
|||
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
|||
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1") |
@ -1,294 +0,0 @@ |
|||
package wow.doge.mygame.state |
|||
|
|||
import scala.concurrent.duration.DurationInt |
|||
|
|||
import akka.actor.typed.ActorRef |
|||
import akka.actor.typed.Behavior |
|||
import akka.actor.typed.scaladsl.ActorContext |
|||
import akka.actor.typed.scaladsl.Behaviors |
|||
import akka.actor.typed.scaladsl.TimerScheduler |
|||
import com.jme3.input.InputManager |
|||
import com.jme3.input.KeyInput |
|||
import com.jme3.input.controls.KeyTrigger |
|||
import com.jme3.math.Vector3f |
|||
import com.jme3.scene.Geometry |
|||
import wow.doge.mygame.implicits._ |
|||
import wow.doge.mygame.subsystems.movement.ImMovementActor |
|||
|
|||
class PlayerMovementState( |
|||
// movementActor: ActorRef[MovementActor.Command], |
|||
// movementActorTimer: ActorRef[MovementActorTimer.Command], |
|||
imMovementActor: ActorRef[ImMovementActor.Command] |
|||
// geom: Geometry, |
|||
// camNode: CameraNode, |
|||
// playerNode: Node |
|||
// gameAppActor: ActorRef[GameAppActor.Command] |
|||
) extends MyBaseState |
|||
// with ActionListener |
|||
{ |
|||
|
|||
protected lazy val mat = MyMaterial( |
|||
assetManager = assetManager, |
|||
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md" |
|||
) |
|||
|
|||
override protected def init(): Unit = { |
|||
|
|||
// setupKeys(inputManager) |
|||
// println("playermovementstate " + Thread.currentThread().getName()) |
|||
|
|||
// geom.setMaterial(mat) |
|||
|
|||
// camNode.setControlDir(ControlDirection.SpatialToCamera) |
|||
// // lazy val camNode = new CameraNode("CameraNode", simpleApp.getCamera()) |
|||
// // camNode.setCamera(simpleApp.getCamera()) |
|||
// discard { |
|||
// playerNode |
|||
// .child(camNode) |
|||
// .child(geom) |
|||
// // playerNode.children(Seq(camNode, geom)) |
|||
// } |
|||
// discard { rootNode.withChild(playerNode) } |
|||
// camNode.setLocalTranslation( |
|||
// new Vector3f(0, 1.5f, 10) |
|||
// ) |
|||
// camNode.lookAt(playerNode.getLocalTranslation(), Vector3f.UNIT_Y) |
|||
|
|||
// movementActorTimer ! MovementActorTimer.Start(geom, cam) |
|||
// movementActorTimer ! MovementActorTimer.Start |
|||
} |
|||
|
|||
override def update(tpf: Float) = { |
|||
// movementActor ! MovementActor.Tick(tpf, geom, cam) |
|||
// imMovementActor ! ImMovementActor.Tick(tpf) |
|||
|
|||
// movementActorTimer ! MovementActorTimer.Update(tpf) |
|||
} |
|||
|
|||
override def stop(): Unit = {} |
|||
// override protected def cleanup(app: Application): Unit = { |
|||
// // gameAppActor ! GameAppActor.Stop |
|||
// super.cleanup(app) |
|||
// } |
|||
|
|||
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) |
|||
) |
|||
.withMapping( |
|||
"Up", |
|||
// new KeyTrigger(KeyInput.KEY_W), |
|||
new KeyTrigger(KeyInput.KEY_UP) |
|||
) |
|||
.withMapping( |
|||
"Down", |
|||
// new KeyTrigger(KeyInput.KEY_S), |
|||
new KeyTrigger(KeyInput.KEY_DOWN) |
|||
) |
|||
.withMapping( |
|||
"Space", |
|||
new KeyTrigger(KeyInput.KEY_SPACE), |
|||
new KeyTrigger(KeyInput.KEY_H) |
|||
) |
|||
.withMapping( |
|||
"Reset", |
|||
new KeyTrigger(KeyInput.KEY_R), |
|||
new KeyTrigger(KeyInput.KEY_RETURN) |
|||
) |
|||
// .withListener(this, "Left") |
|||
// .withListener(this, "Right") |
|||
// .withListener(this, "Up") |
|||
// .withListener(this, "Down") |
|||
// .withListener(this, "Space") |
|||
// .withListener(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 _ => |
|||
// } |
|||
|
|||
override protected def onEnable(): Unit = {} |
|||
|
|||
override protected def onDisable(): Unit = {} |
|||
|
|||
} |
|||
|
|||
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.debugP("up") |
|||
// ctx.log.debugP(Thread.currentThread().getName()) |
|||
// walkDir.addLocal(0, 0, -1) |
|||
walkDir += camDir |
|||
} |
|||
if (dir.left) { |
|||
ctx.log.debugP("left") |
|||
// walkDir.addLocal(-1, 0, 0) |
|||
walkDir.addLocal(camLeft) |
|||
} |
|||
if (dir.right) { |
|||
ctx.log.debugP("right") |
|||
// walkDir.addLocal(1, 0, 0) |
|||
walkDir.addLocal(camLeft.negateLocal()) |
|||
} |
|||
if (dir.down) { |
|||
ctx.log.debugP("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,71 @@ |
|||
package wow.doge.mygame.game.controls |
|||
|
|||
import com.jme3.math.Quaternion |
|||
import com.jme3.scene.Node |
|||
import com.jme3.scene.control.AbstractControl |
|||
import com.jme3.renderer.RenderManager |
|||
import com.jme3.renderer.ViewPort |
|||
import monix.reactive.Observable |
|||
import wow.doge.mygame.game.subsystems.input.PlayerCameraInput |
|||
import com.jme3.scene.Spatial |
|||
import monix.{eval => me} |
|||
import com.jme3.math.FastMath |
|||
import com.jme3.math.Vector3f |
|||
import monix.execution.Cancelable |
|||
import monix.execution.Scheduler |
|||
|
|||
class CameraMovementControl( |
|||
rotationBuf: Quaternion, |
|||
obs: Observable[PlayerCameraInput], |
|||
rotateFn: Quaternion => Unit |
|||
)(implicit s: Scheduler) |
|||
extends AbstractControl { |
|||
private var _event: PlayerCameraInput = null |
|||
private var _subscriptionToken: Cancelable = null |
|||
|
|||
override def controlUpdate(tpf: Float): Unit = |
|||
if (_event != null) |
|||
_event match { |
|||
case PlayerCameraInput.CameraRotateLeft => |
|||
val rot = rotationBuf |
|||
.fromAngleAxis(1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y) |
|||
rotateFn(rot) |
|||
case PlayerCameraInput.CameraRotateRight => |
|||
val rot = rotationBuf |
|||
.fromAngleAxis(-1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y) |
|||
rotateFn(rot) |
|||
case PlayerCameraInput.CameraRotateUp => |
|||
val rot = rotationBuf |
|||
.fromAngleAxis(-1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_X) |
|||
rotateFn(rot) |
|||
case PlayerCameraInput.CameraRotateDown => |
|||
val rot = rotationBuf |
|||
.fromAngleAxis(1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_X) |
|||
rotateFn(rot) |
|||
} |
|||
|
|||
override def controlRender( |
|||
x$1: RenderManager, |
|||
x$2: ViewPort |
|||
): Unit = {} |
|||
override def setSpatial(spatial: Spatial): Unit = { |
|||
super.setSpatial(spatial) |
|||
if (this.spatial != null) |
|||
_subscriptionToken = |
|||
obs.doOnNext(event => me.Task { _event = event }).subscribe() |
|||
else { |
|||
_subscriptionToken.cancel() |
|||
_subscriptionToken = null |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
class FollowControl(playerNode: Node) extends AbstractControl { |
|||
override def controlUpdate(tpf: Float): Unit = |
|||
this.spatial.setLocalTranslation(playerNode.getLocalTranslation()) |
|||
override def controlRender( |
|||
rm: RenderManager, |
|||
vp: ViewPort |
|||
): Unit = {} |
|||
} |
@ -0,0 +1,149 @@ |
|||
package wow.doge.mygame.game.entities.player |
|||
|
|||
import scala.concurrent.duration._ |
|||
|
|||
import akka.actor.typed.ActorRef |
|||
import akka.actor.typed.Behavior |
|||
import akka.actor.typed.LogOptions |
|||
import akka.actor.typed.PostStop |
|||
import akka.actor.typed.SupervisorStrategy |
|||
import akka.actor.typed.scaladsl.ActorContext |
|||
import akka.actor.typed.scaladsl.Behaviors |
|||
import com.typesafe.scalalogging.Logger |
|||
import org.slf4j.event.Level |
|||
import wow.doge.mygame.Dispatchers |
|||
import wow.doge.mygame.game.entities.PlayerCameraActor |
|||
import wow.doge.mygame.game.entities.PlayerCameraEventListener |
|||
import wow.doge.mygame.game.entities.PlayerMovementEventListener |
|||
import wow.doge.mygame.implicits._ |
|||
import wow.doge.mygame.subsystems.events.EventBus |
|||
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus |
|||
import wow.doge.mygame.subsystems.events.PlayerEvent |
|||
import wow.doge.mygame.subsystems.events.TickEvent |
|||
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick |
|||
import wow.doge.mygame.subsystems.movement.ImMovementActor |
|||
|
|||
object PlayerActorSupervisor2 { |
|||
sealed trait Command |
|||
case object Tick extends Command |
|||
sealed trait Movement extends Command |
|||
final case class MoveLeft(pressed: Boolean) extends Movement |
|||
final case class MoveUp(pressed: Boolean) extends Movement |
|||
final case class MoveRight(pressed: Boolean) extends Movement |
|||
final case class MoveDown(pressed: Boolean) extends Movement |
|||
case object Jump extends Movement |
|||
sealed trait Camera |
|||
case object RotateLeft extends Camera |
|||
case object RotateRight extends Camera |
|||
case object RotateUp extends Camera |
|||
case object RotateDown extends Camera |
|||
class Props( |
|||
val playerEventBus: GameEventBus[PlayerEvent], |
|||
val tickEventBus: GameEventBus[TickEvent], |
|||
val imMovementActorBehavior: Behavior[ImMovementActor.Command], |
|||
val playerCameraActorBehavior: Behavior[PlayerCameraActor.Command] |
|||
) { |
|||
def behavior = |
|||
Behaviors.logMessages( |
|||
LogOptions() |
|||
.withLevel(Level.TRACE) |
|||
.withLogger( |
|||
Logger[PlayerActorSupervisor2].underlying |
|||
), |
|||
Behaviors |
|||
.setup[Command] { ctx => |
|||
ctx.log.infoP("Starting PlayerActor") |
|||
|
|||
// spawn children actors |
|||
val movementActor = |
|||
ctx.spawn( |
|||
Behaviors |
|||
.supervise(imMovementActorBehavior) |
|||
.onFailure[Exception]( |
|||
SupervisorStrategy.restart.withLimit(2, 100.millis) |
|||
), |
|||
"playerMovementActor", |
|||
Dispatchers.jmeDispatcher |
|||
) |
|||
|
|||
val playerCameraActor = |
|||
ctx.spawn( |
|||
playerCameraActorBehavior, |
|||
"playerCameraActor", |
|||
Dispatchers.jmeDispatcher |
|||
) |
|||
|
|||
val playerCameraEl = ctx.spawn( |
|||
PlayerCameraEventListener(playerCameraActor), |
|||
"playerCameraActorEl" |
|||
) |
|||
|
|||
val playerMovementEl = ctx.spawn( |
|||
Behaviors |
|||
.supervise(PlayerMovementEventListener(movementActor)) |
|||
.onFailure[Exception]( |
|||
SupervisorStrategy.restart.withLimit(2, 100.millis) |
|||
), |
|||
"playerMovementEventHandler" |
|||
) |
|||
|
|||
val renderTickEl = { |
|||
val behavior: Behavior[RenderTick.type] = |
|||
Behaviors.setup(ctx => |
|||
Behaviors |
|||
.receiveMessage[RenderTick.type] { |
|||
case RenderTick => |
|||
movementActor ! ImMovementActor.Tick |
|||
// playerCameraActor ! PlayerCameraActor.Tick |
|||
Behaviors.same |
|||
} |
|||
.receiveSignal { |
|||
case (_, PostStop) => |
|||
ctx.log.infoP("stopped") |
|||
Behaviors.same |
|||
} |
|||
) |
|||
ctx.spawn(behavior, "playerMovementTickListener") |
|||
} |
|||
|
|||
//init listeners |
|||
playerEventBus ! EventBus.Subscribe(playerMovementEl) |
|||
tickEventBus ! EventBus.Subscribe(renderTickEl) |
|||
playerEventBus ! EventBus.Subscribe(playerCameraEl) |
|||
|
|||
new PlayerActorSupervisor2( |
|||
ctx, |
|||
this, |
|||
Children(movementActor) |
|||
).receive |
|||
} |
|||
) |
|||
|
|||
} |
|||
|
|||
case class Children( |
|||
movementActor: ActorRef[ImMovementActor.Command] |
|||
) |
|||
} |
|||
class PlayerActorSupervisor2( |
|||
ctx: ActorContext[PlayerActorSupervisor2.Command], |
|||
props: PlayerActorSupervisor2.Props, |
|||
children: PlayerActorSupervisor2.Children |
|||
) { |
|||
import PlayerActorSupervisor2._ |
|||
def receive = |
|||
Behaviors |
|||
.receiveMessage[Command] { |
|||
case m @ MoveDown(pressed) => |
|||
// children.movementActor ! m |
|||
Behaviors.same |
|||
case _ => |
|||
// children.movementActor ! ImMovementActor.MovedDown(true) |
|||
Behaviors.same |
|||
} |
|||
.receiveSignal { |
|||
case (_, PostStop) => |
|||
ctx.log.infoP("stopped") |
|||
Behaviors.same |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
package wow.doge.mygame |
|||
|
|||
import wow.doge.mygame.utils.wrappers.jme.AppNode2 |
|||
import com.softwaremill.tagging._ |
|||
import wow.doge.mygame.game.GameAppTags |
|||
import monix.execution.Scheduler |
|||
import io.estatico.newtype.macros.newtype |
|||
|
|||
package object types { |
|||
type RootNode = AppNode2 @@ GameAppTags.RootNode |
|||
type GuiNode = AppNode2 @@ GameAppTags.GuiNode |
|||
@newtype case class AsyncScheduler(value: Scheduler) |
|||
@newtype case class IoScheduler(value: Scheduler) |
|||
@newtype case class FxScheduler(value: Scheduler) |
|||
@newtype case class JmeScheduler(value: Scheduler) |
|||
@newtype case class AkkaScheduler(value: akka.actor.typed.Scheduler) |
|||
} |
@ -1,12 +1,17 @@ |
|||
package wow.doge.mygame.utils |
|||
|
|||
import monix.bio.IO |
|||
import monix.bio.Task |
|||
import monix.eval.Coeval |
|||
|
|||
object IOUtils { |
|||
def toTask[T](bio: monix.bio.IO[Throwable, T]) = |
|||
def toTask[T](bio: IO[Throwable, T]) = |
|||
monix.eval.Task.deferAction(implicit s => bio.to[monix.eval.Task]) |
|||
|
|||
def toIO[T](task: monix.eval.Task[T]) = |
|||
IO.deferAction(implicit s => IO.from(task)) |
|||
|
|||
def fromCoevalEither[L, R](coeval: Coeval[Either[L, R]]) = |
|||
coeval.to[Task].hideErrors.rethrow |
|||
|
|||
} |
@ -1,57 +1,91 @@ |
|||
package wow.doge.mygame.utils.wrappers.jme |
|||
import com.jme3.bullet.control.PhysicsControl |
|||
import com.jme3.bullet.joints.PhysicsJoint |
|||
import com.jme3.{bullet => jmeb} |
|||
import com.jme3.{scene => jmes} |
|||
import monix.bio.UIO |
|||
import wow.doge.mygame.implicits._ |
|||
|
|||
final class PhysicsSpace(space: jmeb.PhysicsSpace) { |
|||
def add(anyObject: Any) = UIO(space.add(anyObject)) |
|||
def add[T](addable: T)(implicit P: PhysicsSpaceAddable[T]) = |
|||
UIO(P.addToSpace(addable, space)) |
|||
|
|||
def remove(anyObject: Any) = |
|||
UIO { |
|||
space.remove(anyObject) |
|||
space |
|||
} |
|||
def remove(anyObject: Any) = UIO(space.remove(anyObject)) |
|||
|
|||
def addAll(spatial: jmes.Spatial) = UIO(space.addAll(spatial)) |
|||
|
|||
def removeAll(spatial: jmes.Spatial) = |
|||
UIO { |
|||
space.removeAll(spatial) |
|||
space |
|||
} |
|||
def removeAll(spatial: jmes.Spatial) = UIO(space.removeAll(spatial)) |
|||
|
|||
def collisionObservable = space.collisionObservable() |
|||
|
|||
// space.enqueue(() => ()) |
|||
|
|||
def physicsTickObservable = space.physicsTickObservable() |
|||
|
|||
def prePhysicsTickObservable = space.prePhysicsTickObservable() |
|||
} |
|||
object PhysicsSpace { |
|||
implicit final class PhysicsSpaceOps(private val space: PhysicsSpace) |
|||
extends AnyVal { |
|||
def +=(anyObject: Any) = space.add(anyObject) |
|||
def +=[T: PhysicsSpaceAddable](addable: T) = space.add(addable) |
|||
|
|||
def :+(anyObject: Any) = { |
|||
space.add(anyObject) |
|||
space |
|||
} |
|||
def -(anyObject: Any) = { |
|||
space.remove(anyObject) |
|||
space |
|||
} |
|||
def :+[T: PhysicsSpaceAddable](addable: T) = |
|||
for { |
|||
_ <- space.add(addable) |
|||
} yield space |
|||
def -(anyObject: Any) = |
|||
for { |
|||
_ <- space.remove(anyObject) |
|||
} yield space |
|||
|
|||
def -=(anyObject: Any) = space.remove(anyObject) |
|||
|
|||
def +=(spatial: jmes.Spatial) = space.addAll(spatial) |
|||
|
|||
def :+(spatial: jmes.Spatial) = { |
|||
space.addAll(spatial) |
|||
space |
|||
} |
|||
// def :+(spatial: jmes.Spatial) = { |
|||
// space.addAll(spatial) |
|||
// space |
|||
// } |
|||
|
|||
def -(spatial: jmes.Spatial) = { |
|||
space.removeAll(spatial) |
|||
space |
|||
} |
|||
// def -(spatial: jmes.Spatial) = { |
|||
// space.removeAll(spatial) |
|||
// space |
|||
// } |
|||
|
|||
def -=(spatial: jmes.Spatial) = space.removeAll(spatial) |
|||
} |
|||
} |
|||
|
|||
trait PhysicsSpaceAddable[-T] { |
|||
def addToSpace(inst: T, space: jmeb.PhysicsSpace): Unit |
|||
} |
|||
|
|||
object PhysicsSpaceAddable { |
|||
implicit val physicsSpaceAddableForPhysControl = |
|||
new PhysicsSpaceAddable[PhysicsControl] { |
|||
|
|||
override def addToSpace( |
|||
inst: PhysicsControl, |
|||
space: jmeb.PhysicsSpace |
|||
): Unit = space.add(inst) |
|||
|
|||
} |
|||
implicit val physicsSpaceAddableForSpatial = |
|||
new PhysicsSpaceAddable[jmes.Spatial] { |
|||
|
|||
override def addToSpace( |
|||
inst: jmes.Spatial, |
|||
space: jmeb.PhysicsSpace |
|||
): Unit = space.add(inst) |
|||
|
|||
} |
|||
implicit val physicsSpaceAddableForPhysJoint = |
|||
new PhysicsSpaceAddable[PhysicsJoint] { |
|||
|
|||
override def addToSpace( |
|||
inst: PhysicsJoint, |
|||
space: jmeb.PhysicsSpace |
|||
): Unit = space.add(inst) |
|||
|
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue