Compare commits
	
		
			8 Commits
		
	
	
		
			main
			...
			feat/liten
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 05dfb92bab | |||
| 7f169fc788 | |||
| 376f18c43a | |||
| 150deaa618 | |||
| d011bf9a7a | |||
| 19124e733c | |||
| c28568d0cb | |||
| 91d301677f | 
							
								
								
									
										484
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										484
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,484 +0,0 @@
 | 
				
			|||||||
## Ignore Visual Studio temporary files, build results, and
 | 
					 | 
				
			||||||
## files generated by popular Visual Studio add-ons.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Get latest from `dotnet new gitignore`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# dotenv files
 | 
					 | 
				
			||||||
.env
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# User-specific files
 | 
					 | 
				
			||||||
*.rsuser
 | 
					 | 
				
			||||||
*.suo
 | 
					 | 
				
			||||||
*.user
 | 
					 | 
				
			||||||
*.userosscache
 | 
					 | 
				
			||||||
*.sln.docstates
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# User-specific files (MonoDevelop/Xamarin Studio)
 | 
					 | 
				
			||||||
*.userprefs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Mono auto generated files
 | 
					 | 
				
			||||||
mono_crash.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Build results
 | 
					 | 
				
			||||||
[Dd]ebug/
 | 
					 | 
				
			||||||
[Dd]ebugPublic/
 | 
					 | 
				
			||||||
[Rr]elease/
 | 
					 | 
				
			||||||
[Rr]eleases/
 | 
					 | 
				
			||||||
x64/
 | 
					 | 
				
			||||||
x86/
 | 
					 | 
				
			||||||
[Ww][Ii][Nn]32/
 | 
					 | 
				
			||||||
[Aa][Rr][Mm]/
 | 
					 | 
				
			||||||
[Aa][Rr][Mm]64/
 | 
					 | 
				
			||||||
bld/
 | 
					 | 
				
			||||||
[Bb]in/
 | 
					 | 
				
			||||||
[Oo]bj/
 | 
					 | 
				
			||||||
[Ll]og/
 | 
					 | 
				
			||||||
[Ll]ogs/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 2015/2017 cache/options directory
 | 
					 | 
				
			||||||
.vs/
 | 
					 | 
				
			||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
 | 
					 | 
				
			||||||
#wwwroot/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 2017 auto generated files
 | 
					 | 
				
			||||||
Generated\ Files/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MSTest test Results
 | 
					 | 
				
			||||||
[Tt]est[Rr]esult*/
 | 
					 | 
				
			||||||
[Bb]uild[Ll]og.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# NUnit
 | 
					 | 
				
			||||||
*.VisualState.xml
 | 
					 | 
				
			||||||
TestResult.xml
 | 
					 | 
				
			||||||
nunit-*.xml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Build Results of an ATL Project
 | 
					 | 
				
			||||||
[Dd]ebugPS/
 | 
					 | 
				
			||||||
[Rr]eleasePS/
 | 
					 | 
				
			||||||
dlldata.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Benchmark Results
 | 
					 | 
				
			||||||
BenchmarkDotNet.Artifacts/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# .NET
 | 
					 | 
				
			||||||
project.lock.json
 | 
					 | 
				
			||||||
project.fragment.lock.json
 | 
					 | 
				
			||||||
artifacts/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Tye
 | 
					 | 
				
			||||||
.tye/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# ASP.NET Scaffolding
 | 
					 | 
				
			||||||
ScaffoldingReadMe.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# StyleCop
 | 
					 | 
				
			||||||
StyleCopReport.xml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Files built by Visual Studio
 | 
					 | 
				
			||||||
*_i.c
 | 
					 | 
				
			||||||
*_p.c
 | 
					 | 
				
			||||||
*_h.h
 | 
					 | 
				
			||||||
*.ilk
 | 
					 | 
				
			||||||
*.meta
 | 
					 | 
				
			||||||
*.obj
 | 
					 | 
				
			||||||
*.iobj
 | 
					 | 
				
			||||||
*.pch
 | 
					 | 
				
			||||||
*.pdb
 | 
					 | 
				
			||||||
*.ipdb
 | 
					 | 
				
			||||||
*.pgc
 | 
					 | 
				
			||||||
*.pgd
 | 
					 | 
				
			||||||
*.rsp
 | 
					 | 
				
			||||||
*.sbr
 | 
					 | 
				
			||||||
*.tlb
 | 
					 | 
				
			||||||
*.tli
 | 
					 | 
				
			||||||
*.tlh
 | 
					 | 
				
			||||||
*.tmp
 | 
					 | 
				
			||||||
*.tmp_proj
 | 
					 | 
				
			||||||
*_wpftmp.csproj
 | 
					 | 
				
			||||||
*.log
 | 
					 | 
				
			||||||
*.tlog
 | 
					 | 
				
			||||||
*.vspscc
 | 
					 | 
				
			||||||
*.vssscc
 | 
					 | 
				
			||||||
.builds
 | 
					 | 
				
			||||||
*.pidb
 | 
					 | 
				
			||||||
*.svclog
 | 
					 | 
				
			||||||
*.scc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Chutzpah Test files
 | 
					 | 
				
			||||||
_Chutzpah*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual C++ cache files
 | 
					 | 
				
			||||||
ipch/
 | 
					 | 
				
			||||||
*.aps
 | 
					 | 
				
			||||||
*.ncb
 | 
					 | 
				
			||||||
*.opendb
 | 
					 | 
				
			||||||
*.opensdf
 | 
					 | 
				
			||||||
*.sdf
 | 
					 | 
				
			||||||
*.cachefile
 | 
					 | 
				
			||||||
*.VC.db
 | 
					 | 
				
			||||||
*.VC.VC.opendb
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio profiler
 | 
					 | 
				
			||||||
*.psess
 | 
					 | 
				
			||||||
*.vsp
 | 
					 | 
				
			||||||
*.vspx
 | 
					 | 
				
			||||||
*.sap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio Trace Files
 | 
					 | 
				
			||||||
*.e2e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# TFS 2012 Local Workspace
 | 
					 | 
				
			||||||
$tf/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Guidance Automation Toolkit
 | 
					 | 
				
			||||||
*.gpState
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# ReSharper is a .NET coding add-in
 | 
					 | 
				
			||||||
_ReSharper*/
 | 
					 | 
				
			||||||
*.[Rr]e[Ss]harper
 | 
					 | 
				
			||||||
*.DotSettings.user
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# TeamCity is a build add-in
 | 
					 | 
				
			||||||
_TeamCity*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# DotCover is a Code Coverage Tool
 | 
					 | 
				
			||||||
*.dotCover
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# AxoCover is a Code Coverage Tool
 | 
					 | 
				
			||||||
.axoCover/*
 | 
					 | 
				
			||||||
!.axoCover/settings.json
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Coverlet is a free, cross platform Code Coverage Tool
 | 
					 | 
				
			||||||
coverage*.json
 | 
					 | 
				
			||||||
coverage*.xml
 | 
					 | 
				
			||||||
coverage*.info
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio code coverage results
 | 
					 | 
				
			||||||
*.coverage
 | 
					 | 
				
			||||||
*.coveragexml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# NCrunch
 | 
					 | 
				
			||||||
_NCrunch_*
 | 
					 | 
				
			||||||
.*crunch*.local.xml
 | 
					 | 
				
			||||||
nCrunchTemp_*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MightyMoose
 | 
					 | 
				
			||||||
*.mm.*
 | 
					 | 
				
			||||||
AutoTest.Net/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Web workbench (sass)
 | 
					 | 
				
			||||||
.sass-cache/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Installshield output folder
 | 
					 | 
				
			||||||
[Ee]xpress/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# DocProject is a documentation generator add-in
 | 
					 | 
				
			||||||
DocProject/buildhelp/
 | 
					 | 
				
			||||||
DocProject/Help/*.HxT
 | 
					 | 
				
			||||||
DocProject/Help/*.HxC
 | 
					 | 
				
			||||||
DocProject/Help/*.hhc
 | 
					 | 
				
			||||||
DocProject/Help/*.hhk
 | 
					 | 
				
			||||||
DocProject/Help/*.hhp
 | 
					 | 
				
			||||||
DocProject/Help/Html2
 | 
					 | 
				
			||||||
DocProject/Help/html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Click-Once directory
 | 
					 | 
				
			||||||
publish/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Publish Web Output
 | 
					 | 
				
			||||||
*.[Pp]ublish.xml
 | 
					 | 
				
			||||||
*.azurePubxml
 | 
					 | 
				
			||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
 | 
					 | 
				
			||||||
# but database connection strings (with potential passwords) will be unencrypted
 | 
					 | 
				
			||||||
*.pubxml
 | 
					 | 
				
			||||||
*.publishproj
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
 | 
					 | 
				
			||||||
# checkin your Azure Web App publish settings, but sensitive information contained
 | 
					 | 
				
			||||||
# in these scripts will be unencrypted
 | 
					 | 
				
			||||||
PublishScripts/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# NuGet Packages
 | 
					 | 
				
			||||||
*.nupkg
 | 
					 | 
				
			||||||
# NuGet Symbol Packages
 | 
					 | 
				
			||||||
*.snupkg
 | 
					 | 
				
			||||||
# The packages folder can be ignored because of Package Restore
 | 
					 | 
				
			||||||
**/[Pp]ackages/*
 | 
					 | 
				
			||||||
# except build/, which is used as an MSBuild target.
 | 
					 | 
				
			||||||
!**/[Pp]ackages/build/
 | 
					 | 
				
			||||||
# Uncomment if necessary however generally it will be regenerated when needed
 | 
					 | 
				
			||||||
#!**/[Pp]ackages/repositories.config
 | 
					 | 
				
			||||||
# NuGet v3's project.json files produces more ignorable files
 | 
					 | 
				
			||||||
*.nuget.props
 | 
					 | 
				
			||||||
*.nuget.targets
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Microsoft Azure Build Output
 | 
					 | 
				
			||||||
csx/
 | 
					 | 
				
			||||||
*.build.csdef
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Microsoft Azure Emulator
 | 
					 | 
				
			||||||
ecf/
 | 
					 | 
				
			||||||
rcf/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Windows Store app package directories and files
 | 
					 | 
				
			||||||
AppPackages/
 | 
					 | 
				
			||||||
BundleArtifacts/
 | 
					 | 
				
			||||||
Package.StoreAssociation.xml
 | 
					 | 
				
			||||||
_pkginfo.txt
 | 
					 | 
				
			||||||
*.appx
 | 
					 | 
				
			||||||
*.appxbundle
 | 
					 | 
				
			||||||
*.appxupload
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio cache files
 | 
					 | 
				
			||||||
# files ending in .cache can be ignored
 | 
					 | 
				
			||||||
*.[Cc]ache
 | 
					 | 
				
			||||||
# but keep track of directories ending in .cache
 | 
					 | 
				
			||||||
!?*.[Cc]ache/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Others
 | 
					 | 
				
			||||||
ClientBin/
 | 
					 | 
				
			||||||
~$*
 | 
					 | 
				
			||||||
*~
 | 
					 | 
				
			||||||
*.dbmdl
 | 
					 | 
				
			||||||
*.dbproj.schemaview
 | 
					 | 
				
			||||||
*.jfm
 | 
					 | 
				
			||||||
*.pfx
 | 
					 | 
				
			||||||
*.publishsettings
 | 
					 | 
				
			||||||
orleans.codegen.cs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Including strong name files can present a security risk
 | 
					 | 
				
			||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
 | 
					 | 
				
			||||||
#*.snk
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
 | 
					 | 
				
			||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
 | 
					 | 
				
			||||||
#bower_components/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RIA/Silverlight projects
 | 
					 | 
				
			||||||
Generated_Code/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Backup & report files from converting an old project file
 | 
					 | 
				
			||||||
# to a newer Visual Studio version. Backup files are not needed,
 | 
					 | 
				
			||||||
# because we have git ;-)
 | 
					 | 
				
			||||||
_UpgradeReport_Files/
 | 
					 | 
				
			||||||
Backup*/
 | 
					 | 
				
			||||||
UpgradeLog*.XML
 | 
					 | 
				
			||||||
UpgradeLog*.htm
 | 
					 | 
				
			||||||
ServiceFabricBackup/
 | 
					 | 
				
			||||||
*.rptproj.bak
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SQL Server files
 | 
					 | 
				
			||||||
*.mdf
 | 
					 | 
				
			||||||
*.ldf
 | 
					 | 
				
			||||||
*.ndf
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Business Intelligence projects
 | 
					 | 
				
			||||||
*.rdl.data
 | 
					 | 
				
			||||||
*.bim.layout
 | 
					 | 
				
			||||||
*.bim_*.settings
 | 
					 | 
				
			||||||
*.rptproj.rsuser
 | 
					 | 
				
			||||||
*- [Bb]ackup.rdl
 | 
					 | 
				
			||||||
*- [Bb]ackup ([0-9]).rdl
 | 
					 | 
				
			||||||
*- [Bb]ackup ([0-9][0-9]).rdl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Microsoft Fakes
 | 
					 | 
				
			||||||
FakesAssemblies/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# GhostDoc plugin setting file
 | 
					 | 
				
			||||||
*.GhostDoc.xml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Node.js Tools for Visual Studio
 | 
					 | 
				
			||||||
.ntvs_analysis.dat
 | 
					 | 
				
			||||||
node_modules/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 build log
 | 
					 | 
				
			||||||
*.plg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 workspace options file
 | 
					 | 
				
			||||||
*.opt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
 | 
					 | 
				
			||||||
*.vbw
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
 | 
					 | 
				
			||||||
*.vbp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
 | 
					 | 
				
			||||||
*.dsw
 | 
					 | 
				
			||||||
*.dsp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio 6 technical files
 | 
					 | 
				
			||||||
*.ncb
 | 
					 | 
				
			||||||
*.aps
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio LightSwitch build output
 | 
					 | 
				
			||||||
**/*.HTMLClient/GeneratedArtifacts
 | 
					 | 
				
			||||||
**/*.DesktopClient/GeneratedArtifacts
 | 
					 | 
				
			||||||
**/*.DesktopClient/ModelManifest.xml
 | 
					 | 
				
			||||||
**/*.Server/GeneratedArtifacts
 | 
					 | 
				
			||||||
**/*.Server/ModelManifest.xml
 | 
					 | 
				
			||||||
_Pvt_Extensions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Paket dependency manager
 | 
					 | 
				
			||||||
.paket/paket.exe
 | 
					 | 
				
			||||||
paket-files/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# FAKE - F# Make
 | 
					 | 
				
			||||||
.fake/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CodeRush personal settings
 | 
					 | 
				
			||||||
.cr/personal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Python Tools for Visual Studio (PTVS)
 | 
					 | 
				
			||||||
__pycache__/
 | 
					 | 
				
			||||||
*.pyc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Cake - Uncomment if you are using it
 | 
					 | 
				
			||||||
# tools/**
 | 
					 | 
				
			||||||
# !tools/packages.config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Tabs Studio
 | 
					 | 
				
			||||||
*.tss
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Telerik's JustMock configuration file
 | 
					 | 
				
			||||||
*.jmconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BizTalk build output
 | 
					 | 
				
			||||||
*.btp.cs
 | 
					 | 
				
			||||||
*.btm.cs
 | 
					 | 
				
			||||||
*.odx.cs
 | 
					 | 
				
			||||||
*.xsd.cs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# OpenCover UI analysis results
 | 
					 | 
				
			||||||
OpenCover/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Azure Stream Analytics local run output
 | 
					 | 
				
			||||||
ASALocalRun/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MSBuild Binary and Structured Log
 | 
					 | 
				
			||||||
*.binlog
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# NVidia Nsight GPU debugger configuration file
 | 
					 | 
				
			||||||
*.nvuser
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MFractors (Xamarin productivity tool) working folder
 | 
					 | 
				
			||||||
.mfractor/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Local History for Visual Studio
 | 
					 | 
				
			||||||
.localhistory/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Visual Studio History (VSHistory) files
 | 
					 | 
				
			||||||
.vshistory/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BeatPulse healthcheck temp database
 | 
					 | 
				
			||||||
healthchecksdb
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
 | 
					 | 
				
			||||||
MigrationBackup/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Ionide (cross platform F# VS Code tools) working folder
 | 
					 | 
				
			||||||
.ionide/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Fody - auto-generated XML schema
 | 
					 | 
				
			||||||
FodyWeavers.xsd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# VS Code files for those working on multiple tools
 | 
					 | 
				
			||||||
.vscode/*
 | 
					 | 
				
			||||||
!.vscode/settings.json
 | 
					 | 
				
			||||||
!.vscode/tasks.json
 | 
					 | 
				
			||||||
!.vscode/launch.json
 | 
					 | 
				
			||||||
!.vscode/extensions.json
 | 
					 | 
				
			||||||
*.code-workspace
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Local History for Visual Studio Code
 | 
					 | 
				
			||||||
.history/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Windows Installer files from build outputs
 | 
					 | 
				
			||||||
*.cab
 | 
					 | 
				
			||||||
*.msi
 | 
					 | 
				
			||||||
*.msix
 | 
					 | 
				
			||||||
*.msm
 | 
					 | 
				
			||||||
*.msp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# JetBrains Rider
 | 
					 | 
				
			||||||
*.sln.iml
 | 
					 | 
				
			||||||
.idea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Visual studio for Mac
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# globs
 | 
					 | 
				
			||||||
Makefile.in
 | 
					 | 
				
			||||||
*.userprefs
 | 
					 | 
				
			||||||
*.usertasks
 | 
					 | 
				
			||||||
config.make
 | 
					 | 
				
			||||||
config.status
 | 
					 | 
				
			||||||
aclocal.m4
 | 
					 | 
				
			||||||
install-sh
 | 
					 | 
				
			||||||
autom4te.cache/
 | 
					 | 
				
			||||||
*.tar.gz
 | 
					 | 
				
			||||||
tarballs/
 | 
					 | 
				
			||||||
test-results/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Mac bundle stuff
 | 
					 | 
				
			||||||
*.dmg
 | 
					 | 
				
			||||||
*.app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
 | 
					 | 
				
			||||||
# General
 | 
					 | 
				
			||||||
.DS_Store
 | 
					 | 
				
			||||||
.AppleDouble
 | 
					 | 
				
			||||||
.LSOverride
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Icon must end with two \r
 | 
					 | 
				
			||||||
Icon
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Thumbnails
 | 
					 | 
				
			||||||
._*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Files that might appear in the root of a volume
 | 
					 | 
				
			||||||
.DocumentRevisions-V100
 | 
					 | 
				
			||||||
.fseventsd
 | 
					 | 
				
			||||||
.Spotlight-V100
 | 
					 | 
				
			||||||
.TemporaryItems
 | 
					 | 
				
			||||||
.Trashes
 | 
					 | 
				
			||||||
.VolumeIcon.icns
 | 
					 | 
				
			||||||
.com.apple.timemachine.donotpresent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Directories potentially created on remote AFP share
 | 
					 | 
				
			||||||
.AppleDB
 | 
					 | 
				
			||||||
.AppleDesktop
 | 
					 | 
				
			||||||
Network Trash Folder
 | 
					 | 
				
			||||||
Temporary Items
 | 
					 | 
				
			||||||
.apdisk
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
 | 
					 | 
				
			||||||
# Windows thumbnail cache files
 | 
					 | 
				
			||||||
Thumbs.db
 | 
					 | 
				
			||||||
ehthumbs.db
 | 
					 | 
				
			||||||
ehthumbs_vista.db
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Dump file
 | 
					 | 
				
			||||||
*.stackdump
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Folder config file
 | 
					 | 
				
			||||||
[Dd]esktop.ini
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Recycle Bin used on file shares
 | 
					 | 
				
			||||||
$RECYCLE.BIN/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Windows Installer files
 | 
					 | 
				
			||||||
*.cab
 | 
					 | 
				
			||||||
*.msi
 | 
					 | 
				
			||||||
*.msix
 | 
					 | 
				
			||||||
*.msm
 | 
					 | 
				
			||||||
*.msp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Windows shortcuts
 | 
					 | 
				
			||||||
*.lnk
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Vim temporary swap files
 | 
					 | 
				
			||||||
*.swp
 | 
					 | 
				
			||||||
							
								
								
									
										86
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										86
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							@@ -1,80 +1,46 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  // Use IntelliSense to learn about possible attributes.
 | 
				
			||||||
 | 
					  // Hover to view descriptions of existing attributes.
 | 
				
			||||||
 | 
					  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
				
			||||||
  "version": "0.2.0",
 | 
					  "version": "0.2.0",
 | 
				
			||||||
  "configurations": [
 | 
					  "configurations": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "name": ".NET Launch (Client) 1",
 | 
					      "name": "Start Client",
 | 
				
			||||||
      "type": "coreclr",
 | 
					      "type": "coreclr",
 | 
				
			||||||
      "request": "launch",
 | 
					      "request": "launch",
 | 
				
			||||||
      "preLaunchTask": "build-client",
 | 
					      "preLaunchTask": "build",
 | 
				
			||||||
      "program": "${workspaceFolder}/Platforms/Desktop/bin/Debug/net9.0/Pong.dll",
 | 
					      // If you have changed target frameworks, make sure to update the program path.
 | 
				
			||||||
      "args": [],
 | 
					      "program": "${workspaceFolder}/Game/bin/Debug/net8.0/Game.dll",
 | 
				
			||||||
 | 
					      "args": ["127.0.0.1"],
 | 
				
			||||||
      "cwd": "${workspaceFolder}",
 | 
					      "cwd": "${workspaceFolder}",
 | 
				
			||||||
      "stopAtEntry": false,
 | 
					      // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
 | 
				
			||||||
      "console": "internalConsole",
 | 
					      "console": "internalConsole",
 | 
				
			||||||
      "justMyCode": false,
 | 
					      "stopAtEntry": false
 | 
				
			||||||
      "logging": {
 | 
					 | 
				
			||||||
        "moduleLoad": false,
 | 
					 | 
				
			||||||
        "programOutput": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "name": ".NET Launch (Client) 2",
 | 
					      "name": ".NET Core Attach",
 | 
				
			||||||
 | 
					      "type": "coreclr",
 | 
				
			||||||
 | 
					      "request": "attach",
 | 
				
			||||||
 | 
					      "processId": "${command:pickProcess}"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "Start Server",
 | 
				
			||||||
      "type": "coreclr",
 | 
					      "type": "coreclr",
 | 
				
			||||||
      "request": "launch",
 | 
					      "request": "launch",
 | 
				
			||||||
      "preLaunchTask": "build-client",
 | 
					      "preLaunchTask": "build",
 | 
				
			||||||
      "program": "${workspaceFolder}/Platforms/Desktop/bin/Debug/net9.0/Desktop.dll",
 | 
					      // If you have changed target frameworks, make sure to update the program path.
 | 
				
			||||||
      "args": [],
 | 
					      "program": "${workspaceFolder}/Game/bin/Debug/net8.0/Game.dll",
 | 
				
			||||||
 | 
					      "args": ["server"],
 | 
				
			||||||
      "cwd": "${workspaceFolder}",
 | 
					      "cwd": "${workspaceFolder}",
 | 
				
			||||||
      "stopAtEntry": false,
 | 
					      // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
 | 
				
			||||||
      "console": "internalConsole",
 | 
					      "console": "internalConsole",
 | 
				
			||||||
      "justMyCode": false,
 | 
					      "stopAtEntry": false
 | 
				
			||||||
      "logging": {
 | 
					 | 
				
			||||||
        "moduleLoad": false,
 | 
					 | 
				
			||||||
        "programOutput": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "name": ".NET Launch (Server)",
 | 
					      "name": ".NET Core Attach",
 | 
				
			||||||
      "type": "coreclr",
 | 
					      "type": "coreclr",
 | 
				
			||||||
      "request": "launch",
 | 
					      "request": "attach",
 | 
				
			||||||
      "preLaunchTask": "build-server",
 | 
					      "processId": "${command:pickProcess}"
 | 
				
			||||||
      "program": "${workspaceFolder}/Platforms/Server/bin/Debug/net9.0/Server.dll",
 | 
					 | 
				
			||||||
      "args": [],
 | 
					 | 
				
			||||||
      "env": {
 | 
					 | 
				
			||||||
        "PORT": "8888",
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "cwd": "${workspaceFolder}",
 | 
					 | 
				
			||||||
      "stopAtEntry": false,
 | 
					 | 
				
			||||||
      "console": "internalConsole",
 | 
					 | 
				
			||||||
      "justMyCode": false,
 | 
					 | 
				
			||||||
      "logging": {
 | 
					 | 
				
			||||||
        "moduleLoad": false,
 | 
					 | 
				
			||||||
        "programOutput": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  "compounds": [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "name": ".NET Launch Client & Server",
 | 
					 | 
				
			||||||
      "configurations": [
 | 
					 | 
				
			||||||
        ".NET Launch (Server)",
 | 
					 | 
				
			||||||
        ".NET Launch (Client) 1"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "name": ".NET Launch 2 Client & 1 Server",
 | 
					 | 
				
			||||||
      "configurations": [
 | 
					 | 
				
			||||||
        ".NET Launch (Server)",
 | 
					 | 
				
			||||||
        ".NET Launch (Client) 1",
 | 
					 | 
				
			||||||
        ".NET Launch (Client) 2"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "name": ".NET Launch 2 Clients",
 | 
					 | 
				
			||||||
      "configurations": [
 | 
					 | 
				
			||||||
        ".NET Launch (Client) 1",
 | 
					 | 
				
			||||||
        ".NET Launch (Client) 2"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "cSpell.words": [
 | 
				
			||||||
 | 
					        "AABB",
 | 
				
			||||||
 | 
					        "DAABB",
 | 
				
			||||||
 | 
					        "Syntriax"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							@@ -2,32 +2,14 @@
 | 
				
			|||||||
  "version": "2.0.0",
 | 
					  "version": "2.0.0",
 | 
				
			||||||
  "tasks": [
 | 
					  "tasks": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "label": "build-client",
 | 
					      "type": "dotnet",
 | 
				
			||||||
      "command": "dotnet",
 | 
					      "task": "build",
 | 
				
			||||||
      "type": "process",
 | 
					      "problemMatcher": ["$msCompile"],
 | 
				
			||||||
      "args": [
 | 
					 | 
				
			||||||
        "build",
 | 
					 | 
				
			||||||
        "${workspaceFolder}/Platforms/Desktop"
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      "problemMatcher": "$msCompile",
 | 
					 | 
				
			||||||
      "group": {
 | 
					      "group": {
 | 
				
			||||||
        "kind": "build",
 | 
					        "kind": "build",
 | 
				
			||||||
        "isDefault": true
 | 
					        "isDefault": true
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
    },
 | 
					      "label": "build"
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "label": "build-server",
 | 
					 | 
				
			||||||
      "command": "dotnet",
 | 
					 | 
				
			||||||
      "type": "process",
 | 
					 | 
				
			||||||
      "args": [
 | 
					 | 
				
			||||||
        "build",
 | 
					 | 
				
			||||||
        "${workspaceFolder}/Platforms/Server"
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      "problemMatcher": "$msCompile",
 | 
					 | 
				
			||||||
      "group": {
 | 
					 | 
				
			||||||
        "kind": "build",
 | 
					 | 
				
			||||||
        "isDefault": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,16 +0,0 @@
 | 
				
			|||||||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /App
 | 
					 | 
				
			||||||
COPY . ./
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN dotnet restore
 | 
					 | 
				
			||||||
RUN dotnet publish Platforms/Server -c Release -r linux-musl-x64 --self-contained true -o out
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FROM alpine:latest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /App
 | 
					 | 
				
			||||||
COPY --from=build /App/out .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN apk add --no-cache icu-libs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENTRYPOINT ["./Server"]
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								Engine
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								Engine
									
									
									
									
									
								
							 Submodule Engine updated: 65dcb0c564...ef21cdf213
									
								
							@@ -3,31 +3,31 @@
 | 
				
			|||||||
  "isRoot": true,
 | 
					  "isRoot": true,
 | 
				
			||||||
  "tools": {
 | 
					  "tools": {
 | 
				
			||||||
    "dotnet-mgcb": {
 | 
					    "dotnet-mgcb": {
 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					      "version": "3.8.1.303",
 | 
				
			||||||
      "commands": [
 | 
					      "commands": [
 | 
				
			||||||
        "mgcb"
 | 
					        "mgcb"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "dotnet-mgcb-editor": {
 | 
					    "dotnet-mgcb-editor": {
 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					      "version": "3.8.1.303",
 | 
				
			||||||
      "commands": [
 | 
					      "commands": [
 | 
				
			||||||
        "mgcb-editor"
 | 
					        "mgcb-editor"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "dotnet-mgcb-editor-linux": {
 | 
					    "dotnet-mgcb-editor-linux": {
 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					      "version": "3.8.1.303",
 | 
				
			||||||
      "commands": [
 | 
					      "commands": [
 | 
				
			||||||
        "mgcb-editor-linux"
 | 
					        "mgcb-editor-linux"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "dotnet-mgcb-editor-windows": {
 | 
					    "dotnet-mgcb-editor-windows": {
 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					      "version": "3.8.1.303",
 | 
				
			||||||
      "commands": [
 | 
					      "commands": [
 | 
				
			||||||
        "mgcb-editor-windows"
 | 
					        "mgcb-editor-windows"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "dotnet-mgcb-editor-mac": {
 | 
					    "dotnet-mgcb-editor-mac": {
 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					      "version": "3.8.1.303",
 | 
				
			||||||
      "commands": [
 | 
					      "commands": [
 | 
				
			||||||
        "mgcb-editor-mac"
 | 
					        "mgcb-editor-mac"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
							
								
								
									
										0
									
								
								.dockerignore → Game/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								.dockerignore → Game/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										8
									
								
								Game/Abstract/IDisplayableShape.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Game/Abstract/IDisplayableShape.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					using Apos.Shapes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface IDisplayableShape
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void Draw(ShapeBatch shapeBatch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								Game/Abstract/IDisplayableSprite.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Game/Abstract/IDisplayableSprite.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface IDisplayableSprite
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public void Draw(SpriteBatch spriteBatch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										81
									
								
								Game/Behaviours/BallBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								Game/Behaviours/BallBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BallBehaviour : BehaviourOverride
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
 | 
				
			||||||
 | 
					    public float Speed { get; set; } = 500f;
 | 
				
			||||||
 | 
					    public float SpeedUpMultiplier { get; set; } = .0125f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Random random = new();
 | 
				
			||||||
 | 
					    private IRigidBody2D rigidBody = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? foundRigidBody))
 | 
				
			||||||
 | 
					            throw new Exception($"{nameof(IRigidBody2D)} is missing on {GameObject.Name}.");
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out ICollider2D? foundCollider))
 | 
				
			||||||
 | 
					            throw new Exception($"{nameof(ICollider2D)} is missing on {GameObject.Name}.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foundCollider.OnCollisionDetected += OnCollisionDetected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rigidBody = foundRigidBody;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (GameObject.GameManager.TryFindBehaviour(out PongManagerBehaviour? pongManager))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            pongManager.OnReset += ResetBall;
 | 
				
			||||||
 | 
					            pongManager.OnScored += ResetBall;
 | 
				
			||||||
 | 
					            pongManager.OnFinished += DisableBall;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void DisableBall(PongManagerBehaviour pongManager)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
 | 
				
			||||||
 | 
					        rigidBody.Velocity = Vector2D.Zero;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void ResetBall(PongManagerBehaviour pongManager)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        StateEnable.Enabled = true;
 | 
				
			||||||
 | 
					        BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
 | 
				
			||||||
 | 
					        rigidBody.Velocity = GetRandomDirection() * Speed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Vector2D GetRandomDirection()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const float AllowedRadians = 45f * Syntriax.Engine.Core.Math.DegreeToRadian;
 | 
				
			||||||
 | 
					        float rotation = (float)random.NextDouble() * 2f * AllowedRadians - AllowedRadians;
 | 
				
			||||||
 | 
					        bool isBackwards = (random.Next() % 2) == 1;
 | 
				
			||||||
 | 
					        return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector2D speedUp = rigidBody.Velocity.Normalized * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					        rigidBody.Velocity += speedUp * SpeedUpMultiplier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
 | 
				
			||||||
 | 
					            rigidBody.Velocity = information.Left.Transform.Position.FromTo(information.Right.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BallBehaviour() { }
 | 
				
			||||||
 | 
					    public BallBehaviour(Vector2D startDirection, float speed)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        StartDirection = Vector2D.Normalize(startDirection);
 | 
				
			||||||
 | 
					        Speed = speed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										74
									
								
								Game/Behaviours/CameraController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Game/Behaviours/CameraController.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class CameraController : BehaviourOverride
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private MonoGameCamera2DBehaviour cameraBehaviour = null!;
 | 
				
			||||||
 | 
					    private IButtonInputs<Keys> buttonInputs = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private float defaultZoomLevel = 1f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (BehaviourController.TryGetBehaviour(out MonoGameCamera2DBehaviour? foundCameraBehaviour))
 | 
				
			||||||
 | 
					            cameraBehaviour = foundCameraBehaviour;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cameraBehaviour ??= BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (BehaviourController.TryGetBehaviour(out IButtonInputs<Keys>? foundButtonInputs))
 | 
				
			||||||
 | 
					            buttonInputs = foundButtonInputs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buttonInputs ??= BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
 | 
				
			||||||
 | 
					        buttonInputs.RegisterOnPress(Keys.F, SwitchToFullScreen);
 | 
				
			||||||
 | 
					        buttonInputs.RegisterOnPress(Keys.R, ResetCamera);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.U))
 | 
				
			||||||
 | 
					            cameraBehaviour.Zoom += Time.Elapsed.Nanoseconds * 0.00025f;
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.J))
 | 
				
			||||||
 | 
					            cameraBehaviour.Zoom -= Time.Elapsed.Nanoseconds * 0.00025f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.NumPad8)) cameraBehaviour.BehaviourController.GameObject.Transform.Position += Vector2D.Up.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.NumPad2)) cameraBehaviour.BehaviourController.GameObject.Transform.Position -= Vector2D.Up.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.NumPad6)) cameraBehaviour.BehaviourController.GameObject.Transform.Position += Vector2D.Right.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.NumPad4)) cameraBehaviour.BehaviourController.GameObject.Transform.Position -= Vector2D.Right.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.Q))
 | 
				
			||||||
 | 
					            cameraBehaviour.BehaviourController.GameObject.Transform.Rotation += Time.Elapsed.Nanoseconds * 0.0025f;
 | 
				
			||||||
 | 
					        if (buttonInputs.IsPressed(Keys.E))
 | 
				
			||||||
 | 
					            cameraBehaviour.BehaviourController.GameObject.Transform.Rotation -= Time.Elapsed.Nanoseconds * 0.0025f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SwitchToFullScreen(IButtonInputs<Keys> inputs, Keys keys)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (cameraBehaviour.Graphics.IsFullScreen)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cameraBehaviour.Graphics.PreferMultiSampling = false;
 | 
				
			||||||
 | 
					        cameraBehaviour.Graphics.PreferredBackBufferWidth = cameraBehaviour.Graphics.GraphicsDevice.Adapter.CurrentDisplayMode.Width;
 | 
				
			||||||
 | 
					        cameraBehaviour.Graphics.PreferredBackBufferHeight = cameraBehaviour.Graphics.GraphicsDevice.Adapter.CurrentDisplayMode.Height;
 | 
				
			||||||
 | 
					        cameraBehaviour.Graphics.IsFullScreen = true;
 | 
				
			||||||
 | 
					        cameraBehaviour.Graphics.ApplyChanges();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float previousScreenSize = Math.Sqrt(Math.Sqr(cameraBehaviour.Viewport.Width) + Math.Sqr(cameraBehaviour.Viewport.Height));
 | 
				
			||||||
 | 
					        float currentScreenSize = Math.Sqrt(Math.Sqr(cameraBehaviour.Graphics.GraphicsDevice.Viewport.Width) + Math.Sqr(cameraBehaviour.Graphics.GraphicsDevice.Viewport.Height));
 | 
				
			||||||
 | 
					        defaultZoomLevel /= previousScreenSize / currentScreenSize;
 | 
				
			||||||
 | 
					        cameraBehaviour.Zoom /= previousScreenSize / currentScreenSize;
 | 
				
			||||||
 | 
					        cameraBehaviour.Viewport = cameraBehaviour.Graphics.GraphicsDevice.Viewport;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void ResetCamera(IButtonInputs<Keys> inputs, Keys keys)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cameraBehaviour.Zoom = defaultZoomLevel;
 | 
				
			||||||
 | 
					        Transform.Position = Vector2D.Zero;
 | 
				
			||||||
 | 
					        Transform.Rotation = 0f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								Game/Behaviours/CircleBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								Game/Behaviours/CircleBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Apos.Shapes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Primitives;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class CircleBehaviour : Syntriax.Engine.Physics2D.Collider2DCircleBehaviour, IDisplayableShape
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Color Color { get; set; } = Color.White;
 | 
				
			||||||
 | 
					    public float Thickness { get; set; } = .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Draw(ShapeBatch shapeBatch)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!IsActive)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Recalculate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        shapeBatch.BorderCircle(CircleWorld.Center.ToDisplayVector2(), CircleWorld.Radius, Color);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public CircleBehaviour(Circle circle) : base(circle) { }
 | 
				
			||||||
 | 
					    public CircleBehaviour(Circle circle, float thickness) : base(circle) { Thickness = thickness; }
 | 
				
			||||||
 | 
					    public CircleBehaviour(Circle circle, Color color) : base(circle) { Color = color; }
 | 
				
			||||||
 | 
					    public CircleBehaviour(Circle circle, Color color, float thickness) : base(circle) { Thickness = thickness; Color = color; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										107
									
								
								Game/Behaviours/KeyboardInputsBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								Game/Behaviours/KeyboardInputsBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class KeyboardInputsBehaviour : BehaviourOverride, IButtonInputs<Keys>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>> OnPressed = new(256);
 | 
				
			||||||
 | 
					    private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>> OnReleased = new(256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int cachePressedCurrentlyCount = 0;
 | 
				
			||||||
 | 
					    private readonly Keys[] cachePressedCurrently = new Keys[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int cachePressedPreviouslyCount = 0;
 | 
				
			||||||
 | 
					    private readonly Keys[] cachePressedPreviously = new Keys[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void RegisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (OnPressed.TryGetValue(key, out var action))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            action += callback;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnPressed.Add(key, callback);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void UnregisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (OnPressed.TryGetValue(key, out var action))
 | 
				
			||||||
 | 
					            action -= callback;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void RegisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (OnReleased.TryGetValue(key, out var action))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            action += callback;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnReleased.Add(key, callback);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void UnregisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (OnReleased.TryGetValue(key, out var action))
 | 
				
			||||||
 | 
					            action -= callback;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KeyboardState keyboardState = Keyboard.GetState();
 | 
				
			||||||
 | 
					        keyboardState.GetPressedKeys(cachePressedCurrently);
 | 
				
			||||||
 | 
					        cachePressedCurrentlyCount = keyboardState.GetPressedKeyCount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < cachePressedCurrentlyCount; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Keys currentlyPressedKey = cachePressedCurrently[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!OnPressed.TryGetValue(currentlyPressedKey, out var action))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (WasPressed(currentlyPressedKey))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            action.Invoke(this, currentlyPressedKey);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < cachePressedPreviouslyCount; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Keys previouslyPressedKey = cachePressedPreviously[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!OnReleased.TryGetValue(previouslyPressedKey, out var action))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (IsPressed(previouslyPressedKey))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            action.Invoke(this, previouslyPressedKey);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount);
 | 
				
			||||||
 | 
					        cachePressedPreviouslyCount = cachePressedCurrentlyCount;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsPressed(Keys key)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < cachePressedCurrentlyCount; i++)
 | 
				
			||||||
 | 
					            if (cachePressedCurrently[i] == key)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool WasPressed(Keys key)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < cachePressedPreviouslyCount; i++)
 | 
				
			||||||
 | 
					            if (cachePressedPreviously[i] == key)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										106
									
								
								Game/Behaviours/MonoGameCamera2DBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								Game/Behaviours/MonoGameCamera2DBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : BehaviourOverride, ICamera2D
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public event OnMatrixTransformChangedDelegate? OnMatrixTransformChanged = null;
 | 
				
			||||||
 | 
					    public event OnViewportChangedDelegate? OnViewportChanged = null;
 | 
				
			||||||
 | 
					    public event OnZoomChangedDelegate? OnZoomChanged = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Matrix _matrixTransform = Matrix.Identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Viewport _viewport = default;
 | 
				
			||||||
 | 
					    private float _zoom = 1f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GraphicsDeviceManager Graphics { get; } = Graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Matrix MatrixTransform
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _matrixTransform;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_matrixTransform == value)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _matrixTransform = value;
 | 
				
			||||||
 | 
					            OnMatrixTransformChanged?.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector2D Position
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => Transform.Position;
 | 
				
			||||||
 | 
					        set => Transform.Position = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Viewport Viewport
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _viewport;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_viewport.Equals(value))
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _viewport = value;
 | 
				
			||||||
 | 
					            OnViewportChanged?.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public float Zoom
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _zoom;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            float newValue = Math.Max(0.1f, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (_zoom == newValue)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _zoom = newValue;
 | 
				
			||||||
 | 
					            OnZoomChanged?.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public float Rotation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => Transform.Rotation;
 | 
				
			||||||
 | 
					        set => Transform.Rotation = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public event IAssignableTransform.OnTransformAssignedDelegate? OnTransformAssigned { add => GameObject.OnTransformAssigned += value; remove => GameObject.OnTransformAssigned -= value; }
 | 
				
			||||||
 | 
					    ITransform IAssignableTransform.Transform => GameObject.Transform;
 | 
				
			||||||
 | 
					    bool IAssignableTransform.Assign(ITransform transform) => GameObject.Assign(transform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO This causes delay since OnPreDraw calls assuming this is called in in Update 
 | 
				
			||||||
 | 
					    public Vector2D ScreenToWorldPosition(Vector2D screenPosition)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2D worldPosition = Vector2.Transform(screenPosition.ToVector2(), Matrix.Invert(MatrixTransform)).ToVector2D();
 | 
				
			||||||
 | 
					        return worldPosition.Scale(EngineConverter.screenScale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public Vector2D WorldToScreenPosition(Vector2D worldPosition)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), MatrixTransform).ToVector2D();
 | 
				
			||||||
 | 
					        return screenPosition.Scale(EngineConverter.screenScale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					        => Viewport = Graphics.GraphicsDevice.Viewport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnPreDraw()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MatrixTransform =
 | 
				
			||||||
 | 
					            Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 0f)) *
 | 
				
			||||||
 | 
					            Matrix.CreateRotationZ(Rotation * Math.DegreeToRadian) *
 | 
				
			||||||
 | 
					            Matrix.CreateScale(Zoom) *
 | 
				
			||||||
 | 
					            Matrix.CreateTranslation(new Vector3(_viewport.Width * .5f, _viewport.Height * .5f, 0f));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public delegate void OnMatrixTransformChangedDelegate(MonoGameCamera2DBehaviour sender);
 | 
				
			||||||
 | 
					    public delegate void OnViewportChangedDelegate(MonoGameCamera2DBehaviour sender);
 | 
				
			||||||
 | 
					    public delegate void OnZoomChangedDelegate(MonoGameCamera2DBehaviour sender);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										53
									
								
								Game/Behaviours/MovementBallBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Game/Behaviours/MovementBallBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MovementBallBehaviour : BehaviourOverride
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
 | 
				
			||||||
 | 
					    public float Speed { get; set; } = 500f;
 | 
				
			||||||
 | 
					    public float SpeedUpMultiplier { get; set; } = .0125f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IRigidBody2D rigidBody = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? foundRigidBody))
 | 
				
			||||||
 | 
					            throw new Exception($"{nameof(IRigidBody2D)} is missing on {GameObject.Name}.");
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out ICollider2D? foundCollider))
 | 
				
			||||||
 | 
					            throw new Exception($"{nameof(ICollider2D)} is missing on {GameObject.Name}.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foundRigidBody.Velocity = StartDirection * Speed;
 | 
				
			||||||
 | 
					        foundCollider.OnCollisionDetected += OnCollisionDetected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rigidBody = foundRigidBody;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector2D speedUp = rigidBody.Velocity.Normalized * Time.DeltaTimeFrame;
 | 
				
			||||||
 | 
					        rigidBody.Velocity += speedUp * SpeedUpMultiplier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
 | 
				
			||||||
 | 
					            rigidBody.Velocity = information.Left.Transform.Position.FromTo(information.Right.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public MovementBallBehaviour() { }
 | 
				
			||||||
 | 
					    public MovementBallBehaviour(Vector2D startDirection, float speed)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        StartDirection = Vector2D.Normalize(startDirection);
 | 
				
			||||||
 | 
					        Speed = speed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										99
									
								
								Game/Behaviours/PaddleBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								Game/Behaviours/PaddleBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Input;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : NetworkBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private Keys Up { get; } = Up;
 | 
				
			||||||
 | 
					    private Keys Down { get; } = Down;
 | 
				
			||||||
 | 
					    public float High { get; } = High;
 | 
				
			||||||
 | 
					    public float Low { get; } = Low;
 | 
				
			||||||
 | 
					    public float Speed { get; set; } = Speed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private bool isUpPressed = false;
 | 
				
			||||||
 | 
					    private bool isDownPressed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IButtonInputs<Keys> inputs = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (isUpPressed && isDownPressed)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isUpPressed)
 | 
				
			||||||
 | 
					            Move(Vector2D.Up);
 | 
				
			||||||
 | 
					        else if (isDownPressed)
 | 
				
			||||||
 | 
					            Move(-Vector2D.Up);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void Move(Vector2D vectorToMove)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        GameObject.Transform.Position = GameObject.Transform.Position + vectorToMove * (float)Time.Elapsed.TotalSeconds * Speed;
 | 
				
			||||||
 | 
					        GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour<IButtonInputs<Keys>>(out var behaviourResult))
 | 
				
			||||||
 | 
					            inputs = behaviourResult ?? BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputs.RegisterOnPress(Up, OnUpPressed);
 | 
				
			||||||
 | 
					        inputs.RegisterOnRelease(Up, OnUpReleased);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputs.RegisterOnPress(Down, OnDownPressed);
 | 
				
			||||||
 | 
					        inputs.RegisterOnRelease(Down, OnDownReleased);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFinalize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        inputs.UnregisterOnPress(Up, OnUpPressed);
 | 
				
			||||||
 | 
					        inputs.UnregisterOnRelease(Up, OnUpReleased);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputs.UnregisterOnPress(Down, OnDownPressed);
 | 
				
			||||||
 | 
					        inputs.UnregisterOnRelease(Down, OnDownReleased);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
 | 
				
			||||||
 | 
					    private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
 | 
				
			||||||
 | 
					    private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
 | 
				
			||||||
 | 
					    private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed, PositionY = Transform.Position.Y }); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void ReceiveData<T>(T data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (data is not PaddleInputs paddleInputs)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Transform.Position = new(Transform.Position.X, paddleInputs.PositionY);
 | 
				
			||||||
 | 
					        isUpPressed = paddleInputs.IsUpPressed;
 | 
				
			||||||
 | 
					        isDownPressed = paddleInputs.IsDownPressed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [System.Serializable]
 | 
				
			||||||
 | 
					    public struct PaddleInputs : INetworkPacket
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public float PositionY { get; set; }
 | 
				
			||||||
 | 
					        public bool IsUpPressed { get; set; }
 | 
				
			||||||
 | 
					        public bool IsDownPressed { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Deserialize(NetDataReader reader)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            PositionY = reader.GetFloat();
 | 
				
			||||||
 | 
					            IsUpPressed = reader.GetBool();
 | 
				
			||||||
 | 
					            IsDownPressed = reader.GetBool();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Serialize(NetDataWriter writer)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            writer.Put(PositionY);
 | 
				
			||||||
 | 
					            writer.Put(IsUpPressed);
 | 
				
			||||||
 | 
					            writer.Put(IsDownPressed);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								Game/Behaviours/PongManagerBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Game/Behaviours/PongManagerBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PongManagerBehaviour : BehaviourOverride
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Action<PongManagerBehaviour>? OnReset { get; set; } = null;
 | 
				
			||||||
 | 
					    public Action<PongManagerBehaviour>? OnFinished { get; set; } = null;
 | 
				
			||||||
 | 
					    public Action<PongManagerBehaviour>? OnScored { get; set; } = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int ScoreLeft { get; private set; } = 0;
 | 
				
			||||||
 | 
					    public int ScoreRight { get; private set; } = 0;
 | 
				
			||||||
 | 
					    public int ScoreSum => ScoreLeft + ScoreRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int WinScore { get; } = 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public PongManagerBehaviour() => WinScore = 5;
 | 
				
			||||||
 | 
					    public PongManagerBehaviour(int winScore) => WinScore = winScore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KeyboardInputsBehaviour? buttonInputs = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out buttonInputs))
 | 
				
			||||||
 | 
					            buttonInputs = BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => Reset());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void ScoreToLeft()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ScoreLeft++;
 | 
				
			||||||
 | 
					        OnScored?.Invoke(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CheckFinish();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void ScoreToRight()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ScoreRight++;
 | 
				
			||||||
 | 
					        OnScored?.Invoke(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CheckFinish();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Reset()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ScoreLeft = ScoreRight = 0;
 | 
				
			||||||
 | 
					        OnReset?.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void CheckFinish()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int halfwayScore = (int)(WinScore * .5f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
 | 
				
			||||||
 | 
					            OnFinished?.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								Game/Behaviours/ShapeAABBBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Game/Behaviours/ShapeAABBBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Apos.Shapes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Input;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Primitives;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ShapeAABBBehaviour : BehaviourOverride, IDisplayableShape
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private IShapeCollider2D? shapeCollider = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Color Color { get; set; } = Color.White;
 | 
				
			||||||
 | 
					    public float Thickness { get; set; } = .5f;
 | 
				
			||||||
 | 
					    public bool display = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BehaviourController.TryGetBehaviour(out shapeCollider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (BehaviourController.TryGetBehaviour(out IButtonInputs<Microsoft.Xna.Framework.Input.Keys>? keys))
 | 
				
			||||||
 | 
					            keys.RegisterOnPress(Microsoft.Xna.Framework.Input.Keys.D, (_1, _2) => display = !display);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Draw(ShapeBatch shapeBatch)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!display)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (shapeCollider is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        AABB aabb = AABB.FromVectors(shapeCollider.ShapeWorld);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        shapeBatch.BorderCircle(aabb.Center.ToDisplayVector2(), 7.5f, Color.Beige);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        shapeBatch.DrawRectangle(aabb.Center.ApplyDisplayScale().Subtract(aabb.SizeHalf).ToVector2(), aabb.Size.ToVector2(), Color.Transparent, Color.Blue);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ShapeAABBBehaviour() { }
 | 
				
			||||||
 | 
					    public ShapeAABBBehaviour(float Thickness) { this.Thickness = Thickness; }
 | 
				
			||||||
 | 
					    public ShapeAABBBehaviour(Color color) { Color = color; }
 | 
				
			||||||
 | 
					    public ShapeAABBBehaviour(Color color, float Thickness) { this.Thickness = Thickness; Color = color; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								Game/Behaviours/ShapeBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Game/Behaviours/ShapeBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Apos.Shapes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Primitives;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ShapeBehaviour : Syntriax.Engine.Physics2D.Collider2DShapeBehaviour, IDisplayableShape
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Color Color { get; set; } = Color.White;
 | 
				
			||||||
 | 
					    public float Thickness { get; set; } = .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Draw(ShapeBatch shapeBatch)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!IsActive)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Recalculate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int count = ShapeWorld.Vertices.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < count - 1; i++)
 | 
				
			||||||
 | 
					            shapeBatch.DrawLine(ShapeWorld[i].ToDisplayVector2(), ShapeWorld[i + 1].ToDisplayVector2(), Thickness, Color, Color);
 | 
				
			||||||
 | 
					        shapeBatch.DrawLine(ShapeWorld[0].ToDisplayVector2(), ShapeWorld[^1].ToDisplayVector2(), Thickness, Color, Color);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ShapeBehaviour(Shape shape) : base(shape) { }
 | 
				
			||||||
 | 
					    public ShapeBehaviour(Shape shape, float thickness) : base(shape) { Thickness = thickness; }
 | 
				
			||||||
 | 
					    public ShapeBehaviour(Shape shape, Color color) : base(shape) { Color = color; }
 | 
				
			||||||
 | 
					    public ShapeBehaviour(Shape shape, Color color, float thickness) : base(shape) { Thickness = thickness; Color = color; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								Game/Behaviours/TextBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Game/Behaviours/TextBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TextBehaviour : BehaviourOverride, IDisplayableSprite
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public SpriteFont? Font { get; set; } = null;
 | 
				
			||||||
 | 
					    public int Size { get; set; } = 16;
 | 
				
			||||||
 | 
					    public string Text { get; set; } = string.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Draw(SpriteBatch spriteBatch)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!IsActive || Font is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        spriteBatch.DrawString(Font, Text, Transform.Position.ToDisplayVector2(), Color.White, Transform.Rotation, Vector2.One * .5f, Transform.Scale.Magnitude, SpriteEffects.None, 0f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TextBehaviour() { }
 | 
				
			||||||
 | 
					    public TextBehaviour(SpriteFont font) => Font = font;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								Game/Behaviours/TextScoreBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Game/Behaviours/TextScoreBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TextScoreBehaviour : TextBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public bool IsLeft { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private PongManagerBehaviour? pongManager = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!GameObject.GameManager.TryFindBehaviour(out pongManager))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pongManager.OnScored += UpdateScores;
 | 
				
			||||||
 | 
					        pongManager.OnReset += UpdateScores;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateScores(pongManager);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateScores(PongManagerBehaviour pongManager)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsLeft)
 | 
				
			||||||
 | 
					            Text = pongManager.ScoreLeft.ToString();
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            Text = pongManager.ScoreRight.ToString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TextScoreBehaviour(bool IsLeft) => this.IsLeft = IsLeft;
 | 
				
			||||||
 | 
					    public TextScoreBehaviour(bool IsLeft, SpriteFont font) : base(font) => this.IsLeft = IsLeft;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								Game/Behaviours/WallScoreBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Game/Behaviours/WallScoreBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong.Behaviours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class WallScoreBehaviour(Action OnCollision) : BehaviourOverride
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private Action OnCollision { get; } = OnCollision;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!BehaviourController.TryGetBehaviour(out ICollider2D? collider2D))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        collider2D.OnCollisionDetected += (_, _1) => OnCollision?.Invoke();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,3 +13,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#---------------------------------- Content ---------------------------------#
 | 
					#---------------------------------- Content ---------------------------------#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#begin UbuntuMono.spritefont
 | 
				
			||||||
 | 
					/importer:FontDescriptionImporter
 | 
				
			||||||
 | 
					/processor:FontDescriptionProcessor
 | 
				
			||||||
 | 
					/processorParam:PremultiplyAlpha=True
 | 
				
			||||||
 | 
					/processorParam:TextureFormat=Compressed
 | 
				
			||||||
 | 
					/build:UbuntuMono.spritefont
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								Game/EngineConverter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Game/EngineConverter.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					using System.Runtime.CompilerServices;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class EngineConverter
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public readonly static Vector2D screenScale = Vector2D.Down + Vector2D.Right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static EngineTime ToEngineTime(this GameTime gameTime) => new(gameTime.TotalGameTime, gameTime.ElapsedGameTime);
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector2D ToVector2D(this Vector2 vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector2D ToVector2D(this Point point) => new(point.X, point.Y);
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector2 ToVector2(this Vector2D vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector2 ToDisplayVector2(this Vector2D vector) => vector.Scale(screenScale).ToVector2();
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector2D ApplyDisplayScale(this Vector2D vector) => vector.Scale(screenScale);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								Game/Game.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Game/Game.csproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk">
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <OutputType>WinExe</OutputType>
 | 
				
			||||||
 | 
					    <TargetFramework>net8.0</TargetFramework>
 | 
				
			||||||
 | 
					    <RollForward>Major</RollForward>
 | 
				
			||||||
 | 
					    <PublishReadyToRun>false</PublishReadyToRun>
 | 
				
			||||||
 | 
					    <TieredCompilation>false</TieredCompilation>
 | 
				
			||||||
 | 
					    <Nullable>enable</Nullable>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <ApplicationManifest>app.manifest</ApplicationManifest>
 | 
				
			||||||
 | 
					    <ApplicationIcon>Icon.ico</ApplicationIcon>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Remove="Icon.ico" />
 | 
				
			||||||
 | 
					    <None Remove="Icon.bmp" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <EmbeddedResource Include="Icon.ico" />
 | 
				
			||||||
 | 
					    <EmbeddedResource Include="Icon.bmp" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Apos.Shapes" Version="0.2.3" />
 | 
				
			||||||
 | 
					    <PackageReference Include="LiteNetLib" Version="1.2.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
 | 
				
			||||||
 | 
					    <PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Engine\Engine.Core\Engine.Core.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Engine\Engine.Input\Engine.Input.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Engine\Engine.Physics2D\Engine.Physics2D.csproj" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <Target Name="RestoreDotnetTools" BeforeTargets="Restore">
 | 
				
			||||||
 | 
					    <Message Text="Restoring dotnet tools" Importance="High" />
 | 
				
			||||||
 | 
					    <Exec Command="dotnet tool restore" />
 | 
				
			||||||
 | 
					  </Target>
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										197
									
								
								Game/GamePong.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								Game/GamePong.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Apos.Shapes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Pong.Behaviours;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Abstract;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Physics2D.Primitives;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Pong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class GamePong : Game
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly GraphicsDeviceManager graphics = null!;
 | 
				
			||||||
 | 
					    private IPhysicsEngine2D physicsEngine = null!;
 | 
				
			||||||
 | 
					    private SpriteBatch spriteBatch = null!;
 | 
				
			||||||
 | 
					    private ShapeBatch shapeBatch = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private GameManager gameManager = null!;
 | 
				
			||||||
 | 
					    private BehaviourCollector<IDisplayableSprite> displayableCollector = null!;
 | 
				
			||||||
 | 
					    private BehaviourCollector<IDisplayableShape> displayableShapeCollector = null!;
 | 
				
			||||||
 | 
					    private MonoGameCamera2DBehaviour cameraBehaviour = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private PongManagerBehaviour pongManager = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private float physicsTimer = 0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GamePong()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        graphics = new GraphicsDeviceManager(this)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            PreferredBackBufferWidth = 1024,
 | 
				
			||||||
 | 
					            PreferredBackBufferHeight = 576,
 | 
				
			||||||
 | 
					            GraphicsProfile = GraphicsProfile.HiDef
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Content.RootDirectory = "Content";
 | 
				
			||||||
 | 
					        IsMouseVisible = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void Initialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // TODO: Add your initialization logic here
 | 
				
			||||||
 | 
					        gameManager = new();
 | 
				
			||||||
 | 
					        displayableCollector = new(gameManager);
 | 
				
			||||||
 | 
					        displayableShapeCollector = new(gameManager);
 | 
				
			||||||
 | 
					        physicsEngine = new PhysicsEngine2DCollector(gameManager) { IterationPerStep = 3 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameManager.Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        base.Initialize();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void LoadContent()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        spriteBatch = new SpriteBatch(GraphicsDevice);
 | 
				
			||||||
 | 
					        shapeBatch = new ShapeBatch(GraphicsDevice, Content);
 | 
				
			||||||
 | 
					        SpriteFont spriteFont = Content.Load<SpriteFont>("UbuntuMono");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        string[] commandLineArguments = Environment.GetCommandLineArgs();
 | 
				
			||||||
 | 
					        if (commandLineArguments.Length != 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (commandLineArguments[1].Equals("server", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkServer>().Start(8888, 2);
 | 
				
			||||||
 | 
					                Window.Title = "Pong - Server";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Window.Title = $"Pong - Client -> {commandLineArguments[1]}";
 | 
				
			||||||
 | 
					                gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect(commandLineArguments[1], 8888);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect("127.0.0.1", 8888);
 | 
				
			||||||
 | 
					            Window.Title = $"Pong - Client -> 127.0.0.1";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectNetworkManager = gameManager.InstantiateGameObject().SetGameObject("Network Manager"); ;
 | 
				
			||||||
 | 
					        gameObjectNetworkManager.BehaviourController.AddBehaviour<NetworkManager>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectCamera = gameManager.InstantiateGameObject().SetGameObject("Camera"); ;
 | 
				
			||||||
 | 
					        gameObjectCamera.BehaviourController.AddBehaviour<CameraController>();
 | 
				
			||||||
 | 
					        cameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>(graphics);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectPongManager = gameManager.InstantiateGameObject().SetGameObject("Pong Game Manager");
 | 
				
			||||||
 | 
					        pongManager = gameObjectPongManager.BehaviourController.AddBehaviour<PongManagerBehaviour>(5);
 | 
				
			||||||
 | 
					        pongManager.Id = "pongManager";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectBall = gameManager.InstantiateGameObject().SetGameObject("Ball");
 | 
				
			||||||
 | 
					        gameObjectBall.Transform.SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameObjectBall.BehaviourController.AddBehaviour<CircleBehaviour>(new Circle(Vector2D.Zero, 1f));
 | 
				
			||||||
 | 
					        gameObjectBall.BehaviourController.AddBehaviour<BallBehaviour>().Id = "ball";
 | 
				
			||||||
 | 
					        gameObjectBall.BehaviourController.AddBehaviour<RigidBody2D>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectLeftPaddle = gameManager.InstantiateGameObject().SetGameObject("Left Paddle");
 | 
				
			||||||
 | 
					        gameObjectLeftPaddle.Transform.SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameObjectLeftPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.W, Keys.S, 228f, -228f, 400f).Id = "leftPaddle";
 | 
				
			||||||
 | 
					        gameObjectLeftPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectLeftPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectRightPaddle = gameManager.InstantiateGameObject().SetGameObject("Right Paddle");
 | 
				
			||||||
 | 
					        gameObjectRightPaddle.Transform.SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f));
 | 
				
			||||||
 | 
					        gameObjectRightPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.Up, Keys.Down, 228f, -228f, 400f).Id = "rightPaddle";
 | 
				
			||||||
 | 
					        gameObjectRightPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectRightPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectWallTop = gameManager.InstantiateGameObject().SetGameObject("Wall Top");
 | 
				
			||||||
 | 
					        gameObjectWallTop.Transform.SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f));
 | 
				
			||||||
 | 
					        gameObjectWallTop.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectWallTop.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectWallBottom = gameManager.InstantiateGameObject().SetGameObject("Wall Bottom");
 | 
				
			||||||
 | 
					        gameObjectWallBottom.Transform.SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f));
 | 
				
			||||||
 | 
					        gameObjectWallBottom.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectWallBottom.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectWallRight = gameManager.InstantiateGameObject().SetGameObject("Wall Right");
 | 
				
			||||||
 | 
					        gameObjectWallRight.Transform.SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f));
 | 
				
			||||||
 | 
					        gameObjectWallRight.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToLeft);
 | 
				
			||||||
 | 
					        gameObjectWallRight.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectWallRight.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectWallLeft = gameManager.InstantiateGameObject().SetGameObject("Wall Left");
 | 
				
			||||||
 | 
					        gameObjectWallLeft.Transform.SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f));
 | 
				
			||||||
 | 
					        gameObjectWallLeft.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToRight);
 | 
				
			||||||
 | 
					        gameObjectWallLeft.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
 | 
				
			||||||
 | 
					        gameObjectWallLeft.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectLeftScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Left");
 | 
				
			||||||
 | 
					        gameObjectLeftScoreText.Transform.SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f);
 | 
				
			||||||
 | 
					        gameObjectLeftScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(true, spriteFont);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IGameObject gameObjectRightScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Right");
 | 
				
			||||||
 | 
					        gameObjectRightScoreText.Transform.SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f);
 | 
				
			||||||
 | 
					        gameObjectRightScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(false, spriteFont);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void Update(GameTime gameTime)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
 | 
				
			||||||
 | 
					            Exit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameManager.Update(gameTime.ToEngineTime());
 | 
				
			||||||
 | 
					        while (physicsTimer + 0.01f < gameTime.TotalGameTime.TotalMilliseconds * .001f)//seconds)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            physicsTimer += 0.01f;
 | 
				
			||||||
 | 
					            physicsEngine.Step(.01f);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        base.Update(gameTime);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void Draw(GameTime gameTime)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        GraphicsDevice.Clear(new Color() { R = 32, G = 32, B = 32 });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: Add your drawing code here
 | 
				
			||||||
 | 
					        gameManager.PreDraw();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cameraBehaviour.MatrixTransform);
 | 
				
			||||||
 | 
					        foreach (var displayable in displayableCollector)
 | 
				
			||||||
 | 
					            displayable.Draw(spriteBatch);
 | 
				
			||||||
 | 
					        spriteBatch.End();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        shapeBatch.Begin(cameraBehaviour.MatrixTransform);
 | 
				
			||||||
 | 
					        foreach (var displayableShape in displayableShapeCollector)
 | 
				
			||||||
 | 
					            displayableShape.Draw(shapeBatch);
 | 
				
			||||||
 | 
					        shapeBatch.End();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        base.Draw(gameTime);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								Game/Icon.bmp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Game/Icon.bmp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 256 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Game/Icon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Game/Icon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 144 KiB  | 
							
								
								
									
										11
									
								
								Game/Network/Abstract/INetworkBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Game/Network/Abstract/INetworkBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					using Syntriax.Engine.Core.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkBehaviour : IBehaviour, INetworkEntity
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool IsServer { get; }
 | 
				
			||||||
 | 
					    bool IsClient { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    INetworkCommunicator NetworkCommunicator { get; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								Game/Network/Abstract/INetworkCommunicator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Game/Network/Abstract/INetworkCommunicator.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					using LiteNetLib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkCommunicator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    event OnPacketReceivedDelegate? OnPacketReceived;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EventBasedNetListener Listener { get; }
 | 
				
			||||||
 | 
					    NetManager Manager { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void PollEvents();
 | 
				
			||||||
 | 
					    void Stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Send<T>(NetworkPacket<T> Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delegate void OnPacketReceivedDelegate(INetworkCommunicator sender, object packet);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								Game/Network/Abstract/INetworkCommunicatorClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Game/Network/Abstract/INetworkCommunicatorClient.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkCommunicatorClient : INetworkCommunicator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void Connect(string address, int port, string? password = null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								Game/Network/Abstract/INetworkCommunicatorServer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Game/Network/Abstract/INetworkCommunicatorServer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkCommunicatorServer : INetworkCommunicator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    string Password { get; }
 | 
				
			||||||
 | 
					    int MaxConnectionCount { get; }
 | 
				
			||||||
 | 
					    int Port { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Start(int port, int maxConnectionCount, string? password = null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								Game/Network/Abstract/INetworkEntity.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Game/Network/Abstract/INetworkEntity.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkEntity
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    event OnNetworkIdChangedDelegate? OnNetworkIdChanged;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint NetworkId { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void ReceiveData<T>(T data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delegate void OnNetworkIdChangedDelegate(INetworkEntity sender, uint previousId);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								Game/Network/Abstract/INetworkManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Game/Network/Abstract/INetworkManager.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkManager
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // Action<IGameObject>? OnNetworkGameObjectInstantiated { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    INetworkCommunicator NetworkCommunicator { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Task<T> Instantiate<T>(params object?[]? args) where T : class, IGameObject;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								Game/Network/Abstract/INetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Game/Network/Abstract/INetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface INetworkPacket : INetSerializable;
 | 
				
			||||||
							
								
								
									
										7
									
								
								Game/Network/Abstract/NetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Game/Network/Abstract/NetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					namespace Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class NetworkPacket<T>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public uint NetworkId { get; set; } = 0;
 | 
				
			||||||
 | 
					    public T Data { get; set; } = default!;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										140
									
								
								Game/Network/NetworkBase.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Game/Network/NetworkBase.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using LiteNetLib;
 | 
				
			||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected readonly NetPacketProcessor netPacketProcessor = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected readonly Dictionary<uint, INetworkEntity> networkEntities = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected BehaviourCollector<INetworkEntity> networkEntityCollector = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public EventBasedNetListener Listener { get; private set; } = null!;
 | 
				
			||||||
 | 
					    public NetManager Manager { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public NetworkBase()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Priority = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Listener = new EventBasedNetListener();
 | 
				
			||||||
 | 
					        Manager = new NetManager(Listener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Listener.NetworkReceiveEvent += NetworkReceiveEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType<Pong.Behaviours.PaddleBehaviour.PaddleInputs>();
 | 
				
			||||||
 | 
					        RegisterPackets();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void RegisterPackets()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var packetTypes = Assembly.GetExecutingAssembly().GetTypes()
 | 
				
			||||||
 | 
					            .Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface)
 | 
				
			||||||
 | 
					            .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo[] subscribeMethods = netPacketProcessor.GetType()
 | 
				
			||||||
 | 
					            .GetMethods()
 | 
				
			||||||
 | 
					            .Where(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable))
 | 
				
			||||||
 | 
					            .ToArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo subscribeMethod = subscribeMethods
 | 
				
			||||||
 | 
					            .FirstOrDefault(m =>
 | 
				
			||||||
 | 
					                m.GetParameters().Length == 1 &&
 | 
				
			||||||
 | 
					                m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)
 | 
				
			||||||
 | 
					            ) ?? throw new Exception();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo[] methodInfos = typeof(NetworkBase)
 | 
				
			||||||
 | 
					            .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo method = methodInfos
 | 
				
			||||||
 | 
					            .FirstOrDefault(
 | 
				
			||||||
 | 
					                m => m.Name == nameof(OnPacketArrived) &&
 | 
				
			||||||
 | 
					                m.IsGenericMethodDefinition
 | 
				
			||||||
 | 
					            ) ?? throw new Exception();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (var packetType in packetTypes)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var networkPacketType = typeof(NetworkPacket<>).MakeGenericType(packetType);
 | 
				
			||||||
 | 
					            MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(networkPacketType, typeof(NetPeer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Action<object, NetPeer> handler = (packet, peer) =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                MethodInfo handlerMethod = method.MakeGenericMethod(packetType);
 | 
				
			||||||
 | 
					                handlerMethod.Invoke(this, [packet, peer]);
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            genericSubscribe.Invoke(netPacketProcessor, [handler]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnPacketArrived<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetworkPacket
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (networkEntities.TryGetValue(packet.NetworkId, out INetworkEntity? entity))
 | 
				
			||||||
 | 
					            entity.ReceiveData(packet.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnPacketReceived?.Invoke(this, packet);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnInitialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        base.OnInitialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        networkEntityCollector = new(GameObject.GameManager);
 | 
				
			||||||
 | 
					        networkEntityCollector.OnCollected += OnNetworkEntityCollected;
 | 
				
			||||||
 | 
					        networkEntityCollector.OnRemoved += OnNetworkEntityRemoved;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnFinalize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        networkEntityCollector.OnCollected -= OnNetworkEntityCollected;
 | 
				
			||||||
 | 
					        networkEntityCollector.OnRemoved -= OnNetworkEntityRemoved;
 | 
				
			||||||
 | 
					        Stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnNetworkEntityCollected(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourCollected)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (behaviourCollected.NetworkId != 0)
 | 
				
			||||||
 | 
					            networkEntities.Add(behaviourCollected.NetworkId, behaviourCollected);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        behaviourCollected.OnNetworkIdChanged += OnNetworkIdChanged;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnNetworkIdChanged(INetworkEntity sender, uint previousId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (networkEntities.TryGetValue(previousId, out INetworkEntity? networkEntity) && sender == networkEntity)
 | 
				
			||||||
 | 
					            networkEntities.Remove(previousId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        networkEntities.Add(sender.NetworkId, sender);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnNetworkEntityRemoved(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourRemoved)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        networkEntities.Remove(behaviourRemoved.NetworkId);
 | 
				
			||||||
 | 
					        behaviourRemoved.OnNetworkIdChanged -= OnNetworkIdChanged;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            netPacketProcessor.ReadAllPackets(reader, peer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch { }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void PollEvents() => Manager.PollEvents();
 | 
				
			||||||
 | 
					    public void Stop() => Manager.Stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnUpdate() => PollEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public abstract void Send<T>(NetworkPacket<T> packet);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								Game/Network/NetworkBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								Game/Network/NetworkBehaviour.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public abstract class NetworkBehaviour : BehaviourOverride, INetworkBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public event INetworkEntity.OnNetworkIdChangedDelegate? OnNetworkIdChanged = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private uint _networkId = 0;
 | 
				
			||||||
 | 
					    public uint NetworkId
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _networkId;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _networkId)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uint previousNetworkId = _networkId;
 | 
				
			||||||
 | 
					            _networkId = value;
 | 
				
			||||||
 | 
					            OnNetworkIdChanged?.Invoke(this, previousNetworkId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsServer { get; private set; } = false;
 | 
				
			||||||
 | 
					    public bool IsClient { get; private set; } = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public INetworkCommunicator NetworkCommunicator { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnInitialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        NetworkCommunicator = BehaviourController.GetBehaviourInParent<INetworkCommunicator>()
 | 
				
			||||||
 | 
					                              ?? GameObject.GameManager.FindBehaviour<INetworkCommunicator>()
 | 
				
			||||||
 | 
					                              ?? throw new Exception($"Could not find an {nameof(INetworkCommunicator)}.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (NetworkCommunicator is INetworkCommunicatorClient client)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IsClient = true;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IsServer = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void SendData<T>(T data)
 | 
				
			||||||
 | 
					        => NetworkCommunicator.Send(new NetworkPacket<T>() { NetworkId = _networkId, Data = data });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public abstract void ReceiveData<T>(T data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								Game/Network/NetworkClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Game/Network/NetworkClient.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class NetworkClient : NetworkBase, INetworkCommunicatorClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly NetDataWriter netDataWriter = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Connect(string address, int port, string? password = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Manager.Start();
 | 
				
			||||||
 | 
					        Manager.Connect(address, port, password ?? string.Empty);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void Send<T>(NetworkPacket<T> packet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        netDataWriter.Reset();
 | 
				
			||||||
 | 
					        netPacketProcessor.Write(netDataWriter, packet);
 | 
				
			||||||
 | 
					        Manager.FirstPeer.Send(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								Game/Network/NetworkExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Game/Network/NetworkExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					using LiteNetLib;
 | 
				
			||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class NetworkExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static Vector2D GetVector2D(this NetPacketReader reader)
 | 
				
			||||||
 | 
					        => new(reader.GetFloat(), reader.GetFloat());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void GetVector2D(this NetPacketReader reader, out Vector2D vector2D)
 | 
				
			||||||
 | 
					        => vector2D = new(reader.GetFloat(), reader.GetFloat());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void Put(this NetDataWriter writer, Vector2D vector)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        writer.Put(vector.X);
 | 
				
			||||||
 | 
					        writer.Put(vector.Y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								Game/Network/NetworkManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Game/Network/NetworkManager.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					using Syntriax.Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class NetworkManager : NetworkBehaviour, INetworkManager
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private BehaviourCollector<INetworkEntity> entities = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static uint networkIdIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnInitialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        base.OnInitialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        NetworkId = networkIdIndex++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        entities = new(GameObject.GameManager);
 | 
				
			||||||
 | 
					        foreach (var entity in entities)
 | 
				
			||||||
 | 
					            entity.NetworkId = networkIdIndex++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        entities.OnCollected += OnCollected;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnCollected(BehaviourCollector<INetworkEntity> collector, INetworkEntity entity)
 | 
				
			||||||
 | 
					        => entity.NetworkId = networkIdIndex++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void ReceiveData<T>(T data) { }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										67
									
								
								Game/Network/NetworkServer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								Game/Network/NetworkServer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Syntriax.Engine.Network.Abstract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Syntriax.Engine.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class NetworkServer : NetworkBase, INetworkCommunicatorServer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public string Password { get; private set; } = string.Empty;
 | 
				
			||||||
 | 
					    public int MaxConnectionCount { get; private set; } = 2;
 | 
				
			||||||
 | 
					    public int Port { get; private set; } = 8888;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly NetDataWriter netDataWriter = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public NetworkServer() : this(8888, 2) { }
 | 
				
			||||||
 | 
					    public NetworkServer(int port, int maxConnectionCount) : base()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MaxConnectionCount = maxConnectionCount;
 | 
				
			||||||
 | 
					        Port = port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Listener.ConnectionRequestEvent += request =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Manager.ConnectedPeersCount < maxConnectionCount)
 | 
				
			||||||
 | 
					                request.AcceptIfKey(Password);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                request.Reject();
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnPacketReceived += ServerOnPacketReceived;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Start(int port, int maxConnectionCount, string? password = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Password = password ?? string.Empty;
 | 
				
			||||||
 | 
					        MaxConnectionCount = maxConnectionCount;
 | 
				
			||||||
 | 
					        Port = port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Manager.Start(port);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void Send<T>(NetworkPacket<T> packet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        netDataWriter.Reset();
 | 
				
			||||||
 | 
					        netPacketProcessor.Write(netDataWriter, packet);
 | 
				
			||||||
 | 
					        Manager.SendToAll(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void ServerOnPacketReceived(INetworkCommunicator sender, object packet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MethodInfo[] methodInfos = GetType()
 | 
				
			||||||
 | 
					            .GetMethods(BindingFlags.Public | BindingFlags.Instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo method = methodInfos
 | 
				
			||||||
 | 
					            .FirstOrDefault(
 | 
				
			||||||
 | 
					                m => m.Name == nameof(Send) && m.IsGenericMethod
 | 
				
			||||||
 | 
					            ) ?? throw new Exception();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Type typeArguments = packet.GetType().GetGenericArguments()[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodInfo methodInfo = method.MakeGenericMethod(typeArguments);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        methodInfo.Invoke(this, [packet]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								Game/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Game/Program.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					using var game = new Pong.GamePong();
 | 
				
			||||||
 | 
					game.Run();
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
 | 
					<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
 | 
				
			||||||
  <assemblyIdentity version="1.0.0.0" name="Desktop"/>
 | 
					  <assemblyIdentity version="1.0.0.0" name="Game"/>
 | 
				
			||||||
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
 | 
					  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
 | 
				
			||||||
    <security>
 | 
					    <security>
 | 
				
			||||||
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
 | 
					      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
public class ClientConfiguration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public bool Host = false;
 | 
					 | 
				
			||||||
    public int HostPort = 8888;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public string ServerAddress = "localhost";
 | 
					 | 
				
			||||||
    public int ServerPort = 8888;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int windowWidth = 1024;
 | 
					 | 
				
			||||||
    public int windowHeight = 576;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,90 +0,0 @@
 | 
				
			|||||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
					 | 
				
			||||||
  <PropertyGroup>
 | 
					 | 
				
			||||||
    <OutputType>WinExe</OutputType>
 | 
					 | 
				
			||||||
    <TargetFramework>net9.0</TargetFramework>
 | 
					 | 
				
			||||||
    <RollForward>Major</RollForward>
 | 
					 | 
				
			||||||
    <PublishReadyToRun>false</PublishReadyToRun>
 | 
					 | 
				
			||||||
    <TieredCompilation>false</TieredCompilation>
 | 
					 | 
				
			||||||
    <Nullable>enable</Nullable>
 | 
					 | 
				
			||||||
    <RootNamespace>Pong.Platforms.Desktop</RootNamespace>
 | 
					 | 
				
			||||||
    <AssemblyName>Pong</AssemblyName>
 | 
					 | 
				
			||||||
  </PropertyGroup>
 | 
					 | 
				
			||||||
  <PropertyGroup>
 | 
					 | 
				
			||||||
    <ApplicationManifest>app.manifest</ApplicationManifest>
 | 
					 | 
				
			||||||
    <ApplicationIcon>Icon.ico</ApplicationIcon>
 | 
					 | 
				
			||||||
  </PropertyGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <None Remove="Icon.ico" />
 | 
					 | 
				
			||||||
    <None Remove="Icon.bmp" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <EmbeddedResource Include="Icon.ico">
 | 
					 | 
				
			||||||
      <LogicalName>Icon.ico</LogicalName>
 | 
					 | 
				
			||||||
    </EmbeddedResource>
 | 
					 | 
				
			||||||
    <EmbeddedResource Include="Icon.bmp">
 | 
					 | 
				
			||||||
      <LogicalName>Icon.bmp</LogicalName>
 | 
					 | 
				
			||||||
    </EmbeddedResource>
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105" />
 | 
					 | 
				
			||||||
    <PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.2.1105" />
 | 
					 | 
				
			||||||
    <PackageReference Include="nulastudio.NetBeauty" Version="2.1.5" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <ProjectReference Include="../../Shared/Shared.csproj" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <MonoGameContentReference Include="../../Shared/Content/Content.mgcb">
 | 
					 | 
				
			||||||
      <Link>Content/Content.mgcb</Link>
 | 
					 | 
				
			||||||
    </MonoGameContentReference>
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <ProjectReference Include="../../Shared/Shared.csproj" />
 | 
					 | 
				
			||||||
    <ProjectReference Include="..\..\Engine\Engine.Integration\Engine.Integration.Yaml\Engine.Integration.Yaml.csproj" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <Target Name="RestoreDotnetTools" BeforeTargets="Restore">
 | 
					 | 
				
			||||||
    <Message Text="Restoring dotnet tools" Importance="High" />
 | 
					 | 
				
			||||||
    <Exec Command="dotnet tool restore" />
 | 
					 | 
				
			||||||
  </Target>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <PropertyGroup>
 | 
					 | 
				
			||||||
    <BeautySharedRuntimeMode>False</BeautySharedRuntimeMode>
 | 
					 | 
				
			||||||
    <!-- beauty into sub-directory, default is libs, quote with "" if contains space  -->
 | 
					 | 
				
			||||||
    <BeautyLibsDir Condition="$(BeautySharedRuntimeMode) == 'True'">../Libraries</BeautyLibsDir>
 | 
					 | 
				
			||||||
    <BeautyLibsDir Condition="$(BeautySharedRuntimeMode) != 'True'">./Libraries</BeautyLibsDir>
 | 
					 | 
				
			||||||
    <!-- dlls that you don't want to be moved or can not be moved -->
 | 
					 | 
				
			||||||
    <!-- <BeautyExcludes>dll1.dll;lib*;...</BeautyExcludes> -->
 | 
					 | 
				
			||||||
    <BeautyExcludes>SDL2.dll</BeautyExcludes>
 | 
					 | 
				
			||||||
    <!-- dlls that end users never needed, so hide them -->
 | 
					 | 
				
			||||||
    <BeautyHiddens>hostfxr;hostpolicy;*.deps.json;*.runtimeconfig*.json</BeautyHiddens>
 | 
					 | 
				
			||||||
    <!-- set to True if you want to disable -->
 | 
					 | 
				
			||||||
    <DisableBeauty>False</DisableBeauty>
 | 
					 | 
				
			||||||
    <!-- set to False if you want to beauty on build -->
 | 
					 | 
				
			||||||
    <BeautyOnPublishOnly>False</BeautyOnPublishOnly>
 | 
					 | 
				
			||||||
    <!-- DO NOT TOUCH THIS OPTION -->
 | 
					 | 
				
			||||||
    <BeautyNoRuntimeInfo>False</BeautyNoRuntimeInfo>
 | 
					 | 
				
			||||||
    <!-- valid values: auto|with|without -->
 | 
					 | 
				
			||||||
    <BeautyNBLoaderVerPolicy>auto</BeautyNBLoaderVerPolicy>
 | 
					 | 
				
			||||||
    <!-- set to True if you want to allow 3rd debuggers(like dnSpy) debugs the app -->
 | 
					 | 
				
			||||||
    <BeautyEnableDebugging>False</BeautyEnableDebugging>
 | 
					 | 
				
			||||||
    <!-- the patch can reduce the file count -->
 | 
					 | 
				
			||||||
    <!-- set to False if you want to disable -->
 | 
					 | 
				
			||||||
    <!-- SCD Mode Feature Only -->
 | 
					 | 
				
			||||||
    <BeautyUsePatch>True</BeautyUsePatch>
 | 
					 | 
				
			||||||
    <!-- App Entry Dll = BeautyDir + BeautyAppHostDir + BeautyAppHostEntry -->
 | 
					 | 
				
			||||||
    <!-- see https://github.com/nulastudio/NetBeauty2#customize-apphost for more details -->
 | 
					 | 
				
			||||||
    <!-- relative path based on AppHostDir -->
 | 
					 | 
				
			||||||
    <!-- .NET Core Non Single-File Only -->
 | 
					 | 
				
			||||||
    <!-- <BeautyAppHostEntry>bin/MyApp.dll</BeautyAppHostEntry> -->
 | 
					 | 
				
			||||||
    <!-- relative path based on BeautyDir -->
 | 
					 | 
				
			||||||
    <!-- .NET Core Non Single-File Only -->
 | 
					 | 
				
			||||||
    <!-- <BeautyAppHostDir>..</BeautyAppHostDir> -->
 | 
					 | 
				
			||||||
    <!-- <BeautyAfterTasks></BeautyAfterTasks> -->
 | 
					 | 
				
			||||||
    <!-- valid values: Error|Detail|Info -->
 | 
					 | 
				
			||||||
    <BeautyLogLevel>Info</BeautyLogLevel>
 | 
					 | 
				
			||||||
    <!-- set to a repo mirror if you have troble in connecting github -->
 | 
					 | 
				
			||||||
    <!-- <BeautyGitCDN>https://gitee.com/liesauer/HostFXRPatcher</BeautyGitCDN> -->
 | 
					 | 
				
			||||||
    <!-- <BeautyGitTree>master</BeautyGitTree> -->
 | 
					 | 
				
			||||||
  </PropertyGroup>
 | 
					 | 
				
			||||||
</Project>
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 192 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 7.2 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 7.2 KiB  | 
@@ -1,74 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.IO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Graphics;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Debug;
 | 
					 | 
				
			||||||
using Engine.Core.Serialization;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Serializers.Yaml;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Universe universe = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ISerializer serializer = new YamlSerializer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ILogger logger = new FileLogger($"Logs/{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss-ffffff}.log");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if DEBUG
 | 
					 | 
				
			||||||
logger = new LoggerWrapper(logger, new ConsoleLogger());
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
universe.InstantiateUniverseObject().SetUniverseObject("Logger").BehaviourController.AddBehaviour<LoggerContainer>().Logger = ILogger.Shared = logger;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
string settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "settings.yaml");
 | 
					 | 
				
			||||||
ClientConfiguration clientConfiguration = GetOrCreateConfiguration(serializer, logger, settingsPath);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (clientConfiguration.Host)
 | 
					 | 
				
			||||||
    Pong.PongUniverse.ApplyPongServer(universe, clientConfiguration.HostPort);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Pong.PongUniverse.ApplyPongClient(universe, clientConfiguration.ServerAddress, clientConfiguration.ServerPort);
 | 
					 | 
				
			||||||
Pong.PongUniverse.ApplyPongUniverse(universe);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
universe.InstantiateUniverseObject().SetUniverseObject("Desktop HO")
 | 
					 | 
				
			||||||
    .BehaviourController.AddBehaviour<KeyboardInputs>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using MonoGameWindow monoGameWindow = new(universe);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
monoGameWindow.Graphics.PreferredBackBufferWidth = clientConfiguration.windowWidth;
 | 
					 | 
				
			||||||
monoGameWindow.Graphics.PreferredBackBufferHeight = clientConfiguration.windowHeight;
 | 
					 | 
				
			||||||
monoGameWindow.Graphics.GraphicsProfile = GraphicsProfile.HiDef;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
universe.FindBehaviour<Engine.Systems.Network.INetworkCommunicatorClient>()?
 | 
					 | 
				
			||||||
    .OnConnectionEstablished.AddOneTimeListener(
 | 
					 | 
				
			||||||
        (sender, connection) => monoGameWindow.Window.Title = $"Client {connection.Id}"
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
monoGameWindow.Run();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static ClientConfiguration GetOrCreateConfiguration(ISerializer serializer, ILogger logger, string settingsPath)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    ClientConfiguration clientConfiguration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        clientConfiguration = serializer.Deserialize<ClientConfiguration>(File.ReadAllText(settingsPath));
 | 
					 | 
				
			||||||
        logger.Log(clientConfiguration, $"Configuration is successfully read");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    catch (FileNotFoundException)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        clientConfiguration = new();
 | 
					 | 
				
			||||||
        logger.Log(clientConfiguration, $"Configuration does not exist");
 | 
					 | 
				
			||||||
        File.WriteAllText(settingsPath, serializer.Serialize(clientConfiguration));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    catch (Exception exception)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        clientConfiguration = new();
 | 
					 | 
				
			||||||
        logger.LogError(clientConfiguration, $"Error loading configuration");
 | 
					 | 
				
			||||||
        logger.LogException(clientConfiguration, exception);
 | 
					 | 
				
			||||||
        File.WriteAllText(settingsPath, serializer.Serialize(clientConfiguration));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    logger.Log(clientConfiguration, $"Creating new configuration file at {settingsPath}");
 | 
					 | 
				
			||||||
    return clientConfiguration;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,131 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
					 | 
				
			||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
   width="100mm"
 | 
					 | 
				
			||||||
   height="100mm"
 | 
					 | 
				
			||||||
   viewBox="0 0 100 100"
 | 
					 | 
				
			||||||
   version="1.1"
 | 
					 | 
				
			||||||
   id="svg5"
 | 
					 | 
				
			||||||
   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
 | 
					 | 
				
			||||||
   sodipodi:docname="icon.svg"
 | 
					 | 
				
			||||||
   inkscape:export-filename="Icon.png"
 | 
					 | 
				
			||||||
   inkscape:export-xdpi="65.024002"
 | 
					 | 
				
			||||||
   inkscape:export-ydpi="65.024002"
 | 
					 | 
				
			||||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
					 | 
				
			||||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
					 | 
				
			||||||
   xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
   xmlns:svg="http://www.w3.org/2000/svg">
 | 
					 | 
				
			||||||
  <sodipodi:namedview
 | 
					 | 
				
			||||||
     id="namedview7"
 | 
					 | 
				
			||||||
     pagecolor="#505050"
 | 
					 | 
				
			||||||
     bordercolor="#eeeeee"
 | 
					 | 
				
			||||||
     borderopacity="1"
 | 
					 | 
				
			||||||
     inkscape:showpageshadow="0"
 | 
					 | 
				
			||||||
     inkscape:pageopacity="0"
 | 
					 | 
				
			||||||
     inkscape:pagecheckerboard="0"
 | 
					 | 
				
			||||||
     inkscape:deskcolor="#505050"
 | 
					 | 
				
			||||||
     inkscape:document-units="mm"
 | 
					 | 
				
			||||||
     showgrid="false"
 | 
					 | 
				
			||||||
     inkscape:zoom="0.76791526"
 | 
					 | 
				
			||||||
     inkscape:cx="-14.975611"
 | 
					 | 
				
			||||||
     inkscape:cy="272.16545"
 | 
					 | 
				
			||||||
     inkscape:window-width="1920"
 | 
					 | 
				
			||||||
     inkscape:window-height="1008"
 | 
					 | 
				
			||||||
     inkscape:window-x="0"
 | 
					 | 
				
			||||||
     inkscape:window-y="36"
 | 
					 | 
				
			||||||
     inkscape:window-maximized="1"
 | 
					 | 
				
			||||||
     inkscape:current-layer="layer1" />
 | 
					 | 
				
			||||||
  <defs
 | 
					 | 
				
			||||||
     id="defs2">
 | 
					 | 
				
			||||||
    <inkscape:path-effect
 | 
					 | 
				
			||||||
       effect="taper_stroke"
 | 
					 | 
				
			||||||
       id="path-effect1965"
 | 
					 | 
				
			||||||
       is_visible="true"
 | 
					 | 
				
			||||||
       lpeversion="1"
 | 
					 | 
				
			||||||
       stroke_width="14.57"
 | 
					 | 
				
			||||||
       attach_start="0.99999"
 | 
					 | 
				
			||||||
       end_offset="1e-07"
 | 
					 | 
				
			||||||
       start_smoothing="0"
 | 
					 | 
				
			||||||
       end_smoothing="0"
 | 
					 | 
				
			||||||
       jointype="extrapolated"
 | 
					 | 
				
			||||||
       start_shape="center"
 | 
					 | 
				
			||||||
       end_shape="center"
 | 
					 | 
				
			||||||
       miter_limit="1000.5" />
 | 
					 | 
				
			||||||
    <inkscape:path-effect
 | 
					 | 
				
			||||||
       effect="join_type"
 | 
					 | 
				
			||||||
       id="path-effect1959"
 | 
					 | 
				
			||||||
       is_visible="true"
 | 
					 | 
				
			||||||
       lpeversion="1"
 | 
					 | 
				
			||||||
       linecap_type="square"
 | 
					 | 
				
			||||||
       line_width="0.26458299"
 | 
					 | 
				
			||||||
       linejoin_type="extrp_arc"
 | 
					 | 
				
			||||||
       miter_limit="100"
 | 
					 | 
				
			||||||
       attempt_force_join="true" />
 | 
					 | 
				
			||||||
    <inkscape:path-effect
 | 
					 | 
				
			||||||
       effect="powerstroke"
 | 
					 | 
				
			||||||
       id="path-effect1957"
 | 
					 | 
				
			||||||
       is_visible="true"
 | 
					 | 
				
			||||||
       lpeversion="1"
 | 
					 | 
				
			||||||
       offset_points="0.2,0.1322915 | 1,0.1322915 | 1.8,0.1322915"
 | 
					 | 
				
			||||||
       not_jump="false"
 | 
					 | 
				
			||||||
       sort_points="true"
 | 
					 | 
				
			||||||
       interpolator_type="Linear"
 | 
					 | 
				
			||||||
       interpolator_beta="1"
 | 
					 | 
				
			||||||
       start_linecap_type="zerowidth"
 | 
					 | 
				
			||||||
       linejoin_type="miter"
 | 
					 | 
				
			||||||
       miter_limit="11100"
 | 
					 | 
				
			||||||
       scale_width="20"
 | 
					 | 
				
			||||||
       end_linecap_type="butt" />
 | 
					 | 
				
			||||||
    <inkscape:path-effect
 | 
					 | 
				
			||||||
       effect="fill_between_many"
 | 
					 | 
				
			||||||
       method="bsplinespiro"
 | 
					 | 
				
			||||||
       linkedpaths="#path1175,0,1"
 | 
					 | 
				
			||||||
       id="path-effect1961"
 | 
					 | 
				
			||||||
       is_visible="true"
 | 
					 | 
				
			||||||
       lpeversion="0"
 | 
					 | 
				
			||||||
       join="true"
 | 
					 | 
				
			||||||
       close="true"
 | 
					 | 
				
			||||||
       autoreverse="true" />
 | 
					 | 
				
			||||||
    <inkscape:path-effect
 | 
					 | 
				
			||||||
       effect="fill_between_many"
 | 
					 | 
				
			||||||
       method="bsplinespiro"
 | 
					 | 
				
			||||||
       linkedpaths="#path1175,0,1"
 | 
					 | 
				
			||||||
       id="path-effect1967"
 | 
					 | 
				
			||||||
       is_visible="true"
 | 
					 | 
				
			||||||
       lpeversion="0"
 | 
					 | 
				
			||||||
       join="true"
 | 
					 | 
				
			||||||
       close="true"
 | 
					 | 
				
			||||||
       autoreverse="true" />
 | 
					 | 
				
			||||||
  </defs>
 | 
					 | 
				
			||||||
  <g
 | 
					 | 
				
			||||||
     inkscape:label="Layer 1"
 | 
					 | 
				
			||||||
     inkscape:groupmode="layer"
 | 
					 | 
				
			||||||
     id="layer1">
 | 
					 | 
				
			||||||
    <rect
 | 
					 | 
				
			||||||
       style="fill:#25202c;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:square;stroke-linejoin:bevel;stroke-opacity:1;paint-order:fill markers stroke"
 | 
					 | 
				
			||||||
       id="rect4712"
 | 
					 | 
				
			||||||
       width="100"
 | 
					 | 
				
			||||||
       height="100"
 | 
					 | 
				
			||||||
       x="0"
 | 
					 | 
				
			||||||
       y="0"
 | 
					 | 
				
			||||||
       ry="24.342688" />
 | 
					 | 
				
			||||||
    <circle
 | 
					 | 
				
			||||||
       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.296213;stroke-linecap:square;stroke-linejoin:bevel;paint-order:fill markers stroke"
 | 
					 | 
				
			||||||
       id="path234"
 | 
					 | 
				
			||||||
       cx="32.183838"
 | 
					 | 
				
			||||||
       cy="37.277283"
 | 
					 | 
				
			||||||
       r="11.198684" />
 | 
					 | 
				
			||||||
    <rect
 | 
					 | 
				
			||||||
       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.296213;stroke-linecap:square;stroke-linejoin:bevel;paint-order:fill markers stroke"
 | 
					 | 
				
			||||||
       id="rect1054"
 | 
					 | 
				
			||||||
       width="19.398724"
 | 
					 | 
				
			||||||
       height="71.576004"
 | 
					 | 
				
			||||||
       x="59.616123"
 | 
					 | 
				
			||||||
       y="14.211996" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
       id="path1175"
 | 
					 | 
				
			||||||
       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.31583;stroke-linecap:square;stroke-linejoin:bevel;stroke-opacity:1;paint-order:fill markers stroke"
 | 
					 | 
				
			||||||
       d="m 45.710924,37.909235 c -0.08308,1.7843 -0.506133,3.552079 -1.278577,5.16464 -1.067261,2.404981 -2.906892,4.366553 -5.129349,5.714834 l 10.696654,4.40096 -13.418115,24.765056 21.254461,-19.595787 c 5.44e-4,-4.297076 -4.96e-4,-8.593943 5.78e-4,-12.891057 z" />
 | 
					 | 
				
			||||||
  </g>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
@@ -1,39 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Builder;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					 | 
				
			||||||
using Microsoft.Extensions.DependencyInjection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Server;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class PongEndpoints : Behaviour, IFirstFrameUpdate
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private INetworkCommunicatorServer? server = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public PongEndpoints()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Task.Run(() =>
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            WebApplicationBuilder builder = WebApplication.CreateBuilder();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            builder.Services.AddHealthChecks();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            WebApplication app = builder.Build();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            app.MapHealthChecks("/health");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            app.MapGet("/stats", GetStats);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            app.Run($"http://0.0.0.0:{Environment.GetEnvironmentVariable("PORT") ?? "8888"}");
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IResult GetStats() => Results.Json(new { Count = server?.Connections.Count ?? 0 });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame() => server = Universe.FindRequiredBehaviour<INetworkCommunicatorServer>();
 | 
					 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe) => server = null;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Threading;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Debug;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Universe universe = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FileLogger fileLogger = new($"Logs/{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss-ffffff}.log");
 | 
					 | 
				
			||||||
universe.InstantiateUniverseObject().SetUniverseObject("Logger").BehaviourController
 | 
					 | 
				
			||||||
    .AddBehaviour<LoggerContainer>().Logger = ILogger.Shared = new LoggerWrapper(fileLogger, new ConsoleLogger());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Pong.PongUniverse.ApplyPongServer(universe, int.Parse(Environment.GetEnvironmentVariable("PORT") ?? "8888"));
 | 
					 | 
				
			||||||
Pong.PongUniverse.ApplyPongUniverse(universe);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
universe.InstantiateUniverseObject().SetUniverseObject("Endpoints").BehaviourController
 | 
					 | 
				
			||||||
    .AddBehaviour<Server.PongEndpoints>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DateTime lastRun = DateTime.UtcNow;
 | 
					 | 
				
			||||||
TimeSpan interval = new(0, 0, 0, 0, 16);
 | 
					 | 
				
			||||||
TimeSpan timeSinceStart = new(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
universe.Initialize();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
while (true)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (lastRun + interval <= DateTime.UtcNow)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        lastRun += interval;
 | 
					 | 
				
			||||||
        timeSinceStart += interval;
 | 
					 | 
				
			||||||
        universe.Update(new(timeSinceStart, interval));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    Thread.Sleep(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <PropertyGroup>
 | 
					 | 
				
			||||||
    <OutputType>Exe</OutputType>
 | 
					 | 
				
			||||||
    <TargetFramework>net9.0</TargetFramework>
 | 
					 | 
				
			||||||
    <ImplicitUsings>disable</ImplicitUsings>
 | 
					 | 
				
			||||||
    <Nullable>enable</Nullable>
 | 
					 | 
				
			||||||
    <RootNamespace>Pong.Platforms.Server</RootNamespace>
 | 
					 | 
				
			||||||
    <AssemblyName>Server</AssemblyName>
 | 
					 | 
				
			||||||
  </PropertyGroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <ProjectReference Include="../../Shared/Shared.csproj" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" />
 | 
					 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.0-preview.5.25277.114" />
 | 
					 | 
				
			||||||
    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</Project>
 | 
					 | 
				
			||||||
							
								
								
									
										176
									
								
								Pong.sln
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								Pong.sln
									
									
									
									
									
								
							@@ -7,171 +7,41 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{F7F626
 | 
				
			|||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Core", "Engine\Engine.Core\Engine.Core.csproj", "{990CA10C-1EBB-4395-A43A-456B7029D8C9}"
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Core", "Engine\Engine.Core\Engine.Core.csproj", "{990CA10C-1EBB-4395-A43A-456B7029D8C9}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game", "Game\Game.csproj", "{500E1B05-39D7-4232-8051-E7351D745306}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Input", "Engine\Engine.Input\Engine.Input.csproj", "{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Physics2D", "Engine\Engine.Physics2D\Engine.Physics2D.csproj", "{0D97F83C-B043-48B1-B155-7354C4E84FC0}"
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Physics2D", "Engine\Engine.Physics2D\Engine.Physics2D.csproj", "{0D97F83C-B043-48B1-B155-7354C4E84FC0}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine", "Engine\Engine\Engine.csproj", "{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{FECFFD54-338F-4060-9161-1E5770D1DC33}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Desktop", "Platforms\Desktop\Desktop.csproj", "{2B627F66-5A61-4F69-B479-62EEAB603D01}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Systems", "Engine\Engine.Systems\Engine.Systems.csproj", "{8863A1BA-2E83-419F-BACB-D4A4156EC71C}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine.Integration", "Engine.Integration", "{9059393F-4073-9273-0EEC-2B1BA61B620B}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Integration.MonoGame", "Engine\Engine.Integration\Engine.Integration.MonoGame\Engine.Integration.MonoGame.csproj", "{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Platforms\Server\Server.csproj", "{A15263DB-DF65-4A07-8CA1-33A2919501A0}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Integration.Yaml", "Engine\Engine.Integration\Engine.Integration.Yaml\Engine.Integration.Yaml.csproj", "{79F870AB-249E-4CA0-9DF0-F265514581DF}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Integration.LiteNetLib", "Engine\Engine.Integration\Engine.Integration.LiteNetLib\Engine.Integration.LiteNetLib.csproj", "{7AA22306-772F-45F4-8F30-97EBD1FC124D}"
 | 
					 | 
				
			||||||
EndProject
 | 
					 | 
				
			||||||
Global
 | 
					Global
 | 
				
			||||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
						GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
				
			||||||
		Debug|Any CPU = Debug|Any CPU
 | 
							Debug|Any CPU = Debug|Any CPU
 | 
				
			||||||
		Debug|x64 = Debug|x64
 | 
					 | 
				
			||||||
		Debug|x86 = Debug|x86
 | 
					 | 
				
			||||||
		Release|Any CPU = Release|Any CPU
 | 
							Release|Any CPU = Release|Any CPU
 | 
				
			||||||
		Release|x64 = Release|x64
 | 
					 | 
				
			||||||
		Release|x86 = Release|x86
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
					 | 
				
			||||||
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{79F870AB-249E-4CA0-9DF0-F265514581DF}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|x64.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Debug|x86.Build.0 = Debug|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x64.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x64.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x86.ActiveCfg = Release|Any CPU
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x86.Build.0 = Release|Any CPU
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(SolutionProperties) = preSolution
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
		HideSolutionNode = FALSE
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
				
			||||||
 | 
							{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{500E1B05-39D7-4232-8051-E7351D745306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{500E1B05-39D7-4232-8051-E7351D745306}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{500E1B05-39D7-4232-8051-E7351D745306}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{500E1B05-39D7-4232-8051-E7351D745306}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(NestedProjects) = preSolution
 | 
						GlobalSection(NestedProjects) = preSolution
 | 
				
			||||||
		{990CA10C-1EBB-4395-A43A-456B7029D8C9} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
							{990CA10C-1EBB-4395-A43A-456B7029D8C9} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
				
			||||||
 | 
							{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
				
			||||||
		{0D97F83C-B043-48B1-B155-7354C4E84FC0} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
							{0D97F83C-B043-48B1-B155-7354C4E84FC0} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
				
			||||||
		{2F6B1E26-1217-4EFD-874C-05ADEE4C7969} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
					 | 
				
			||||||
		{2B627F66-5A61-4F69-B479-62EEAB603D01} = {FECFFD54-338F-4060-9161-1E5770D1DC33}
 | 
					 | 
				
			||||||
		{8863A1BA-2E83-419F-BACB-D4A4156EC71C} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
					 | 
				
			||||||
		{9059393F-4073-9273-0EEC-2B1BA61B620B} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
 | 
					 | 
				
			||||||
		{7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283} = {9059393F-4073-9273-0EEC-2B1BA61B620B}
 | 
					 | 
				
			||||||
		{A15263DB-DF65-4A07-8CA1-33A2919501A0} = {FECFFD54-338F-4060-9161-1E5770D1DC33}
 | 
					 | 
				
			||||||
		{7AA22306-772F-45F4-8F30-97EBD1FC124D} = {9059393F-4073-9273-0EEC-2B1BA61B620B}
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
EndGlobal
 | 
					EndGlobal
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "version": 1,
 | 
					 | 
				
			||||||
  "isRoot": true,
 | 
					 | 
				
			||||||
  "tools": {
 | 
					 | 
				
			||||||
    "dotnet-mgcb": {
 | 
					 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					 | 
				
			||||||
      "commands": [
 | 
					 | 
				
			||||||
        "mgcb"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "dotnet-mgcb-editor": {
 | 
					 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					 | 
				
			||||||
      "commands": [
 | 
					 | 
				
			||||||
        "mgcb-editor"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "dotnet-mgcb-editor-linux": {
 | 
					 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					 | 
				
			||||||
      "commands": [
 | 
					 | 
				
			||||||
        "mgcb-editor-linux"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "dotnet-mgcb-editor-windows": {
 | 
					 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					 | 
				
			||||||
      "commands": [
 | 
					 | 
				
			||||||
        "mgcb-editor-windows"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "dotnet-mgcb-editor-mac": {
 | 
					 | 
				
			||||||
      "version": "3.8.2.1105",
 | 
					 | 
				
			||||||
      "commands": [
 | 
					 | 
				
			||||||
        "mgcb-editor-mac"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,110 +0,0 @@
 | 
				
			|||||||
using Microsoft.Xna.Framework.Audio;
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Content;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
using Engine.Physics2D;
 | 
					 | 
				
			||||||
using Engine.Systems.Tween;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Ball : Behaviour2D, IFirstFrameUpdate, ILoadContent, IPhysicsUpdate, INetworkEntity,
 | 
					 | 
				
			||||||
    IPacketListenerClient<Ball.BallUpdatePacket>,
 | 
					 | 
				
			||||||
    IPacketListenerClient<Ball.BallResetPacket>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public float Speed { get; set; } = 500f;
 | 
					 | 
				
			||||||
    public float SpeedUpMultiplier { get; set; } = .025f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public IRigidBody2D RigidBody { get; private set; } = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IPhysicsEngine2D physicsEngine2D = null!;
 | 
					 | 
				
			||||||
    private ITweenManager tweenManager = null!;
 | 
					 | 
				
			||||||
    private INetworkCommunicatorServer? networkServer = null;
 | 
					 | 
				
			||||||
    private ITween? networkTween = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SoundEffect? bounceSoundEffect = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        BehaviourController.GetRequiredBehaviour<ICollider2D>().OnCollisionDetected.AddListener(OnCollisionDetected);
 | 
					 | 
				
			||||||
        physicsEngine2D = Universe.FindRequiredBehaviour<IPhysicsEngine2D>();
 | 
					 | 
				
			||||||
        tweenManager = Universe.FindRequiredBehaviour<ITweenManager>();
 | 
					 | 
				
			||||||
        RigidBody = BehaviourController.GetRequiredBehaviour<IRigidBody2D>();
 | 
					 | 
				
			||||||
        networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void LoadContent(ContentManager content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        bounceSoundEffect = content.Load<SoundEffect>("Audio/Bounce");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void LaunchBall(Vector2D launchDirection)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        ResetBall();
 | 
					 | 
				
			||||||
        RigidBody.Velocity = launchDirection * Speed;
 | 
					 | 
				
			||||||
        networkServer?.SendToAll(new BallUpdatePacket(this));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void ResetBall()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (networkTween is not null)
 | 
					 | 
				
			||||||
            tweenManager.CancelTween(networkTween);
 | 
					 | 
				
			||||||
        Transform.Position = Vector2D.Zero;
 | 
					 | 
				
			||||||
        RigidBody.Velocity = Vector2D.Zero;
 | 
					 | 
				
			||||||
        networkServer?.SendToAll(new BallResetPacket());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void PhysicsUpdate(float delta)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (RigidBody.Velocity.MagnitudeSquared <= 0.01f)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Vector2D direction = RigidBody.Velocity.Normalized;
 | 
					 | 
				
			||||||
        RigidBody.Velocity += direction * delta * SpeedUpMultiplier;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
 | 
					 | 
				
			||||||
            RigidBody.Velocity = information.Detected.Transform.Position.FromTo(information.Detector.Transform.Position).Normalized * RigidBody.Velocity.Magnitude;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            RigidBody.Velocity = RigidBody.Velocity.Reflect(information.Normal);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (information.Detected.Transform.BehaviourController.GetBehaviour<ScoreWall>() is null)
 | 
					 | 
				
			||||||
            networkServer?.SendToAll(new BallUpdatePacket(this));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Ball() { }
 | 
					 | 
				
			||||||
    public Ball(float speed) => Speed = speed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void IPacketListenerClient<BallResetPacket>.OnClientPacketArrived(IConnection sender, BallResetPacket packet) => ResetBall();
 | 
					 | 
				
			||||||
    void IPacketListenerClient<BallUpdatePacket>.OnClientPacketArrived(IConnection sender, BallUpdatePacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Vector2D localToServerPosition = Transform.Position.FromTo(packet.Position);
 | 
					 | 
				
			||||||
        if (localToServerPosition.MagnitudeSquared < 4f)
 | 
					 | 
				
			||||||
            networkTween = Transform.TweenPositionAdditive(tweenManager, .25f, localToServerPosition);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            Transform.Position = packet.Position;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (RigidBody.Velocity.MagnitudeSquared >= .01f)
 | 
					 | 
				
			||||||
            bounceSoundEffect?.Play();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        RigidBody.Velocity = packet.Velocity;
 | 
					 | 
				
			||||||
        physicsEngine2D.StepIndividual(RigidBody, sender.Ping);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private class BallResetPacket : INetworkPacket;
 | 
					 | 
				
			||||||
    private class BallUpdatePacket : INetworkPacket
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public Vector2D Position { get; set; } = Vector2D.Zero;
 | 
					 | 
				
			||||||
        public Vector2D Velocity { get; set; } = Vector2D.Zero;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public BallUpdatePacket() { }
 | 
					 | 
				
			||||||
        public BallUpdatePacket(Ball ballBehaviour)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Position = ballBehaviour.Transform.Position;
 | 
					 | 
				
			||||||
            Velocity = ballBehaviour.RigidBody.Velocity;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,69 +0,0 @@
 | 
				
			|||||||
using Microsoft.Xna.Framework.Input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Systems.Input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class CameraController : Behaviour, IFirstFrameUpdate, IUpdate
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private MonoGameCamera2D cameraBehaviour = null!;
 | 
					 | 
				
			||||||
    private IButtonInputs<Keys> buttonInputs = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private float defaultZoomLevel = 1f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cameraBehaviour = BehaviourController.GetRequiredBehaviour<MonoGameCamera2D>();
 | 
					 | 
				
			||||||
        buttonInputs = Universe.FindRequiredBehaviour<IButtonInputs<Keys>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        buttonInputs.RegisterOnPress(Keys.F, SwitchToFullScreen);
 | 
					 | 
				
			||||||
        buttonInputs.RegisterOnPress(Keys.R, ResetCamera);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void Update()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.U))
 | 
					 | 
				
			||||||
            cameraBehaviour.Zoom += Universe.Time.DeltaTime * 5f;
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.J))
 | 
					 | 
				
			||||||
            cameraBehaviour.Zoom -= Universe.Time.DeltaTime * 5f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.NumPad8)) cameraBehaviour.Transform.LocalPosition += Vector2D.Up * Universe.Time.DeltaTime * 500f;
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.NumPad2)) cameraBehaviour.Transform.LocalPosition -= Vector2D.Up * Universe.Time.DeltaTime * 500f;
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.NumPad6)) cameraBehaviour.Transform.LocalPosition += Vector2D.Right * Universe.Time.DeltaTime * 500f;
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.NumPad4)) cameraBehaviour.Transform.LocalPosition -= Vector2D.Right * Universe.Time.DeltaTime * 500f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.Q))
 | 
					 | 
				
			||||||
            cameraBehaviour.Transform.Rotation += Universe.Time.DeltaTime * 45f;
 | 
					 | 
				
			||||||
        if (buttonInputs.IsPressed(Keys.E))
 | 
					 | 
				
			||||||
            cameraBehaviour.Transform.Rotation -= Universe.Time.DeltaTime * 45f;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void SwitchToFullScreen(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (cameraBehaviour.Graphics.IsFullScreen)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cameraBehaviour.Graphics.PreferMultiSampling = false;
 | 
					 | 
				
			||||||
        cameraBehaviour.Graphics.PreferredBackBufferWidth = cameraBehaviour.Graphics.GraphicsDevice.Adapter.CurrentDisplayMode.Width;
 | 
					 | 
				
			||||||
        cameraBehaviour.Graphics.PreferredBackBufferHeight = cameraBehaviour.Graphics.GraphicsDevice.Adapter.CurrentDisplayMode.Height;
 | 
					 | 
				
			||||||
        cameraBehaviour.Graphics.IsFullScreen = true;
 | 
					 | 
				
			||||||
        cameraBehaviour.Graphics.ApplyChanges();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        float previousScreenSize = Math.Sqrt(Math.Sqr(cameraBehaviour.Viewport.Width) + Math.Sqr(cameraBehaviour.Viewport.Height));
 | 
					 | 
				
			||||||
        float currentScreenSize = Math.Sqrt(Math.Sqr(cameraBehaviour.Graphics.GraphicsDevice.Viewport.Width) + Math.Sqr(cameraBehaviour.Graphics.GraphicsDevice.Viewport.Height));
 | 
					 | 
				
			||||||
        defaultZoomLevel /= previousScreenSize / currentScreenSize;
 | 
					 | 
				
			||||||
        cameraBehaviour.Zoom /= previousScreenSize / currentScreenSize;
 | 
					 | 
				
			||||||
        cameraBehaviour.Viewport = cameraBehaviour.Graphics.GraphicsDevice.Viewport;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void ResetCamera(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cameraBehaviour.Zoom = defaultZoomLevel;
 | 
					 | 
				
			||||||
        cameraBehaviour.Transform.LocalPosition = Vector2D.Zero;
 | 
					 | 
				
			||||||
        cameraBehaviour.Transform.LocalRotation = 0f;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class DrawableColliderCircle : Engine.Physics2D.Collider2DCircle, IDrawableTriangle
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private const float CIRCLE_SEGMENT_COUNT = 32f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ColorRGBA Color { get; set; } = new ColorRGBA(255, 255, 255);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void Draw(ITriangleBatch triangleBatch)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Recalculate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < CIRCLE_SEGMENT_COUNT; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            float iPi1 = i / CIRCLE_SEGMENT_COUNT * 2f * Math.Pi;
 | 
					 | 
				
			||||||
            float iPi2 = (i + 1f).Mod(CIRCLE_SEGMENT_COUNT) / CIRCLE_SEGMENT_COUNT * 2f * Math.Pi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Vector2D firstVertex = new Vector2D(Math.Sin(iPi1), Math.Cos(iPi1)) * CircleWorld.Radius;
 | 
					 | 
				
			||||||
            Vector2D secondVertex = new Vector2D(Math.Sin(iPi2), Math.Cos(iPi2)) * CircleWorld.Radius;
 | 
					 | 
				
			||||||
            triangleBatch.Draw(new(CircleWorld.Center, CircleWorld.Center + firstVertex, CircleWorld.Center + secondVertex), Color);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public DrawableColliderCircle(Circle circle) : base(circle) { }
 | 
					 | 
				
			||||||
    public DrawableColliderCircle(Circle circle, ColorRGBA color) : base(circle) { Color = color; }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class DrawableColliderShape : Engine.Physics2D.Collider2DShape, IDrawableTriangle
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private readonly IList<Triangle> triangles = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ColorRGBA Color { get; set; } = new ColorRGBA(255, 255, 255);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void Draw(ITriangleBatch triangleBatch)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Recalculate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ShapeWorld.ToTrianglesConvex(triangles);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (Triangle triangle in triangles)
 | 
					 | 
				
			||||||
            triangleBatch.Draw(triangle, Color);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public DrawableColliderShape(Shape2D shape) : base(shape) { }
 | 
					 | 
				
			||||||
    public DrawableColliderShape(Shape2D shape, ColorRGBA color) : base(shape) { Color = color; }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
using Microsoft.Xna.Framework.Content;
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Graphics;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Label : Behaviour2D, IDrawableSprite, ILoadContent
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public SpriteFont? Font { get; set; } = null;
 | 
					 | 
				
			||||||
    public ColorRGBA Color { get; set; } = new ColorRGBA(255, 255, 255, 255);
 | 
					 | 
				
			||||||
    public int Size { get; set; } = 16;
 | 
					 | 
				
			||||||
    public string Text { get; set; } = string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void Draw(ISpriteBatch spriteBatch)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (Font is null)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        spriteBatch.DrawString(Font, Text, Transform.Position, Color.ToPreMultipliedColor(), Transform.Rotation, Vector2D.One * .5f, Transform.Scale.Magnitude, SpriteEffects.None, 0f);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void LoadContent(ContentManager content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Font ??= content.Load<SpriteFont>("UbuntuMono");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Label() { }
 | 
					 | 
				
			||||||
    public Label(SpriteFont font) => Font = font;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,117 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
using Engine.Physics2D;
 | 
					 | 
				
			||||||
using Engine.Systems.Input;
 | 
					 | 
				
			||||||
using Engine.Systems.Tween;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Paddle(Keys Up, Keys Down, float High, float Low, float Speed) : Behaviour2D,
 | 
					 | 
				
			||||||
    IFirstFrameUpdate, IPhysicsIteration, IPostPhysicsUpdate,
 | 
					 | 
				
			||||||
    IPacketListenerServer<Paddle.PaddleKeyStatePacket>, IPacketListenerClient<Paddle.PaddleKeyStatePacket>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private Keys Up { get; } = Up;
 | 
					 | 
				
			||||||
    private Keys Down { get; } = Down;
 | 
					 | 
				
			||||||
    public float High { get; } = High;
 | 
					 | 
				
			||||||
    public float Low { get; } = Low;
 | 
					 | 
				
			||||||
    public float Speed { get; set; } = Speed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private bool isUpPressed = false;
 | 
					 | 
				
			||||||
    private bool isDownPressed = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IButtonInputs<Keys>? inputs = null;
 | 
					 | 
				
			||||||
    private INetworkCommunicatorClient? networkClient = null!;
 | 
					 | 
				
			||||||
    private INetworkCommunicatorServer? networkServer = null;
 | 
					 | 
				
			||||||
    private IRigidBody2D rigidBody = null!;
 | 
					 | 
				
			||||||
    private IPhysicsEngine2D physicsEngine2D = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ITween? networkTween = null;
 | 
					 | 
				
			||||||
    private ITweenManager tweenManager = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void PhysicsIterate(float delta)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (isUpPressed)
 | 
					 | 
				
			||||||
            rigidBody.Transform.Position += Vector2D.Up * Speed * delta;
 | 
					 | 
				
			||||||
        else if (isDownPressed)
 | 
					 | 
				
			||||||
            rigidBody.Transform.Position -= Vector2D.Up * Speed * delta;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void PostPhysicsUpdate(float delta)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Transform.Position = new Vector2D(Transform.Position.X, MathF.Max(MathF.Min(Transform.Position.Y, High), Low));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        physicsEngine2D = Universe.FindRequiredBehaviour<IPhysicsEngine2D>();
 | 
					 | 
				
			||||||
        inputs = Universe.FindBehaviour<IButtonInputs<Keys>>();
 | 
					 | 
				
			||||||
        networkClient = Universe.FindBehaviour<INetworkCommunicatorClient>();
 | 
					 | 
				
			||||||
        networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
 | 
					 | 
				
			||||||
        rigidBody = BehaviourController.GetRequiredBehaviour<IRigidBody2D>();
 | 
					 | 
				
			||||||
        tweenManager = Universe.FindRequiredBehaviour<ITweenManager>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        inputs?.RegisterOnPress(Up, OnUpPressed);
 | 
					 | 
				
			||||||
        inputs?.RegisterOnRelease(Up, OnUpReleased);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        inputs?.RegisterOnPress(Down, OnDownPressed);
 | 
					 | 
				
			||||||
        inputs?.RegisterOnRelease(Down, OnDownReleased);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnUpPressed(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args) { isUpPressed = true; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); }
 | 
					 | 
				
			||||||
    private void OnUpReleased(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args) { isUpPressed = false; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); }
 | 
					 | 
				
			||||||
    private void OnDownPressed(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args) { isDownPressed = true; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); }
 | 
					 | 
				
			||||||
    private void OnDownReleased(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args) { isDownPressed = false; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void OnServerPacketArrived(IConnection sender, PaddleKeyStatePacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        physicsEngine2D.StepIndividual(rigidBody, -sender.Ping.Min(.05f));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        isUpPressed = packet.IsUpPressed;
 | 
					 | 
				
			||||||
        isDownPressed = packet.IsDownPressed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        physicsEngine2D.StepIndividual(rigidBody, sender.Ping.Min(.05f));
 | 
					 | 
				
			||||||
        networkServer?.SendToAll(new PaddleKeyStatePacket(this));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void OnClientPacketArrived(IConnection sender, PaddleKeyStatePacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (packet.IsDownPressed || packet.IsUpPressed) // Check if the server paddle is moving
 | 
					 | 
				
			||||||
            if (isDownPressed == packet.IsDownPressed && isUpPressed == packet.IsUpPressed) // Check if we are the ones giving the inputs
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        physicsEngine2D.StepIndividual(rigidBody, -sender.Ping);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        isUpPressed = packet.IsUpPressed;
 | 
					 | 
				
			||||||
        isDownPressed = packet.IsDownPressed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        physicsEngine2D.StepIndividual(rigidBody, sender.Ping);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Vector2D localToServerPosition = Transform.Position.FromTo(packet.Position);
 | 
					 | 
				
			||||||
        networkTween = Transform.TweenPositionAdditive(tweenManager, .1f, localToServerPosition);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public class PaddleKeyStatePacket : IEntityNetworkPacket
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public string EntityId { get; set; } = default!;
 | 
					 | 
				
			||||||
        public Vector2D Position { get; set; } = default!;
 | 
					 | 
				
			||||||
        public bool IsUpPressed { get; set; } = default!;
 | 
					 | 
				
			||||||
        public bool IsDownPressed { get; set; } = default!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public PaddleKeyStatePacket Set(Paddle paddleBehaviour)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            EntityId = paddleBehaviour.Id;
 | 
					 | 
				
			||||||
            Position = paddleBehaviour.Transform.Position;
 | 
					 | 
				
			||||||
            IsUpPressed = paddleBehaviour.isUpPressed;
 | 
					 | 
				
			||||||
            IsDownPressed = paddleBehaviour.isDownPressed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return this;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public PaddleKeyStatePacket() { }
 | 
					 | 
				
			||||||
        public PaddleKeyStatePacket(Paddle paddleBehaviour) => Set(paddleBehaviour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,107 +0,0 @@
 | 
				
			|||||||
using Microsoft.Xna.Framework.Audio;
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Content;
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Debug;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
using Engine.Systems.Input;
 | 
					 | 
				
			||||||
using Engine.Systems.Time;
 | 
					 | 
				
			||||||
using Engine.Systems.Tween;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class PongGameStarter : Behaviour, INetworkEntity, IFirstFrameUpdate, ILoadContent,
 | 
					 | 
				
			||||||
    IPacketListenerServer<PongGameStarter.RequestStartPacket>,
 | 
					 | 
				
			||||||
    IPacketListenerClient<PongGameStarter.RequestStartPacket>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private const float START_COUNTDOWN = 3f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private INetworkCommunicatorServer? networkServer = null;
 | 
					 | 
				
			||||||
    private INetworkCommunicatorClient? networkClient = null;
 | 
					 | 
				
			||||||
    private ITweenManager? tweenManager = null;
 | 
					 | 
				
			||||||
    private PongManager pongManager = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ILogger? logger = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Label? label = null;
 | 
					 | 
				
			||||||
    private TickerTimer timer = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SoundEffectInstance? tickSoundEffect = null;
 | 
					 | 
				
			||||||
    private SoundEffectInstance? startSoundEffect = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IButtonInputs<Keys>? buttonInputs = Universe.FindBehaviour<IButtonInputs<Keys>>();
 | 
					 | 
				
			||||||
        buttonInputs?.RegisterOnRelease(Keys.Space, (_, _1) => networkClient?.SendToServer(new RequestStartPacket()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        networkClient = Universe.FindBehaviour<INetworkCommunicatorClient>();
 | 
					 | 
				
			||||||
        networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
 | 
					 | 
				
			||||||
        tweenManager = Universe.FindBehaviour<ITweenManager>();
 | 
					 | 
				
			||||||
        pongManager = BehaviourController.GetRequiredBehaviourInParent<PongManager>();
 | 
					 | 
				
			||||||
        label = BehaviourController.GetRequiredBehaviour<Label>();
 | 
					 | 
				
			||||||
        logger = Universe.FindBehaviour<ILogger>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!BehaviourController.TryGetBehaviour(out timer!))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            timer = BehaviourController.AddBehaviour<TickerTimer>();
 | 
					 | 
				
			||||||
            timer.OnStarted.AddListener(OnCountdownStart);
 | 
					 | 
				
			||||||
            timer.OnTick.AddListener(DisplayCountdown);
 | 
					 | 
				
			||||||
            timer.OnStopped.AddListener(StartPong);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void LoadContent(ContentManager content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        tickSoundEffect = content.Load<SoundEffect>("Audio/TimerTick").CreateInstance();
 | 
					 | 
				
			||||||
        startSoundEffect = content.Load<SoundEffect>("Audio/TimerEnd").CreateInstance();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnCountdownStart(IReadOnlyTimer sender)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        pongManager.Reset();
 | 
					 | 
				
			||||||
        DisplayCountdown(timer);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void DisplayCountdown(ITicker sender)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        tickSoundEffect?.Play();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (label != null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            label.Text = $"{START_COUNTDOWN - timer.TickCounter}";
 | 
					 | 
				
			||||||
            label.Color = new ColorRGBA(255, 255, 255, 255);
 | 
					 | 
				
			||||||
            if (tweenManager is not null)
 | 
					 | 
				
			||||||
                label.Color.TweenColor(tweenManager, 1f, new ColorRGBA(255, 255, 255, 0), (x) => label.Color = x);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void StartPong(IReadOnlyTimer sender)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        startSoundEffect?.Play();
 | 
					 | 
				
			||||||
        pongManager.Start();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void IPacketListenerServer<RequestStartPacket>.OnServerPacketArrived(IConnection sender, RequestStartPacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        logger?.Log(this, $"{sender} requested start");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pongManager.IsGameInProgress)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            logger?.Log(this, $"The game is already in progress");
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        timer.Start(START_COUNTDOWN);
 | 
					 | 
				
			||||||
        networkServer?.SendToAll(packet);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void IPacketListenerClient<RequestStartPacket>.OnClientPacketArrived(IConnection sender, RequestStartPacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        logger?.Log(this, $"Server is starting the game");
 | 
					 | 
				
			||||||
        timer.Start(START_COUNTDOWN - sender.Ping);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private class RequestStartPacket : INetworkPacket;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,154 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Audio;
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Content;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Debug;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate, ILoadContent,
 | 
					 | 
				
			||||||
    IPacketListenerClient<PongManager.StartPacket>,
 | 
					 | 
				
			||||||
    IPacketListenerClient<PongManager.ScorePacket>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public Action<PongManager>? OnReset { get; set; } = null;
 | 
					 | 
				
			||||||
    public Action<PongManager>? OnFinished { get; set; } = null;
 | 
					 | 
				
			||||||
    public Action<PongManager>? OnScoreUpdated { get; set; } = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Random random = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private INetworkCommunicatorServer? networkServer = null;
 | 
					 | 
				
			||||||
    private ILogger? logger = null;
 | 
					 | 
				
			||||||
    private SoundEffectInstance? scoreSoundEffect = null;
 | 
					 | 
				
			||||||
    private SoundEffectInstance? gameEndSoundEffect = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int ScoreLeft { get; private set; } = 0;
 | 
					 | 
				
			||||||
    public int ScoreRight { get; private set; } = 0;
 | 
					 | 
				
			||||||
    public int ScoreSum => ScoreLeft + ScoreRight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int WinScore { get; } = 5;
 | 
					 | 
				
			||||||
    public Ball Ball { get; private set; } = null!;
 | 
					 | 
				
			||||||
    public bool IsGameInProgress { get; private set; } = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public PongManager() => WinScore = 5;
 | 
					 | 
				
			||||||
    public PongManager(int winScore) => WinScore = winScore;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Ball = Universe.FindRequiredBehaviour<Ball>();
 | 
					 | 
				
			||||||
        networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
 | 
					 | 
				
			||||||
        logger = Universe.FindBehaviour<ILogger>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void LoadContent(ContentManager content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        gameEndSoundEffect = content.Load<SoundEffect>("Audio/Win").CreateInstance();
 | 
					 | 
				
			||||||
        scoreSoundEffect = content.Load<SoundEffect>("Audio/Score").CreateInstance();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void ScoreToLeft()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        ScoreLeft++;
 | 
					 | 
				
			||||||
        PostScoreUpdate();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void ScoreToRight()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        ScoreRight++;
 | 
					 | 
				
			||||||
        PostScoreUpdate();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public bool Start()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (networkServer is null)
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (Ball.RigidBody.Velocity.MagnitudeSquared > 0.01f)
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Reset();
 | 
					 | 
				
			||||||
        IsGameInProgress = true;
 | 
					 | 
				
			||||||
        PostScoreUpdate();
 | 
					 | 
				
			||||||
        networkServer.SendToAll(new StartPacket());
 | 
					 | 
				
			||||||
        logger?.Log(this, $"Game started");
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void Reset()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        ScoreLeft = ScoreRight = 0;
 | 
					 | 
				
			||||||
        IsGameInProgress = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ball.ResetBall();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        OnReset?.Invoke(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void PostScoreUpdate()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        OnScoreUpdated?.Invoke(this);
 | 
					 | 
				
			||||||
        Ball.ResetBall();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (networkServer is not null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            networkServer.SendToAll(new ScorePacket(this));
 | 
					 | 
				
			||||||
            logger?.Log(this, $"Sending score update packet to all: {ScoreLeft} - {ScoreRight}");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int halfwayScore = (int)(WinScore * .5f);
 | 
					 | 
				
			||||||
        if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            IsGameInProgress = false;
 | 
					 | 
				
			||||||
            gameEndSoundEffect?.Play();
 | 
					 | 
				
			||||||
            OnFinished?.Invoke(this);
 | 
					 | 
				
			||||||
            logger?.Log(this, $"Game finished: {ScoreLeft} - {ScoreRight}");
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ball.LaunchBall(GetBallLaunchDirection());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Vector2D GetBallLaunchDirection()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        const float AllowedRadians = 45f * Engine.Core.Math.DegreeToRadian;
 | 
					 | 
				
			||||||
        float rotation = (float)random.NextDouble() * 2f * AllowedRadians - AllowedRadians;
 | 
					 | 
				
			||||||
        bool isBackwards = (random.Next() % 2) == 1;
 | 
					 | 
				
			||||||
        return Vector2D.Right.Rotate(isBackwards ? rotation + Engine.Core.Math.Pi : rotation);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void IPacketListenerClient<ScorePacket>.OnClientPacketArrived(IConnection sender, ScorePacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        ScoreLeft = packet.Left;
 | 
					 | 
				
			||||||
        ScoreRight = packet.Right;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        PostScoreUpdate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (IsGameInProgress && (ScoreLeft != 0 || ScoreRight != 0))
 | 
					 | 
				
			||||||
            scoreSoundEffect?.Play();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        logger?.Log(this, $"Client score update packet arrived: {packet.Left} - {packet.Right}");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void IPacketListenerClient<StartPacket>.OnClientPacketArrived(IConnection sender, StartPacket packet)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IsGameInProgress = true;
 | 
					 | 
				
			||||||
        logger?.Log(this, $"Game started");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private class StartPacket : INetworkPacket;
 | 
					 | 
				
			||||||
    private class ScorePacket : INetworkPacket
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public int Left { get; set; }
 | 
					 | 
				
			||||||
        public int Right { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public ScorePacket() { }
 | 
					 | 
				
			||||||
        public ScorePacket(PongManager pongManagerBehaviour)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Left = pongManagerBehaviour.ScoreLeft;
 | 
					 | 
				
			||||||
            Right = pongManagerBehaviour.ScoreRight;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
using Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class ScoreLabel(bool IsLeft) : Label, IFirstFrameUpdate
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public readonly bool IsLeft = IsLeft;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private PongManager pongManager = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        pongManager = Universe.FindRequiredBehaviour<PongManager>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pongManager.OnScoreUpdated += UpdateScores;
 | 
					 | 
				
			||||||
        pongManager.OnReset += UpdateScores;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        UpdateScores(pongManager);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void UpdateScores(PongManager pongManager)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (IsLeft)
 | 
					 | 
				
			||||||
            Text = pongManager.ScoreLeft.ToString();
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            Text = pongManager.ScoreRight.ToString();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,19 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Physics2D;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class ScoreWall(Action OnCollision) : Behaviour2D, IFirstFrameUpdate
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private Action OnCollision { get; } = OnCollision;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (!BehaviourController.TryGetBehaviour(out ICollider2D? collider2D))
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        collider2D.OnCollisionDetected.AddListener((_, _1) => OnCollision?.Invoke());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,52 +0,0 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
#----------------------------- Global Properties ----------------------------#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/outputDir:bin/$(Platform)
 | 
					 | 
				
			||||||
/intermediateDir:obj/$(Platform)
 | 
					 | 
				
			||||||
/platform:DesktopGL
 | 
					 | 
				
			||||||
/config:
 | 
					 | 
				
			||||||
/profile:Reach
 | 
					 | 
				
			||||||
/compress:False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#-------------------------------- References --------------------------------#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#---------------------------------- Content ---------------------------------#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin Audio/Bounce.wav
 | 
					 | 
				
			||||||
/importer:WavImporter
 | 
					 | 
				
			||||||
/processor:SoundEffectProcessor
 | 
					 | 
				
			||||||
/processorParam:Quality=Best
 | 
					 | 
				
			||||||
/build:Audio/Bounce.wav
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin Audio/Score.wav
 | 
					 | 
				
			||||||
/importer:WavImporter
 | 
					 | 
				
			||||||
/processor:SoundEffectProcessor
 | 
					 | 
				
			||||||
/processorParam:Quality=Best
 | 
					 | 
				
			||||||
/build:Audio/Score.wav
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin Audio/Win.wav
 | 
					 | 
				
			||||||
/importer:WavImporter
 | 
					 | 
				
			||||||
/processor:SoundEffectProcessor
 | 
					 | 
				
			||||||
/processorParam:Quality=Best
 | 
					 | 
				
			||||||
/build:Audio/Win.wav
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin Audio/TimerTick.wav
 | 
					 | 
				
			||||||
/importer:WavImporter
 | 
					 | 
				
			||||||
/processor:SoundEffectProcessor
 | 
					 | 
				
			||||||
/processorParam:Quality=Best
 | 
					 | 
				
			||||||
/build:Audio/TimerTick.wav
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin Audio/TimerEnd.wav
 | 
					 | 
				
			||||||
/importer:WavImporter
 | 
					 | 
				
			||||||
/processor:SoundEffectProcessor
 | 
					 | 
				
			||||||
/processorParam:Quality=Best
 | 
					 | 
				
			||||||
/build:Audio/TimerEnd.wav
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#begin UbuntuMono.spritefont
 | 
					 | 
				
			||||||
/importer:FontDescriptionImporter
 | 
					 | 
				
			||||||
/processor:FontDescriptionProcessor
 | 
					 | 
				
			||||||
/processorParam:PremultiplyAlpha=True
 | 
					 | 
				
			||||||
/processorParam:TextureFormat=Compressed
 | 
					 | 
				
			||||||
/build:UbuntuMono.spritefont
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							@@ -1,128 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Microsoft.Xna.Framework.Input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Pong.Behaviours;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Factory;
 | 
					 | 
				
			||||||
using Engine.Integration.MonoGame;
 | 
					 | 
				
			||||||
using Engine.Systems.Network;
 | 
					 | 
				
			||||||
using Engine.Physics2D;
 | 
					 | 
				
			||||||
using Engine.Systems.Tween;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Pong;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public static class PongUniverse
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public static IUniverse ApplyPongClient(Universe universe, string server, int port)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LiteNetLibClient client = universe.InstantiateUniverseObject().SetUniverseObject("Client").BehaviourController.AddBehaviour<LiteNetLibClient>();
 | 
					 | 
				
			||||||
        client.BehaviourController.AddBehaviour<NetworkManager>();
 | 
					 | 
				
			||||||
        universe.OnPreUpdate.AddOneTimeListener((_, _) => client.Connect(server, port));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        DrawManager drawManager = universe.InstantiateUniverseObject().SetUniverseObject("Draw Manager").BehaviourController.AddBehaviour<DrawManager>();
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Triangle Batcher", drawManager.UniverseObject).BehaviourController.AddBehaviour<TriangleBatcher>();
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Sprite Batcher", drawManager.UniverseObject).BehaviourController.AddBehaviour<SpriteBatcher>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Camera")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>()
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<CameraController>()
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<MonoGameCamera2D>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Score Left")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<ScoreLabel>(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Score Right")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<ScoreLabel>(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return universe;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static IUniverse ApplyPongServer(Universe universe, int port)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LiteNetLibServer server = universe.InstantiateUniverseObject().SetUniverseObject("Server").BehaviourController.AddBehaviour<LiteNetLibServer>();
 | 
					 | 
				
			||||||
        server.BehaviourController.AddBehaviour<NetworkManager>();
 | 
					 | 
				
			||||||
        universe.OnPreUpdate.AddOneTimeListener((_, _) => server.Start(port, 2));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return universe;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static IUniverse ApplyPongUniverse(Universe universe)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Update Manager").BehaviourController.AddBehaviour<UpdateManager>();
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Coroutine Manager").BehaviourController.AddBehaviour<CoroutineManager>();
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Tween Manager").BehaviourController.AddBehaviour<TweenManager>();
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Physics Engine 2D").BehaviourController.AddBehaviour<PhysicsEngine2D>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        PongManager pongManager = universe.InstantiateUniverseObject().SetUniverseObject("Pong Game Manager")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<PongManager>(5);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Pong Game Starter", parent: pongManager.UniverseObject)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<PongGameStarter>()
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-24, 250f), scale: Vector2D.One * .5f)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Label>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Ball")
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f))
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<DrawableColliderCircle>(new Circle(Vector2D.Zero, 1f))
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<Ball>()
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<RigidBody2D>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IUniverseObject leftPaddle = UniverseObjectFactory.Instantiate().SetUniverseObject("Left Paddle");
 | 
					 | 
				
			||||||
        leftPaddle.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f))
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
        Paddle leftPaddleBehaviour = BehaviourFactory.Instantiate<Paddle>(Keys.W, Keys.S, 228f, -228f, 400f);
 | 
					 | 
				
			||||||
        leftPaddleBehaviour.Id = "lp";
 | 
					 | 
				
			||||||
        leftPaddle.BehaviourController.AddBehaviour(leftPaddleBehaviour);
 | 
					 | 
				
			||||||
        universe.Register(leftPaddle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IUniverseObject rightPaddle = UniverseObjectFactory.Instantiate().SetUniverseObject("Right Paddle");
 | 
					 | 
				
			||||||
        rightPaddle.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f))
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
                .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
        Paddle rightPaddleBehaviour = BehaviourFactory.Instantiate<Paddle>(Keys.Up, Keys.Down, 228f, -228f, 400f);
 | 
					 | 
				
			||||||
        rightPaddleBehaviour.Id = "rp";
 | 
					 | 
				
			||||||
        rightPaddle.BehaviourController.AddBehaviour(rightPaddleBehaviour);
 | 
					 | 
				
			||||||
        universe.Register(rightPaddle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Wall Top")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f))
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Wall Bottom")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f))
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Wall Right")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f))
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<ScoreWall>((Action)pongManager.ScoreToLeft)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universe.InstantiateUniverseObject().SetUniverseObject("Wall Left")
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f))
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<ScoreWall>((Action)pongManager.ScoreToRight)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<DrawableColliderShape>(Shape2D.Square)
 | 
					 | 
				
			||||||
            .BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return universe;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
					 | 
				
			||||||
  <PropertyGroup>
 | 
					 | 
				
			||||||
    <TargetFramework>net9.0</TargetFramework>
 | 
					 | 
				
			||||||
    <Nullable>enable</Nullable>
 | 
					 | 
				
			||||||
    <RootNamespace>Pong.Shared</RootNamespace>
 | 
					 | 
				
			||||||
    <AssemblyName>Pong.Shared</AssemblyName>
 | 
					 | 
				
			||||||
  </PropertyGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105">
 | 
					 | 
				
			||||||
      <PrivateAssets>All</PrivateAssets>
 | 
					 | 
				
			||||||
    </PackageReference>
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <ProjectReference Include="../Engine/Engine/Engine.csproj" />
 | 
					 | 
				
			||||||
    <ProjectReference Include="../Engine/Engine.Integration/Engine.Integration.MonoGame/Engine.Integration.MonoGame.csproj" />
 | 
					 | 
				
			||||||
    <ProjectReference Include="../Engine/Engine.Integration/Engine.Integration.LiteNetLib/Engine.Integration.LiteNetLib.csproj" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
</Project>
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user