Skip to content

Commit

Permalink
Create entity when joining and set up room descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklanng committed Mar 22, 2024
1 parent 6f46e9e commit 0a8bf72
Show file tree
Hide file tree
Showing 15 changed files with 268 additions and 138 deletions.
1 change: 1 addition & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ glisten = { path = "../glisten" }
gleam_otp = "~> 0.10"
gleam_erlang = "~> 0.24"
repeatedly = "~> 2.1"
chromatic = "~> 1.0"

[dev-dependencies]
gleeunit = "~> 1.0"
4 changes: 3 additions & 1 deletion manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# You typically do not need to edit this file

packages = [
{ name = "chromatic", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "chromatic", source = "hex", outer_checksum = "BEFE2D9BF1ABD369CCB5876A3A7814B0D7F2D307068D6E9755EAE497BEFE7B9E" },
{ name = "gleam_erlang", version = "0.24.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "26BDB52E61889F56A291CB34167315780EE4AA20961917314446542C90D1C1A0" },
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
Expand All @@ -11,9 +12,10 @@ packages = [
]

[requirements]
chromatic = { version = "~> 1.0"}
gleam_erlang = { version = "~> 0.24" }
gleam_otp = { version = "~> 0.10" }
gleam_stdlib = { version = "~> 0.34 or ~> 1.0" }
gleeunit = { version = "~> 1.0" }
glisten = { path = "../glisten" }
repeatedly = { version = "~> 2.1"}
repeatedly = { version = "~> 2.1" }
15 changes: 8 additions & 7 deletions src/data/entity.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ pub type PaperDollSlotType {
}

pub type Entity {
Entity(components: List(Component))
Entity(id: Int, components: List(Component))
}

pub fn new(components: List(Component)) -> Entity {
pub fn new(id: Int, components: List(Component)) -> Entity {
Entity(
id,
components
|> list.sort(fn(a, b) {
int.compare(component_priority(a), component_priority(b))
}),
|> list.sort(fn(a, b) {
int.compare(component_priority(a), component_priority(b))
}),
)
}

Expand Down Expand Up @@ -144,12 +145,12 @@ pub fn handle_event(entity: Entity, event: Event) -> #(Entity, Event) {
|> list.sort(fn(a, b) {
int.compare(component_priority(a), component_priority(b))
})
#(Entity(components: new_components), event)
#(Entity(entity.id, components: new_components), event)
}
_ -> {
let event = list.fold(entity.components, event, transform_event)
let new_components = list.map(entity.components, apply_event(_, event))
#(Entity(components: new_components), event)
#(Entity(entity.id, components: new_components), event)
}
}
}
Expand Down
29 changes: 15 additions & 14 deletions src/data/prefabs.gleam
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import gleam/int
import gleam/option.{None}
import model/entity
// pub fn create_guest_player() {
// entity.new([
// entity.Named(name: "Guest" <> int.to_string(int.random(99_999))),
// entity.Physical(hp: 10, size: 0),
// entity.PaperDollHead(entity: None),
// entity.PaperDollBack(entity: None),
// entity.PaperDollChest(entity: None),
// entity.PaperDollPrimaryHand(entity: None),
// entity.PaperDollOffHand(entity: None),
// entity.PaperDollLegs(entity: None),
// entity.PaperDollFeet(entity: None),
// ])
// }
import data/entity

pub fn create_guest_player() {
[
entity.Named(name: "Guest" <> int.to_string(int.random(99_999))),
entity.Physical(hp: 10, size: 0),
entity.PaperDollHead(entity: None),
entity.PaperDollBack(entity: None),
entity.PaperDollChest(entity: None),
entity.PaperDollPrimaryHand(entity: None),
entity.PaperDollOffHand(entity: None),
entity.PaperDollLegs(entity: None),
entity.PaperDollFeet(entity: None),
]
}
4 changes: 3 additions & 1 deletion src/data/world.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub type DataError {

pub type RoomTemplate {
RoomTemplate(
region: String,
name: String,
description: String,
exits: Dict(core.Direction, core.Location),
Expand Down Expand Up @@ -42,8 +43,9 @@ pub fn load_world() -> Result(WorldTemplate, DataError) {
|> add_room(
"testroom",
RoomTemplate(
region: "Test Region",
name: "Test Room",
description: "An empty test room",
description: "An empty test room. A black void of nothingness. You get the odd feeling there are actors here, communicating somehow. Some kind of play, perhaps?",
exits: dict.new(),
),
),
Expand Down
45 changes: 26 additions & 19 deletions src/model/entity.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,22 @@ import gleam/otp/actor
import model/sim_messages as msg
import data/entity as dataentity

/// Commands are sent from game connections to entities
pub type Command {
Look
}

/// Updates are sent from entities to game connections
pub type Update {
CommandSubject(Subject(Command))
// RoomDescription
}

type Message {
SimMessage(msg.Message)
CommandMessage(Command)
CommandMessage(msg.Command)
}

type EntityState {
EntityState(
entity: dataentity.Entity,
// the subject for this entity
entity_subject: Subject(msg.Message),
// the subject to talk to the parent room
room_subject: Subject(msg.Message),
// sent to game controllers when they take control of this entity
command_subject: Subject(Command),
command_subject: Subject(msg.Command),
// used for sending updates to game controllers
update_subject: Subject(Update),
update_subject: Subject(msg.Update),
)
}

Expand All @@ -38,10 +29,10 @@ type EntityState {
// and return
// - the entity_subject to send message to the entity
//
pub fn new(
pub fn start(
entity: dataentity.Entity,
room_subject: Subject(msg.Message),
update_subject: Subject(Update),
update_subject: Subject(msg.Update),
) -> Result(Subject(msg.Message), actor.StartError) {
let parent_subject = process.new_subject()

Expand All @@ -54,7 +45,10 @@ pub fn new(

// send the command subject over the update subject to the game connection
let command_subject = process.new_subject()
process.send(update_subject, CommandSubject(command_subject))
process.send(update_subject, msg.CommandSubject(command_subject))

// request initial room description
process.send(room_subject, msg.RequestRoomDescription(entity_subject))

//
let selector =
Expand All @@ -63,7 +57,13 @@ pub fn new(
|> process.selecting(command_subject, fn(msg) { CommandMessage(msg) })

actor.Ready(
EntityState(entity, room_subject, command_subject, update_subject),
EntityState(
entity,
entity_subject,
room_subject,
command_subject,
update_subject,
),
selector,
)
},
Expand All @@ -85,6 +85,13 @@ fn handle_message(
) -> actor.Next(Message, EntityState) {
case message {
SimMessage(msg.Tick) -> actor.continue(state)
_ -> todo
SimMessage(msg.ReplyRoomDescription(region, name, description)) -> {
process.send(
state.update_subject,
msg.RoomDescription(region, name, description),
)
actor.continue(state)
}
_ -> actor.continue(state)
}
}
10 changes: 9 additions & 1 deletion src/model/region.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import gleam/otp/actor
import data/world
import model/room
import model/sim_messages as msg
import gleam/io

type RegionState {
RegionState(
Expand Down Expand Up @@ -73,5 +72,14 @@ fn handle_message(

actor.continue(state)
}
msg.SpawnActorEntity(entity, location, update_subject) -> {
let assert Ok(room_subject) = dict.get(state.rooms, location.room)
process.send(
room_subject,
msg.SpawnActorEntity(entity, location, update_subject),
)
actor.continue(state)
}
_ -> actor.continue(state)
}
}
31 changes: 29 additions & 2 deletions src/model/room.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import gleam/erlang/process.{type Subject}
import gleam/function
import gleam/otp/actor
import data/world
import model/entity
import model/sim_messages as msg

type RoomState {
RoomState(
template: world.RoomTemplate,
region_subject: Subject(msg.Message),
entities: Dict(String, Subject(msg.Message)),
room_subject: Subject(msg.Message),
entities: Dict(Int, Subject(msg.Message)),
)
}

Expand All @@ -30,7 +32,10 @@ pub fn start(
process.new_selector()
|> process.selecting(room_subject, function.identity)

actor.Ready(RoomState(template, region_subject, dict.new()), selector)
actor.Ready(
RoomState(template, region_subject, room_subject, dict.new()),
selector,
)
},
init_timeout: 1000,
loop: handle_message,
Expand All @@ -51,5 +56,27 @@ fn handle_message(
) -> actor.Next(msg.Message, RoomState) {
case message {
msg.Tick -> actor.continue(state)
msg.SpawnActorEntity(entity, _, update_subject) -> {
let assert Ok(ent) =
entity.start(entity, state.room_subject, update_subject)
actor.continue(
RoomState(
..state,
entities: dict.insert(state.entities, entity.id, ent),
),
)
}
msg.RequestRoomDescription(reply) -> {
process.send(
reply,
msg.ReplyRoomDescription(
state.template.region,
state.template.name,
state.template.description,
),
)
actor.continue(state)
}
_ -> actor.continue(state)
}
}
19 changes: 19 additions & 0 deletions src/model/sim_messages.gleam
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
import gleam/erlang/process.{type Subject}
import data/core
import data/entity as dataentity

pub type Message {
Tick
SpawnActorEntity(dataentity.Entity, core.Location, Subject(Update))

RequestRoomDescription(Subject(Message))
ReplyRoomDescription(region: String, name: String, description: String)
}

/// Commands are sent from game connections to entities
pub type Command {
Look
}

/// Updates are sent from entities to game connections
pub type Update {
CommandSubject(Subject(Command))
RoomDescription(region: String, name: String, description: String)
}
17 changes: 12 additions & 5 deletions src/model/simulation.gleam
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import gleam/dict.{type Dict}
import gleam/erlang/process.{type Subject}
import gleam/io
import gleam/list
import gleam/otp/actor
import data/core
import data/entity as dataentity
import data/prefabs
import data/world
import model/region
import model/sim_messages as msg
import model/entity

/// Control message are sent by top level actors to control the sim directly
pub type Control {
JoinAsGuest(Subject(entity.Update))
JoinAsGuest(Subject(msg.Update))
Tick
Shutdown
}
Expand Down Expand Up @@ -85,8 +86,14 @@ fn handle_message(
state: SimState,
) -> actor.Next(SimMessage, SimState) {
case message {
Control(JoinAsGuest(update_channel)) -> {
io.debug("continue as guest")
Control(JoinAsGuest(update_subject)) -> {
let location = core.Location("testregion", "testroom")
let entity = dataentity.Entity(0, prefabs.create_guest_player())
let assert Ok(region_subject) = dict.get(state.regions, location.region)
process.send(
region_subject,
msg.SpawnActorEntity(entity, location, update_subject),
)
actor.continue(state)
}

Expand Down
Loading

0 comments on commit 0a8bf72

Please sign in to comment.