Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to MoveEvent. Add RemoteMoveEvent and RemoteDamageEvent. #114

Merged
merged 4 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions TowerForge/TowerForge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
3CAC4A732BB6B61C00A5D22E /* PlayerRenderStage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CAC4A722BB6B61C00A5D22E /* PlayerRenderStage.swift */; };
3CAC4A752BB6BDD500A5D22E /* HealthRenderStage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CAC4A742BB6BDD500A5D22E /* HealthRenderStage.swift */; };
3CBE72F92BC8D63500CC446A /* RemoteKillEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE72F82BC8D63500CC446A /* RemoteKillEvent.swift */; };
3CBE72FB2BC8D63E00CC446A /* RemoteDamageEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE72FA2BC8D63E00CC446A /* RemoteDamageEvent.swift */; };
3CBE72FD2BC8D64F00CC446A /* RemoteMoveEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE72FC2BC8D64F00CC446A /* RemoteMoveEvent.swift */; };
3CBE72FF2BC8D66C00CC446A /* RemotePowerupEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE72FE2BC8D66C00CC446A /* RemotePowerupEvent.swift */; };
3CBE73012BC8D69A00CC446A /* RemoteLifeEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE73002BC8D69A00CC446A /* RemoteLifeEvent.swift */; };
3CBECF892BBE9797005EF39B /* TFNetworkCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBECF882BBE9797005EF39B /* TFNetworkCoder.swift */; };
Expand Down Expand Up @@ -291,6 +293,8 @@
3CAC4A722BB6B61C00A5D22E /* PlayerRenderStage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerRenderStage.swift; sourceTree = "<group>"; };
3CAC4A742BB6BDD500A5D22E /* HealthRenderStage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthRenderStage.swift; sourceTree = "<group>"; };
3CBE72F82BC8D63500CC446A /* RemoteKillEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteKillEvent.swift; sourceTree = "<group>"; };
3CBE72FA2BC8D63E00CC446A /* RemoteDamageEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteDamageEvent.swift; sourceTree = "<group>"; };
3CBE72FC2BC8D64F00CC446A /* RemoteMoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteMoveEvent.swift; sourceTree = "<group>"; };
3CBE72FE2BC8D66C00CC446A /* RemotePowerupEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePowerupEvent.swift; sourceTree = "<group>"; };
3CBE73002BC8D69A00CC446A /* RemoteLifeEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteLifeEvent.swift; sourceTree = "<group>"; };
3CBECF882BBE9797005EF39B /* TFNetworkCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TFNetworkCoder.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -579,6 +583,8 @@
3CBECF8D2BBE9EAC005EF39B /* RemoteSpawnEvent.swift */,
3CBE72F82BC8D63500CC446A /* RemoteKillEvent.swift */,
3CBE73002BC8D69A00CC446A /* RemoteLifeEvent.swift */,
3CBE72FC2BC8D64F00CC446A /* RemoteMoveEvent.swift */,
3CBE72FA2BC8D63E00CC446A /* RemoteDamageEvent.swift */,
3CD37AA62BBEC5EF00222D8A /* BaseRemoteEvent.swift */,
3CBE72FE2BC8D66C00CC446A /* RemotePowerupEvent.swift */,
);
Expand Down Expand Up @@ -1510,6 +1516,7 @@
3C9955BA2BA5637200D33FA5 /* DamageEvent.swift in Sources */,
3CD37AA52BBEC10700222D8A /* FirebaseRemoteEventSubscriber.swift in Sources */,
52A794172BBC4F690083C976 /* GamePlayer.swift in Sources */,
3CBE72FD2BC8D64F00CC446A /* RemoteMoveEvent.swift in Sources */,
3CE951632BAE037C008B2785 /* AiSystem.swift in Sources */,
3CE9515F2BADE2C5008B2785 /* ShootingSystem.swift in Sources */,
5240D0AB2BB3340F004F1486 /* CaptureTheFlagMode.swift in Sources */,
Expand Down Expand Up @@ -1544,6 +1551,7 @@
5299D1342BC31067003EF746 /* AuthenticationProtocol.swift in Sources */,
527A07822BB3F8D300CD9D08 /* TimerProp.swift in Sources */,
52DF5FDE2BA32D7E00135367 /* EntityManager.swift in Sources */,
3CBE72FB2BC8D63E00CC446A /* RemoteDamageEvent.swift in Sources */,
52A794112BBC48FE0083C976 /* GameRoom.swift in Sources */,
3CD37AA72BBEC5EF00222D8A /* BaseRemoteEvent.swift in Sources */,
527A077C2BB3F4CC00CD9D08 /* KillEvent.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ class DamageComponent: TFComponent {
CACurrentMediaTime() - lastAttackTime >= attackRate
}

func damage(_ healthComponent: HealthComponent) -> TFEvent {
func damage(_ healthComponent: HealthComponent) -> [TFEvent] {
guard canDamage, let enemyId = healthComponent.entity?.id, let entityId = entity?.id else {
return DisabledEvent()
return []
}

guard let teamA = self.entity?.component(ofType: PlayerComponent.self)?.player,
let teamB = healthComponent.entity?.component(ofType: PlayerComponent.self)?.player,
teamA != teamB else {
return DisabledEvent()
return []
}

lastAttackTime = CACurrentMediaTime()
let event = DamageEvent(on: enemyId, at: lastAttackTime, with: attackPower, player: teamA)
var events: [TFEvent] = [DamageEvent(on: enemyId, at: lastAttackTime, with: attackPower, player: teamA)]

if temporary {
return event.concurrentlyWith(RemoveEvent(on: entityId, at: lastAttackTime))
events.append(RemoveEvent(on: entityId, at: lastAttackTime))
}
return event
return events
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,29 @@ class BaseTower: TFEntity {
self.addComponent(ContactComponent(hitboxSize: size))
}

override func collide(with other: any Collidable) -> TFEvent {
let superEvent = super.collide(with: other)
guard let healthComponent = self.component(ofType: HealthComponent.self) else {
return superEvent
override func collide(with other: any Collidable) -> [TFEvent] {
var events = super.collide(with: other)
if let healthComponent = self.component(ofType: HealthComponent.self) {
events.append(contentsOf: other.collide(with: healthComponent))
}

return superEvent.concurrentlyWith(other.collide(with: healthComponent))
return events
}

override func collide(with damageComponent: DamageComponent) -> TFEvent {
override func collide(with damageComponent: DamageComponent) -> [TFEvent] {
guard let healthComponent = self.component(ofType: HealthComponent.self) else {
return DisabledEvent()
return []
}
// No call to super here as super is done on collide with Collidable above.
return damageComponent.damage(healthComponent)
}

override func collide(with movableComponent: MovableComponent) -> (any TFEvent) {
override func collide(with movableComponent: MovableComponent) -> [TFEvent] {
if let playerA = self.component(ofType: PlayerComponent.self)?.player,
let playerB = movableComponent.entity?.component(ofType: PlayerComponent.self)?.player,
playerA != playerB {
movableComponent.shouldMove = false
}
return DisabledEvent()
return []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,16 @@ class BaseUnit: TFEntity {
self.addComponent(ContactComponent(hitboxSize: size))
}

override func collide(with other: any Collidable) -> TFEvent {
let superEvent = super.collide(with: other)
guard let healthComponent = self.component(ofType: HealthComponent.self),
let movableComponent = self.component(ofType: MovableComponent.self) else {
return superEvent
override func collide(with other: any Collidable) -> [TFEvent] {
var events = super.collide(with: other)
if let healthComponent = self.component(ofType: HealthComponent.self) {
events.append(contentsOf: other.collide(with: healthComponent))
}
if let movableComponent = self.component(ofType: MovableComponent.self) {
events.append(contentsOf: other.collide(with: movableComponent))
}

let event = other.collide(with: healthComponent)
.concurrentlyWith(other.collide(with: movableComponent))

return superEvent.concurrentlyWith(event)
return events
}

override func onSeparate() {
Expand All @@ -50,21 +49,21 @@ class BaseUnit: TFEntity {
movableComponent.shouldMove = true
}

override func collide(with damageComponent: DamageComponent) -> TFEvent {
override func collide(with damageComponent: DamageComponent) -> [TFEvent] {
guard let healthComponent = self.component(ofType: HealthComponent.self) else {
return DisabledEvent()
return []
}
// No call to super here as super is done on collide with Collidable above.
return damageComponent.damage(healthComponent)
}

override func collide(with movableComponent: MovableComponent) -> TFEvent {
override func collide(with movableComponent: MovableComponent) -> [TFEvent] {
if let playerA = self.component(ofType: PlayerComponent.self)?.player,
let playerB = movableComponent.entity?.component(ofType: PlayerComponent.self)?.player,
playerA != playerB {
movableComponent.shouldMove = false
}

return DisabledEvent()
return []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ class Bullet: BaseProjectile {
temporary: true))
}

override func collide(with other: any Collidable) -> TFEvent {
let superEvent = super.collide(with: other)
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return superEvent
override func collide(with other: any Collidable) -> [TFEvent] {
var events = super.collide(with: other)
if let damageComponent = self.component(ofType: DamageComponent.self) {
events.append(contentsOf: other.collide(with: damageComponent))
}
return superEvent.concurrentlyWith(other.collide(with: damageComponent))
return events
}

override func collide(with healthComponent: HealthComponent) -> TFEvent {
override func collide(with healthComponent: HealthComponent) -> [TFEvent] {
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return DisabledEvent()
return []
}
return damageComponent.damage(healthComponent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ class WizardBall: BaseProjectile {
temporary: true))
}

override func collide(with other: any Collidable) -> TFEvent {
let superEvent = super.collide(with: other)
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return superEvent
override func collide(with other: any Collidable) -> [TFEvent] {
var events = super.collide(with: other)
if let damageComponent = self.component(ofType: DamageComponent.self) {
events.append(contentsOf: other.collide(with: damageComponent))
}
return superEvent.concurrentlyWith(other.collide(with: damageComponent))
return events
}

override func collide(with healthComponent: HealthComponent) -> TFEvent {
override func collide(with healthComponent: HealthComponent) -> [TFEvent] {
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return DisabledEvent()
return []
}
return damageComponent.damage(healthComponent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ class MeleeUnit: BaseUnit, PlayerSpawnable {
temporary: false))
}

override func collide(with other: any Collidable) -> TFEvent {
let superEvent = super.collide(with: other)
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return superEvent
override func collide(with other: any Collidable) -> [TFEvent] {
var events = super.collide(with: other)
if let damageComponent = self.component(ofType: DamageComponent.self) {
events.append(contentsOf: other.collide(with: damageComponent))
}
return superEvent.concurrentlyWith(other.collide(with: damageComponent))
return events
}

override func collide(with healthComponent: HealthComponent) -> TFEvent {
override func collide(with healthComponent: HealthComponent) -> [TFEvent] {
guard let damageComponent = self.component(ofType: DamageComponent.self) else {
return DisabledEvent()
return []
}
return damageComponent.damage(healthComponent)
}
Expand Down
20 changes: 10 additions & 10 deletions TowerForge/TowerForge/GameModule/Entities/TFEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,31 @@ class TFEntity: Collidable {
}

// To be overriden by sub classes as needed
func collide(with other: any Collidable) -> TFEvent {
func collide(with other: any Collidable) -> [TFEvent] {
/// assert(checkRepresentation())
DisabledEvent()
[]
}

func onSeparate() {}

func collide(with damageComponent: DamageComponent) -> TFEvent {
func collide(with damageComponent: DamageComponent) -> [TFEvent] {
/// assert(checkRepresentation())
DisabledEvent()
[]
}

func collide(with healthComponent: HealthComponent) -> TFEvent {
func collide(with healthComponent: HealthComponent) -> [TFEvent] {
/// assert(checkRepresentation())
DisabledEvent()
[]
}

func collide(with movableComponent: MovableComponent) -> TFEvent {
func collide(with movableComponent: MovableComponent) -> [TFEvent] {
/// assert(checkRepresentation())
DisabledEvent()
[]
}

func collide(with playerComponent: PlayerComponent) -> TFEvent {
func collide(with playerComponent: PlayerComponent) -> [TFEvent] {
/// assert(checkRepresentation())
DisabledEvent()
[]
}

/// Ensures that the UUID keys of entries in the dictionary match the UUID id of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ import Foundation

protocol EventTransformation: Identifiable, AnyObject {
var id: UUID { get}
init(player: Player)
func transformEvent(event: TFEvent) -> TFEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import Foundation
class InvulnerabilityPowerUp: EventTransformation {
let DURATION = CGFloat(5)
let id: UUID
let player: Player

init() {
required init(player: Player = .ownPlayer) {
self.id = UUID()
self.player = player
}

func transformEvent(event: TFEvent) -> TFEvent {
guard let damageEvent = event as? DamageEvent, damageEvent.player == Player.oppositePlayer else {
guard let damageEvent = event as? DamageEvent, damageEvent.player == player.getOppositePlayer() else {
return event
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,20 @@ class ContactSystem: TFSystem {
}

private func handleContact(between entityA: TFEntity, and entityB: TFEntity) {
let event1 = entityA.collide(with: entityB)
let event2 = entityB.collide(with: entityA)
eventManager.add(event1.concurrentlyWith(event2))
var events = entityA.collide(with: entityB)
events.append(contentsOf: entityB.collide(with: entityA))

for event in events {
guard let damageEvent = event as? DamageEvent, let player = eventManager.currentPlayer else {
eventManager.add(event)
continue
}
guard eventManager.isHost else {
continue
}
eventManager.add(RemoteDamageEvent(id: damageEvent.entityId, damage: damageEvent.damage,
player: damageEvent.player, gamePlayer: player))
}
}

private func handleSeparation(for entity: TFEntity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ class MovementSystem: TFSystem {
}

func update(within time: CGFloat) {
for movableComponent in entityManager.components(ofType: MovableComponent.self) {
movableComponent.update(deltaTime: time)
}
entityManager.components(ofType: MovableComponent.self).forEach({
self.processMovableComponent($0, time: time)
})
}

/// Handles movement for the entity associated with the specified UUID according
Expand All @@ -34,4 +34,26 @@ class MovementSystem: TFSystem {
movementComponent.updatePosition(with: displacement)
}

private func processMovableComponent(_ movableComponent: MovableComponent, time: CGFloat) {
guard movableComponent.shouldMove, let entity = movableComponent.entity,
let player = entity.component(ofType: PlayerComponent.self)?.player else {
return
}

if entity is BaseProjectile {
movableComponent.update(deltaTime: time)
return
}

guard eventManager.isHost else {
return
}

let displacement = movableComponent.velocity * player.getDirectionVelocity() * time
guard let player = eventManager.currentPlayer else {
eventManager.add(MoveEvent(on: entity.id, at: Date().timeIntervalSince1970, with: displacement))
return
}
eventManager.add(RemoteMoveEvent(id: entity.id, moveBy: displacement, gamePlayer: player))
}
}
8 changes: 4 additions & 4 deletions TowerForge/TowerForge/LevelModule/Collision/Collidable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import Foundation

protocol Collidable {
func collide(with other: Collidable) -> TFEvent
func collide(with other: Collidable) -> [TFEvent]
func onSeparate()
func collide(with damageComponent: DamageComponent) -> TFEvent
func collide(with healthComponent: HealthComponent) -> TFEvent
func collide(with movableComponent: MovableComponent) -> TFEvent
func collide(with damageComponent: DamageComponent) -> [TFEvent]
func collide(with healthComponent: HealthComponent) -> [TFEvent]
func collide(with movableComponent: MovableComponent) -> [TFEvent]
}
Loading