├── .gitignore
├── .idea
├── .gitignore
├── artifacts
│ └── Multiplayer.xml
├── compiler.xml
├── jarRepositories.xml
├── libraries
│ ├── CMUtils.xml
│ ├── LazyLib_Kotlin.xml
│ ├── commons_compiler_jdk.xml
│ ├── lw_Console.xml
│ └── netty_buffer_4_1_69_Final.xml
├── misc.xml
├── modules.xml
├── runConfigurations
│ └── Starsector.xml
├── uiDesigner.xml
└── vcs.xml
├── Multiplayer.iml
├── data
├── config
│ ├── mp
│ │ └── proj_spawns.csv
│ └── settings.json
├── console
│ └── commands.csv
├── missions
│ ├── MP_Default
│ │ ├── descriptor.json
│ │ ├── logo.png
│ │ └── mission_text.txt
│ ├── MP_FighterTest
│ │ ├── descriptor.json
│ │ ├── logo.png
│ │ └── mission_text.txt
│ └── mission_list.csv
└── weapons
│ ├── mp_hurricane_proj_spawn.wpn
│ ├── mp_pilum_proj_spawn.wpn
│ ├── mp_sabot_proj_spawn.wpn
│ └── weapon_data.csv
├── jars
├── Multiplayer.jar
└── netty
│ ├── netty-all-4.1.69.Final.jar
│ ├── netty-buffer-4.1.69.Final.jar
│ ├── netty-codec-4.1.69.Final.jar
│ ├── netty-codec-dns-4.1.69.Final.jar
│ ├── netty-common-4.1.69.Final.jar
│ ├── netty-resolver-4.1.69.Final.jar
│ ├── netty-resolver-dns-4.1.69.Final.jar
│ └── netty-transport-4.1.69.Final.jar
├── mod_info.json
├── runcodes.txt
├── src
└── data
│ ├── missions
│ ├── MP_Default
│ │ ├── MissionDefinition.java
│ │ └── MultiplayerMissionPlugin.java
│ └── MP_FighterTest
│ │ └── MissionDefinition.java
│ └── scripts
│ ├── MPModPlugin.java
│ ├── console
│ └── commands
│ │ ├── mpConnectToHost.java
│ │ ├── mpConnectToHostCached.java
│ │ ├── mpFlush.java
│ │ ├── mpPilotShip.java
│ │ └── mpRunServer.java
│ ├── misc
│ └── MapSet.java
│ ├── net
│ ├── data
│ │ ├── DataGenManager.java
│ │ ├── InboundData.java
│ │ ├── InstanceData.java
│ │ ├── OutboundData.java
│ │ ├── datagen
│ │ │ ├── BaseDatagen.java
│ │ │ ├── FighterVariantDatastore.java
│ │ │ ├── ProjectileSpecDatastore.java
│ │ │ └── ShipVariantDatastore.java
│ │ ├── packables
│ │ │ ├── DestExecute.java
│ │ │ ├── EntityData.java
│ │ │ ├── InterpExecute.java
│ │ │ ├── InterpRecordLambda.java
│ │ │ ├── RecordLambda.java
│ │ │ ├── SourceExecute.java
│ │ │ ├── entities
│ │ │ │ ├── projectiles
│ │ │ │ │ ├── BallisticProjectileData.java
│ │ │ │ │ ├── MissileData.java
│ │ │ │ │ └── MovingRayData.java
│ │ │ │ └── ships
│ │ │ │ │ ├── ClientPlayerData.java
│ │ │ │ │ ├── ShieldData.java
│ │ │ │ │ ├── ShipData.java
│ │ │ │ │ ├── VariantData.java
│ │ │ │ │ └── WeaponData.java
│ │ │ └── metadata
│ │ │ │ ├── ChatListenData.java
│ │ │ │ ├── ClientConnectionData.java
│ │ │ │ ├── ClientData.java
│ │ │ │ ├── LobbyData.java
│ │ │ │ ├── ServerConnectionData.java
│ │ │ │ └── ServerPlayerData.java
│ │ ├── plugins
│ │ │ ├── ClientScript.java
│ │ │ ├── DEMPlugin.java
│ │ │ └── ServerScript.java
│ │ ├── records
│ │ │ ├── ByteRecord.java
│ │ │ ├── ConversionUtils.java
│ │ │ ├── DataRecord.java
│ │ │ ├── Float16Record.java
│ │ │ ├── Float32Record.java
│ │ │ ├── IntRecord.java
│ │ │ ├── ShortRecord.java
│ │ │ ├── StringRecord.java
│ │ │ ├── Vector2f16Record.java
│ │ │ ├── Vector2f32Record.java
│ │ │ ├── Vector3f32Record.java
│ │ │ └── collections
│ │ │ │ ├── ListenArrayRecord.java
│ │ │ │ ├── SyncingListRecord.java
│ │ │ │ └── SyncingMapRecord.java
│ │ └── tables
│ │ │ ├── BaseEntityManager.java
│ │ │ ├── EntityInstanceMap.java
│ │ │ ├── EntityTable.java
│ │ │ ├── InboundEntityManager.java
│ │ │ ├── OutboundEntityManager.java
│ │ │ ├── client
│ │ │ ├── ClientCustomDataTable.java
│ │ │ └── combat
│ │ │ │ ├── connection
│ │ │ │ ├── LobbyInput.java
│ │ │ │ └── TextChatClient.java
│ │ │ │ ├── entities
│ │ │ │ ├── ClientProjectileTable.java
│ │ │ │ ├── VariantDataMap.java
│ │ │ │ └── ships
│ │ │ │ │ └── ClientShipTable.java
│ │ │ │ └── player
│ │ │ │ ├── Player.java
│ │ │ │ └── PlayerShip.java
│ │ │ └── server
│ │ │ ├── ServerCustomDataTable.java
│ │ │ └── combat
│ │ │ ├── connection
│ │ │ └── TextChatHost.java
│ │ │ ├── entities
│ │ │ ├── DamagingExplosionTable.java
│ │ │ ├── ProjectileTable.java
│ │ │ └── ships
│ │ │ │ └── ShipTable.java
│ │ │ └── players
│ │ │ ├── PlayerLobby.java
│ │ │ └── PlayerShips.java
│ └── io
│ │ ├── BaseConnectionWrapper.java
│ │ ├── ByteArrayReader.java
│ │ ├── ClientConnectionWrapper.java
│ │ ├── ClientDuplex.java
│ │ ├── Clock.java
│ │ ├── CompressionUtils.java
│ │ ├── MessageContainer.java
│ │ ├── ServerConnectionManager.java
│ │ ├── ServerConnectionWrapper.java
│ │ ├── ServerDuplex.java
│ │ ├── Unpacked.java
│ │ ├── tcp
│ │ ├── BufferUnpacker.java
│ │ ├── MessageContainerDecoder.java
│ │ ├── MessageContainerEncoder.java
│ │ ├── client
│ │ │ ├── ClientChannelHandler.java
│ │ │ └── SocketClient.java
│ │ └── server
│ │ │ ├── ServerChannelHandler.java
│ │ │ ├── SocketChannelInitializer.java
│ │ │ └── SocketServer.java
│ │ └── udp
│ │ ├── DatagramDecoder.java
│ │ ├── DatagramUnpacker.java
│ │ ├── DatagramUtils.java
│ │ ├── client
│ │ ├── ClientInboundHandler.java
│ │ └── DatagramClient.java
│ │ └── server
│ │ ├── DatagramChannelInitializer.java
│ │ ├── DatagramServer.java
│ │ └── ServerInboundHandler.java
│ ├── plugins
│ ├── MPClientPlugin.java
│ ├── MPLogger.java
│ ├── MPPlugin.java
│ ├── MPServerPlugin.java
│ ├── ai
│ │ ├── MPDefaultAutofireAIPlugin.java
│ │ ├── MPDefaultMissileAIPlugin.java
│ │ └── MPDefaultShipAIPlugin.java
│ └── gui
│ │ ├── MPChatboxPlugin.java
│ │ └── MPUIPlugin.java
│ └── test
│ └── MPTest.java
└── target
└── classes
└── data
└── scripts
└── console
└── commands
└── mpRunServer.class
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/artifacts/Multiplayer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/jars
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/libraries/CMUtils.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/libraries/LazyLib_Kotlin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/libraries/commons_compiler_jdk.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/libraries/lw_Console.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/libraries/netty_buffer_4_1_69_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Starsector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Multiplayer.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/data/config/mp/proj_spawns.csv:
--------------------------------------------------------------------------------
1 | projectileID,weaponID
2 | sabot_warhead2,mp_sabot_proj_spawn
3 | mirv_warhead,mp_hurricane_proj_spawn
4 | pilum_second_stage,mp_pilum_proj_spawn
--------------------------------------------------------------------------------
/data/config/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins" : {
3 | "MPUIPlugin": "data.scripts.plugins.gui.MPUIPlugin",
4 | },
5 | "mpServerTickRate": 60, # rate at which server broadcasts packets
6 | "mpClientTickrate": 30, # rate at which client will send command packets
7 | "mpMaxConnections": 4,
8 |
9 | "mpSocketQueueLimit": 32,
10 | "mpDatagramQueueLimit": 64,
11 |
12 | "MP_PacketSize": 600,
13 | "MP_UsernameString": "tomatopaste" #max 12 characters
14 | }
--------------------------------------------------------------------------------
/data/console/commands.csv:
--------------------------------------------------------------------------------
1 | command,class,tags,syntax,help
2 | mpP,data.scripts.console.commands.mpPilotShip,"combat,multiplayer",mpPilotShip,Pilot nearest ship
--------------------------------------------------------------------------------
/data/missions/MP_Default/descriptor.json:
--------------------------------------------------------------------------------
1 | {
2 | "title":"Multiplayer",
3 | "difficulty":"GOOD",
4 | "icon":"logo.png",
5 | "background":"graphics/backgrounds/background5.jpg"
6 | }
--------------------------------------------------------------------------------
/data/missions/MP_Default/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/data/missions/MP_Default/logo.png
--------------------------------------------------------------------------------
/data/missions/MP_Default/mission_text.txt:
--------------------------------------------------------------------------------
1 | And after all we're playing multiplayer
--------------------------------------------------------------------------------
/data/missions/MP_FighterTest/descriptor.json:
--------------------------------------------------------------------------------
1 | {
2 | "title":"Fighter Test",
3 | "difficulty":"GOOD",
4 | "icon":"logo.png",
5 | "background":"graphics/backgrounds/background5.jpg"
6 | }
--------------------------------------------------------------------------------
/data/missions/MP_FighterTest/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/data/missions/MP_FighterTest/logo.png
--------------------------------------------------------------------------------
/data/missions/MP_FighterTest/mission_text.txt:
--------------------------------------------------------------------------------
1 | Lmao
--------------------------------------------------------------------------------
/data/missions/mission_list.csv:
--------------------------------------------------------------------------------
1 | mission
2 | MP_Default
3 | MP_FighterTest
--------------------------------------------------------------------------------
/data/weapons/mp_hurricane_proj_spawn.wpn:
--------------------------------------------------------------------------------
1 | {
2 | "id":"mp_hurricane_proj_spawn",
3 | "specClass":"projectile",
4 | "type":"MISSILE",
5 | "size":"LARGE",
6 | "turretSprite":"graphics/weapons/hurricane_mirv_launcher_turret_base.png",
7 | "hardpointSprite":"graphics/weapons/hurricane_mirv_launcher_hardpoint_base.png",
8 | #"hardpointOffsets":[17, -5, 17, 5],
9 | #"turretOffsets":[13, -5, 13, 5],
10 | #"hardpointAngleOffsets":[0, 0],
11 | #"turretAngleOffsets":[0, 0],
12 | "hardpointOffsets":[23, 0],
13 | "turretOffsets":[17, 0],
14 | "hardpointAngleOffsets":[0],
15 | "turretAngleOffsets":[0],
16 | "barrelMode":"ALTERNATING",
17 | "animationType":"SMOKE",
18 | "renderHints":[RENDER_LOADED_MISSILES],
19 | "interruptibleBurst":false,
20 | "displayArcRadius":300,
21 | "smokeSpec":{"particleSizeMin":20.0,
22 | "particleSizeRange":20.0,
23 | "cloudParticleCount":3,
24 | "cloudDuration":1.0,
25 | "cloudRadius":10.0,
26 | "blowbackParticleCount":3,
27 | "blowbackDuration":2.0,
28 | "blowbackLength":30.0,
29 | "blowbackSpread":10.0,
30 | "particleColor":[100,100,100,200]},
31 | "projectileSpecId":"mirv_warhead",
32 | "fireSoundTwo":"hurricane_mirv_fire",
33 | }
--------------------------------------------------------------------------------
/data/weapons/mp_pilum_proj_spawn.wpn:
--------------------------------------------------------------------------------
1 | {
2 | "id":"mp_pilum_proj_spawn",
3 | "specClass":"projectile",
4 | "type":"MISSILE",
5 | "size":"MEDIUM",
6 | "turretSprite":"graphics/weapons/pilum_lrm_launcher_turret_base.png",
7 | "hardpointSprite":"graphics/weapons/pilum_lrm_launcher_hardpoint_base.png",
8 | "hardpointOffsets":[20, -6, 20, 0, 20, 6],
9 | "turretOffsets":[15, -6, 15, 0, 15, 6],
10 | "hardpointAngleOffsets":[0, 0, 0],
11 | "turretAngleOffsets":[0, 0, 0],
12 | "barrelMode":"ALTERNATING",
13 | "animationType":"SMOKE",
14 | "renderHints":[RENDER_LOADED_MISSILES],
15 | "interruptibleBurst":false,
16 | "smokeSpec":{"particleSizeMin":20.0,
17 | "particleSizeRange":20.0,
18 | "cloudParticleCount":3,
19 | "cloudDuration":1.0,
20 | "cloudRadius":10.0,
21 | "blowbackParticleCount":3,
22 | "blowbackDuration":2.0,
23 | "blowbackLength":30.0,
24 | "blowbackSpread":10.0,
25 | "particleColor":[100,100,100,200]},
26 | "projectileSpecId":"pilum_second_stage",
27 | "fireSoundTwo":"pilum_lrm_fire",
28 | }
--------------------------------------------------------------------------------
/data/weapons/mp_sabot_proj_spawn.wpn:
--------------------------------------------------------------------------------
1 | {
2 | "id":"mp_sabot_proj_spawn",
3 | "specClass":"projectile",
4 | "type":"MISSILE",
5 | "size":"SMALL",
6 | "turretSprite":"graphics/weapons/missile_rack_m_3x_turret_base.png",
7 | "hardpointSprite":"graphics/weapons/missile_rack_m_3x_hardpoint_base.png",
8 | "hardpointOffsets":[15, -6, 15, 6, 15, 0],
9 | "turretOffsets":[8, -6, 8, 6, 8, 0],
10 | "hardpointAngleOffsets":[0, 0, 0],
11 | "turretAngleOffsets":[0, 0, 0],
12 | "barrelMode":"ALTERNATING",
13 | "animationType":"SMOKE",
14 | "renderHints":[RENDER_LOADED_MISSILES],
15 | "interruptibleBurst":false,
16 | "displayArcRadius":300,
17 | "smokeSpec":{"particleSizeMin":20.0,
18 | "particleSizeRange":20.0,
19 | "cloudParticleCount":3,
20 | "cloudDuration":1.0,
21 | "cloudRadius":10.0,
22 | "blowbackParticleCount":3,
23 | "blowbackDuration":2.0,
24 | "blowbackLength":30.0,
25 | "blowbackSpread":10.0,
26 | "particleColor":[100,100,100,200]},
27 | "projectileSpecId":"sabot_warhead2",
28 | "fireSoundTwo":"sabot_srm_fire",
29 | }
--------------------------------------------------------------------------------
/data/weapons/weapon_data.csv:
--------------------------------------------------------------------------------
1 | name,id,tier,rarity,base value,range,damage/second,damage/shot,emp,impact,turn rate,OPs,ammo,ammo/sec,reload size,type,energy/shot,energy/second,chargeup,chargedown,burst size,burst delay,min spread,max spread,spread/shot,spread decay/sec,beam speed,proj speed,launch speed,flight time,proj hitpoints,autofireAccBonus,extraArcForAI,hints,tags,groupTag,tech/manufacturer,for weapon tooltip>>,primaryRoleStr,speedStr,trackingStr,turnRateStr,accuracyStr,customPrimary,customPrimaryHL,customAncillary,customAncillaryHL,noDPSInTooltip,number
2 | Sabot MIRV Spawn,mp_sabot_proj_spawn,1,,0,600,,100,200,,,4,3,,,KINETIC,0,,0,1,1,,0,0,0,0,,1000,,,500,,,SYSTEM,,,,,Anti Shield,Slow,Poor,,,"Submunition hits on hull or armor have a %s chance to arc to weapons and engines, dealing %s EMP damage.",25% | 200,,,TRUE,11.75
3 | Hurricane MIRV Spawn,mp_hurricane_proj_spawn,1,,0,2500,,500,,5,,25,10,,,HIGH_EXPLOSIVE,0,,0,15,1,,0,0,0,0,,250,50,12,250,,,SYSTEM,,,,,Finisher,Medium,Good,,,,,,,TRUE,16
4 | Pilum MIRV Spawn,mp_pilum_proj_spawn,0,,0,4000,,500,500,25,10,7,30,0.1,,FRAGMENTATION,0,,0,15,3,0.4,0,0,0,0,,125,100,30,150,,,SYSTEM,,,,,Long Range Support,Very Slow,Very Poor,,,"Second-stage hits on shields have a chance to arc through to weapons and engines, dealing %s EMP damage. The chance to pierce the shields is based on the target's hard flux level.",500,,,TRUE,12.5
--------------------------------------------------------------------------------
/jars/Multiplayer.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/Multiplayer.jar
--------------------------------------------------------------------------------
/jars/netty/netty-all-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-all-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-buffer-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-buffer-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-codec-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-codec-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-codec-dns-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-codec-dns-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-common-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-common-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-resolver-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-resolver-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-resolver-dns-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-resolver-dns-4.1.69.Final.jar
--------------------------------------------------------------------------------
/jars/netty/netty-transport-4.1.69.Final.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/automatopaste/Multiplayer/6ea94d27b83589eb86c56b5fd51910776b51f6c3/jars/netty/netty-transport-4.1.69.Final.jar
--------------------------------------------------------------------------------
/mod_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "id":"multiplayer",
3 | "name":"Multiplayer",
4 | "author":"tomatopaste",
5 | "version":"0.1.2",
6 | "description":"Combat multiplayer mod.",
7 | "gameVersion":"0.97a-RC8",
8 | "jars":[
9 | "jars/Multiplayer.jar",
10 | "jars/netty/netty-all-4.1.69.Final.jar",
11 | "jars/netty/netty-buffer-4.1.69.Final.jar",
12 | "jars/netty/netty-codec-4.1.69.Final.jar",
13 | "jars/netty/netty-codec-dns-4.1.69.Final.jar",
14 | "jars/netty/netty-common-4.1.69.Final.jar",
15 | "jars/netty/netty-transport-4.1.69.Final.jar",
16 | "jars/netty/netty-resolver-4.1.69.Final.jar",
17 | "jars/netty/netty-resolver-dns-4.1.69.Final.jar"
18 | ],
19 | "modPlugin":"data.scripts.MPModPlugin",
20 | "utility": true
21 | }
--------------------------------------------------------------------------------
/runcodes.txt:
--------------------------------------------------------------------------------
1 | -disable all ai
2 | runcode for (ShipAPI ship : Global.getCombatEngine().getShips()) {
3 | ship.setShipAI(new data.scripts.plugins.ai.MPDefaultShipAIPlugin());}
--------------------------------------------------------------------------------
/src/data/missions/MP_Default/MissionDefinition.java:
--------------------------------------------------------------------------------
1 | package data.missions.MP_Default;
2 |
3 | import com.fs.starfarer.api.fleet.FleetGoal;
4 | import com.fs.starfarer.api.fleet.FleetMemberType;
5 | import com.fs.starfarer.api.mission.FleetSide;
6 | import com.fs.starfarer.api.mission.MissionDefinitionAPI;
7 | import com.fs.starfarer.api.mission.MissionDefinitionPlugin;
8 |
9 | public class MissionDefinition implements MissionDefinitionPlugin {
10 |
11 | private static final int NUM_PLAYER = 6;
12 | private static final int NUM_ENEMY = 6;
13 |
14 | @Override
15 | public void defineMission(MissionDefinitionAPI api) {
16 | api.addPlanet(0f, 0f, 150f, "barren-bombarded", 0f, true);
17 |
18 | api.initFleet(FleetSide.PLAYER, "PCS", FleetGoal.ATTACK, false);
19 | api.initFleet(FleetSide.ENEMY, "TTS", FleetGoal.ATTACK, true);
20 |
21 | api.setFleetTagline(FleetSide.PLAYER, "Us");
22 | api.setFleetTagline(FleetSide.ENEMY, "Them");
23 |
24 | api.addToFleet(FleetSide.PLAYER, "hyperion_Attack", FleetMemberType.SHIP, true);
25 | api.addToFleet(FleetSide.ENEMY, "hyperion_Attack", FleetMemberType.SHIP, true);
26 |
27 | // Set up the map.
28 | float width = 15000f;
29 | float height = 15000f;
30 | api.initMap(-width / 2f, width / 2f, -height / 2f, height / 2f);
31 |
32 | float minX = -width / 2;
33 | float minY = -height / 2;
34 |
35 | for (int i = 0; i < 50; i++) {
36 | float x = (float) Math.random() * width - width / 2;
37 | float y = (float) Math.random() * height - height / 2;
38 | float radius = 100f + (float) Math.random() * 400f;
39 | api.addNebula(x, y, radius);
40 | }
41 |
42 | // Add objectives
43 | api.addObjective(minX + width * 0.25f, minY + height * 0.25f, "nav_buoy");
44 | api.addObjective(minX + width * 0.35f, minY + height * 0.65f, "comm_relay");
45 | api.addObjective(minX + width * 0.75f, minY + height * 0.45f, "nav_buoy");
46 | api.addObjective(minX + width * 0.65f, minY + height * 0.35f, "comm_relay");
47 | api.addObjective(minX + width * 0.5f, minY + height * 0.25f, "sensor_array");
48 |
49 | api.addPlugin(new MultiplayerMissionPlugin());
50 | }
51 | }
--------------------------------------------------------------------------------
/src/data/missions/MP_Default/MultiplayerMissionPlugin.java:
--------------------------------------------------------------------------------
1 | package data.missions.MP_Default;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
5 | import com.fs.starfarer.api.combat.CombatEngineAPI;
6 | import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
7 | import com.fs.starfarer.api.combat.ShipAPI;
8 | import com.fs.starfarer.api.fleet.FleetMemberAPI;
9 | import com.fs.starfarer.api.fleet.FleetMemberType;
10 | import com.fs.starfarer.api.input.InputEventAPI;
11 | import com.fs.starfarer.api.mission.FleetSide;
12 | import com.fs.starfarer.api.util.IntervalUtil;
13 | import data.scripts.MPModPlugin;
14 | import data.scripts.net.data.packables.entities.ships.ClientPlayerData;
15 | import data.scripts.net.data.packables.entities.ships.ShipData;
16 | import data.scripts.net.data.tables.server.combat.players.PlayerShips;
17 | import data.scripts.plugins.MPPlugin;
18 | import data.scripts.plugins.MPServerPlugin;
19 | import org.lwjgl.util.vector.Vector2f;
20 |
21 | import java.util.ArrayList;
22 | import java.util.HashMap;
23 | import java.util.List;
24 | import java.util.Map;
25 |
26 | public class MultiplayerMissionPlugin extends BaseEveryFrameCombatPlugin {
27 |
28 | private static final List variants = new ArrayList<>();
29 | static {
30 | variants.add("hyperion_Attack");
31 | }
32 |
33 | private final Map cooldowns = new HashMap<>();
34 |
35 | @Override
36 | public void advance(float amount, List events) {
37 | CombatEngineAPI engine = Global.getCombatEngine();
38 |
39 | engine.setDoNotEndCombat(true);
40 |
41 | if (engine.isPaused()) return;
42 |
43 | MPPlugin plugin = MPModPlugin.getPlugin();
44 | if (!(plugin instanceof MPServerPlugin)) return;
45 | MPServerPlugin server = (MPServerPlugin) plugin;
46 |
47 | PlayerShips playerShips = (PlayerShips) server.getEntityManagers().get(PlayerShips.class);
48 | Map controlData = playerShips.getControlData();
49 |
50 | //runcode Global.getCombatEngine().applyDamage(Global.getCombatEngine().getPlayerShip(), Global.getCombatEngine().getPlayerShip().getLocation(), 9999999f, DamageType.ENERGY, 0f, true, false, null);
51 |
52 | // host
53 | short hostID = playerShips.getHostShipID();
54 | ShipAPI host = null;
55 | if (hostID != PlayerShips.NULL_SHIP_ID) {
56 | ShipData shipData = playerShips.getShipTable().getShipTable().array()[hostID];
57 |
58 | if (shipData != null) {
59 | host = shipData.getShip();
60 | }
61 | }
62 |
63 | IntervalUtil hostCooldown = cooldowns.get((short)-1);
64 | if (hostCooldown == null) {
65 | hostCooldown = new IntervalUtil(1f, 1f);
66 | cooldowns.put((short)-1, hostCooldown);
67 | }
68 | if (host == null || !host.isAlive() || host.isHulk()) {
69 | hostCooldown.advance(amount);
70 | if (hostCooldown.intervalElapsed()) {
71 | ShipAPI newShip = spawnShip(engine);
72 |
73 | playerShips.transferControl(newShip, true, null, (byte) 0);
74 | }
75 | } else {
76 | hostCooldown.setElapsed(0f);
77 | }
78 |
79 | // clients
80 | for (byte connectionID : controlData.keySet()) {
81 | ClientPlayerData player = controlData.get(connectionID);
82 |
83 | ShipAPI ship = player.getShip();
84 |
85 | IntervalUtil cooldown = cooldowns.get(player.getInstanceID());
86 | if (cooldown == null) {
87 | cooldown = new IntervalUtil(1f, 1f);
88 | cooldowns.put(player.getInstanceID(), cooldown);
89 | }
90 |
91 | if (ship == null || !ship.isAlive() || ship.isHulk()) {
92 | cooldown.advance(amount);
93 | if (cooldown.intervalElapsed()) {
94 | ShipAPI newShip = spawnShip(engine);
95 |
96 | playerShips.transferControl(newShip, false, player, connectionID);
97 | }
98 | } else {
99 | cooldown.setElapsed(0f);
100 | }
101 | }
102 |
103 | }
104 |
105 | private ShipAPI spawnShip(CombatEngineAPI engine) {
106 | FleetMemberAPI member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, variants.get(0));
107 | member.getCrewComposition().setCrew(member.getHullSpec().getMaxCrew());
108 |
109 | CombatFleetManagerAPI fleetManager = engine.getFleetManager(FleetSide.PLAYER);
110 | fleetManager.addToReserves(member);
111 |
112 | Vector2f location = new Vector2f((float) (Math.random() * 2000f - 1000f), (float) (Math.random() * 2000f - 1000f));
113 | float facing = (float) (Math.random() * 360f);
114 |
115 | ShipAPI ship = fleetManager.spawnFleetMember(member, location, facing, 0f);
116 | ship.setCRAtDeployment(0.7f);
117 | ship.setControlsLocked(false);
118 |
119 | return ship;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/data/missions/MP_FighterTest/MissionDefinition.java:
--------------------------------------------------------------------------------
1 | package data.missions.MP_FighterTest;
2 |
3 | import com.fs.starfarer.api.fleet.FleetGoal;
4 | import com.fs.starfarer.api.fleet.FleetMemberType;
5 | import com.fs.starfarer.api.mission.FleetSide;
6 | import com.fs.starfarer.api.mission.MissionDefinitionAPI;
7 | import com.fs.starfarer.api.mission.MissionDefinitionPlugin;
8 |
9 | public class MissionDefinition implements MissionDefinitionPlugin {
10 |
11 | private static final int NUM_PLAYER = 6;
12 | private static final int NUM_ENEMY = 6;
13 |
14 | @Override
15 | public void defineMission(MissionDefinitionAPI api) {
16 | api.addPlanet(0f, 0f, 150f, "barren-bombarded", 0f, true);
17 |
18 | api.initFleet(FleetSide.PLAYER, "PCS", FleetGoal.ATTACK, false);
19 | api.initFleet(FleetSide.ENEMY, "TTS", FleetGoal.ATTACK, true);
20 |
21 | api.setFleetTagline(FleetSide.PLAYER, "Us");
22 | api.setFleetTagline(FleetSide.ENEMY, "Them");
23 |
24 | api.addToFleet(FleetSide.PLAYER, "condor_Attack", FleetMemberType.SHIP, true);
25 | api.addToFleet(FleetSide.ENEMY, "condor_Attack", FleetMemberType.SHIP, false);
26 |
27 | // Set up the map.
28 | float width = 15000f;
29 | float height = 15000f;
30 | api.initMap(-width / 2f, width / 2f, -height / 2f, height / 2f);
31 |
32 | float minX = -width / 2;
33 | float minY = -height / 2;
34 |
35 | for (int i = 0; i < 50; i++) {
36 | float x = (float) Math.random() * width - width / 2;
37 | float y = (float) Math.random() * height - height / 2;
38 | float radius = 100f + (float) Math.random() * 400f;
39 | api.addNebula(x, y, radius);
40 | }
41 |
42 | // Add objectives
43 | api.addObjective(minX + width * 0.25f, minY + height * 0.25f, "nav_buoy");
44 | api.addObjective(minX + width * 0.35f, minY + height * 0.65f, "comm_relay");
45 | api.addObjective(minX + width * 0.75f, minY + height * 0.45f, "nav_buoy");
46 | api.addObjective(minX + width * 0.65f, minY + height * 0.35f, "comm_relay");
47 | api.addObjective(minX + width * 0.5f, minY + height * 0.25f, "sensor_array");
48 | }
49 | }
--------------------------------------------------------------------------------
/src/data/scripts/console/commands/mpConnectToHost.java:
--------------------------------------------------------------------------------
1 | package data.scripts.console.commands;
2 |
3 | import data.scripts.MPModPlugin;
4 | import data.scripts.plugins.MPClientPlugin;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.lazywizard.console.BaseCommand;
7 | import org.lazywizard.console.Console;
8 |
9 | public class mpConnectToHost implements BaseCommand {
10 | @Override
11 | public CommandResult runCommand(@NotNull String args, @NotNull CommandContext context) {
12 | if (!(context == CommandContext.COMBAT_CAMPAIGN || context == CommandContext.COMBAT_SIMULATION || context == CommandContext.COMBAT_MISSION)) {
13 | Console.showMessage("Command only usable in combat");
14 | return CommandResult.ERROR;
15 | }
16 | if (args.trim().isEmpty()) {
17 | Console.showMessage("Specify address");
18 | return CommandResult.BAD_SYNTAX;
19 | }
20 |
21 | String[] ids = args.split(" ");
22 | if (ids.length != 1) {
23 | Console.showMessage("Syntax error");
24 | return CommandResult.BAD_SYNTAX;
25 | }
26 |
27 | String[] address = ids[0].split(":");
28 | String host = address[0];
29 | int port = Integer.parseInt(address[1]);
30 |
31 | Console.showMessage("Starting client on port " + port);
32 | MPModPlugin.setPlugin(new MPClientPlugin(host, port));
33 | Console.showMessage("Client started successfully");
34 |
35 | return CommandResult.SUCCESS;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/data/scripts/console/commands/mpConnectToHostCached.java:
--------------------------------------------------------------------------------
1 | package data.scripts.console.commands;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import data.scripts.MPModPlugin;
5 | import data.scripts.plugins.MPClientPlugin;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.lazywizard.console.BaseCommand;
8 | import org.lazywizard.console.Console;
9 |
10 | public class mpConnectToHostCached implements BaseCommand {
11 | @Override
12 | public CommandResult runCommand(@NotNull String args, @NotNull CommandContext context) {
13 | if (!(context == CommandContext.COMBAT_CAMPAIGN || context == CommandContext.COMBAT_SIMULATION || context == CommandContext.COMBAT_MISSION)) {
14 | Console.showMessage("Command only usable in combat");
15 | return CommandResult.ERROR;
16 | }
17 |
18 | String a = Global.getSettings().getString("mpHost");
19 | String[] b = a.split(":");
20 | String host = b[0];
21 | int port = Integer.parseInt(b[1]);
22 |
23 | Console.showMessage("Starting client on port " + port);
24 | MPModPlugin.setPlugin(new MPClientPlugin(host, port));
25 | Console.showMessage("Client started successfully");
26 |
27 | return CommandResult.SUCCESS;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/data/scripts/console/commands/mpFlush.java:
--------------------------------------------------------------------------------
1 | package data.scripts.console.commands;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.lazywizard.console.BaseCommand;
6 | import org.lazywizard.console.Console;
7 |
8 | public class mpFlush implements BaseCommand {
9 | public static final String FLUSH_KEY = "JESSE_WE_NEED_TO_COOK";
10 | @Override
11 | public CommandResult runCommand(@NotNull String args, @NotNull CommandContext context) {
12 | if (!(context == CommandContext.COMBAT_CAMPAIGN || context == CommandContext.COMBAT_SIMULATION || context == CommandContext.COMBAT_MISSION)) {
13 | Console.showMessage("Command only usable in combat");
14 | return CommandResult.ERROR;
15 | }
16 |
17 | Console.showMessage("Flushing data");
18 | Global.getCombatEngine().getCustomData().put(FLUSH_KEY, new Object());
19 |
20 | return CommandResult.SUCCESS;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/data/scripts/console/commands/mpPilotShip.java:
--------------------------------------------------------------------------------
1 | package data.scripts.console.commands;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import com.fs.starfarer.api.combat.*;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.lazywizard.console.BaseCommand;
7 | import org.lazywizard.console.Console;
8 | import org.lwjgl.util.vector.Vector2f;
9 |
10 | import java.util.Set;
11 |
12 | public class mpPilotShip implements BaseCommand {
13 |
14 | @Override
15 | public CommandResult runCommand(@NotNull String args, @NotNull CommandContext context) {
16 | Console.showMessage("deprecated");
17 |
18 | for (final ShipAPI ship : Global.getCombatEngine().getShips()) {
19 | ship.setShipAI(new ShipAIPlugin() {
20 | @Override
21 | public void setDoNotFireDelay(float amount) {
22 |
23 | }
24 |
25 | @Override
26 | public void forceCircumstanceEvaluation() {
27 |
28 | }
29 |
30 | @Override
31 | public void advance(float amount) {
32 | ship.giveCommand(ShipCommand.DECELERATE, null, 0);
33 | ship.setHoldFireOneFrame(true);
34 | }
35 |
36 | @Override
37 | public boolean needsRefit() {
38 | return false;
39 | }
40 |
41 | @Override
42 | public ShipwideAIFlags getAIFlags() {
43 | ShipwideAIFlags flags = new ShipwideAIFlags();
44 | flags.setFlag(ShipwideAIFlags.AIFlags.BACKING_OFF);
45 | return flags;
46 | }
47 |
48 | @Override
49 | public void cancelCurrentManeuver() {
50 |
51 | }
52 |
53 | @Override
54 | public ShipAIConfig getConfig() {
55 | return new ShipAIConfig();
56 | }
57 | });
58 | }
59 |
60 | return CommandResult.SUCCESS;
61 | }
62 |
63 | private static ShipAPI getClosest(Vector2f loc, CombatEngineAPI engine, Set occupied) {
64 | ShipAPI out = null;
65 | float d = Float.MAX_VALUE;
66 | for (ShipAPI ship : engine.getShips()) {
67 | if (occupied.contains(ship.getFleetMemberId())) continue;
68 |
69 | float d2 = Vector2f.sub(ship.getLocation(), loc, new Vector2f()).lengthSquared();
70 | if (d2 < d) {
71 | d = d2;
72 | out = ship;
73 | }
74 | }
75 | return out;
76 | }
77 | }
--------------------------------------------------------------------------------
/src/data/scripts/console/commands/mpRunServer.java:
--------------------------------------------------------------------------------
1 | package data.scripts.console.commands;
2 |
3 | import data.scripts.MPModPlugin;
4 | import data.scripts.plugins.MPServerPlugin;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.lazywizard.console.BaseCommand;
7 | import org.lazywizard.console.Console;
8 |
9 | public class mpRunServer implements BaseCommand {
10 | @Override
11 | public CommandResult runCommand(@NotNull String args, @NotNull CommandContext context) {
12 | if (!(context == CommandContext.COMBAT_CAMPAIGN || context == CommandContext.COMBAT_SIMULATION || context == CommandContext.COMBAT_MISSION)) {
13 | Console.showMessage("Command only usable in combat");
14 | return CommandResult.ERROR;
15 | }
16 |
17 | Console.showMessage("Starting server");
18 | MPModPlugin.setPlugin(new MPServerPlugin(20303));
19 |
20 | return CommandResult.SUCCESS;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/data/scripts/misc/MapSet.java:
--------------------------------------------------------------------------------
1 | package data.scripts.misc;
2 |
3 | import java.util.HashMap;
4 | import java.util.HashSet;
5 | import java.util.Map;
6 | import java.util.Set;
7 |
8 | public class MapSet {
9 |
10 | private final Map a = new HashMap<>();
11 | private final Map b = new HashMap<>();
12 |
13 | public MapSet() {
14 |
15 | }
16 |
17 | public MapSet(Map map) {
18 | a.putAll(map);
19 |
20 | Set set = new HashSet<>();
21 | for (T t : map.keySet()) {
22 | U u = map.get(t);
23 |
24 | if (!set.add(u)) {
25 | throw new IllegalArgumentException("mapset constructor received duplicate values");
26 | }
27 |
28 | b.put(u, t);
29 | }
30 | }
31 |
32 | public U getA(T t) {
33 | return a.get(t);
34 | }
35 |
36 | public T getB(U u) {
37 | return b.get(u);
38 | }
39 |
40 | public void put(T t, U u) {
41 | a.put(t, u);
42 | b.put(u, t);
43 | }
44 |
45 | public Set setA() {
46 | return a.keySet();
47 | }
48 |
49 | public Set setB() {
50 | return b.keySet();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/DataGenManager.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data;
2 |
3 | import data.scripts.net.data.packables.EntityData;
4 | import data.scripts.net.data.records.DataRecord;
5 | import data.scripts.net.data.tables.InboundEntityManager;
6 | import data.scripts.net.data.tables.OutboundEntityManager;
7 | import data.scripts.plugins.MPPlugin;
8 |
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Set;
13 |
14 | /**
15 | * Allows mods to specify entity types and record types at runtime
16 | */
17 | public class DataGenManager {
18 | public static Map, Byte> entityTypeIDs = new HashMap<>();
19 |
20 | public static Map recordTypeIDs = new HashMap<>();
21 | public static Map> recordInstances = new HashMap<>();
22 |
23 | public static Map inboundDataDestinations = new HashMap<>();
24 | public static Map outboundDataSources = new HashMap<>();
25 |
26 | private static byte idIncrementer = 1;
27 |
28 | public static byte registerEntityType(Class extends EntityData> clazz) {
29 | byte id = idIncrementer;
30 | entityTypeIDs.put(clazz, id);
31 | idIncrementer++;
32 |
33 | return id;
34 | }
35 |
36 | public static byte registerRecordType(String c, DataRecord> instance) {
37 | byte id = idIncrementer;
38 | recordTypeIDs.put(c, id);
39 | recordInstances.put(id, instance);
40 | idIncrementer++;
41 | return id;
42 | }
43 |
44 | public static void registerInboundEntityManager(byte dataTypeID, InboundEntityManager manager) {
45 | inboundDataDestinations.put(dataTypeID, manager);
46 | }
47 |
48 | public static void registerOutboundEntityManager(byte dataTypeID, OutboundEntityManager manager) {
49 | outboundDataSources.put(dataTypeID, manager);
50 | }
51 |
52 | public static void distributeInboundDeltas(InboundData inbound, MPPlugin plugin, int tick, byte connectionID) {
53 | for (byte type : inbound.in.keySet()) {
54 | Map> entities = inbound.in.get(type);
55 | InboundEntityManager manager = inboundDataDestinations.get(type);
56 |
57 | if (manager == null) {
58 | System.err.println("MANAGER NOT FOUND");
59 | continue;
60 | }
61 |
62 | for (short instance : entities.keySet()) {
63 | manager.processDelta(type, instance, entities.get(instance), plugin, tick, connectionID);
64 | }
65 | }
66 |
67 | for (byte type : inbound.deleted.keySet()) {
68 | Set instances = inbound.deleted.get(type);
69 | InboundEntityManager manager = inboundDataDestinations.get(type);
70 |
71 | if (manager == null) {
72 | System.err.println("MANAGER NOT FOUND");
73 | continue;
74 | }
75 |
76 | for (short instance : instances) {
77 | manager.processDeletion(type, instance, plugin, tick, connectionID);
78 | }
79 | }
80 | }
81 |
82 | /**
83 | * An ordered hierarchy of data that will be compressed into a byte buffer
84 | * Order: Type ID -> Instance ID -> Record ID
85 | * @return data hierarchy
86 | */
87 | public static Map collectOutboundDeltas(float amount, List connectionIDs, OutboundEntityManager.PacketType type) {
88 | Map connectionOutData = new HashMap<>();
89 |
90 | Map>> out = new HashMap<>();
91 | Map>> deleted = new HashMap<>();
92 |
93 | for (byte connectionID : connectionIDs) {
94 | out.put(connectionID, new HashMap>());
95 | deleted.put(connectionID, new HashMap>());
96 | }
97 |
98 | for (byte source : outboundDataSources.keySet()) {
99 | OutboundEntityManager manager = outboundDataSources.get(source);
100 | if (manager.getOutboundPacketType() != type) continue;
101 |
102 | Map> connectionEntities = manager.getOutbound(source, amount, connectionIDs);
103 |
104 | for (byte connectionID : connectionEntities.keySet()) {
105 | Map entities = connectionEntities.get(connectionID);
106 | if (entities == null || entities.isEmpty()) continue;
107 |
108 | Map> sourceEntityData = out.get(connectionID);
109 | sourceEntityData.put(source, entities);
110 | }
111 |
112 | for (byte connectionID : connectionIDs) {
113 | Set deletedEntities = manager.getDeleted(source, connectionID);
114 | if (deletedEntities == null || deletedEntities.isEmpty()) continue;
115 |
116 | Map> deletedEntityData = deleted.get(connectionID);
117 | deletedEntityData.put(source, deletedEntities);
118 | }
119 | }
120 |
121 | for (byte connectionID : connectionIDs) {
122 | Map> connectionSourceEntities = out.get(connectionID);
123 | Map> connectionDeletedEntities = deleted.get(connectionID);
124 |
125 | connectionOutData.put(connectionID, new OutboundData(connectionSourceEntities, connectionDeletedEntities, connectionID));
126 | }
127 |
128 | return connectionOutData;
129 | }
130 |
131 | /**
132 | * workaround to avoid reflection
133 | * @param typeID id
134 | * @return new empty instance
135 | */
136 | public static DataRecord> recordFactory(byte typeID) {
137 | DataRecord> out = recordInstances.get(typeID);
138 | if (out == null) {
139 | throw new NullPointerException("No record type found at ID: " + typeID);
140 | }
141 | return out;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/InboundData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | public class InboundData {
8 | public final Map>> in;
9 | public final Map> deleted;
10 | public int size = 0;
11 |
12 | public InboundData() {
13 | this(new HashMap>>(), new HashMap>());
14 | }
15 |
16 | public InboundData(Map>> in, Map> deleted) {
17 | this.in = in;
18 | this.deleted = deleted;
19 | }
20 |
21 | public void setSize(int size) {
22 | this.size = size;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/InstanceData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data;
2 |
3 | import data.scripts.net.data.records.DataRecord;
4 |
5 | import java.util.Map;
6 |
7 | public class InstanceData {
8 | public int size;
9 | public final Map> records;
10 |
11 | public InstanceData(int size, Map> records) {
12 | this.size = size;
13 | this.records = records;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/OutboundData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | public class OutboundData {
8 | private final Map> out;
9 | private final Map> deleted;
10 | private int size = -1;
11 | private final byte connectionID;
12 |
13 | public final Object sync = new Object();
14 |
15 | public OutboundData(byte connectionID) {
16 | this(new HashMap>(), new HashMap>(), connectionID);
17 | }
18 |
19 | public OutboundData(Map> out, Map> deleted, byte connectionID) {
20 | this.out = out;
21 | this.deleted = deleted;
22 | this.connectionID = connectionID;
23 | }
24 |
25 | public void setSize(int size) {
26 | this.size = size;
27 | }
28 |
29 | public int getSize() {
30 | return size;
31 | }
32 |
33 | public Map> getOut() {
34 | return out;
35 | }
36 |
37 | public Map> getDeleted() {
38 | return deleted;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/datagen/BaseDatagen.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.datagen;
2 |
3 | import data.scripts.plugins.MPPlugin;
4 |
5 | public interface BaseDatagen {
6 |
7 | void generate(MPPlugin plugin);
8 | }
9 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/datagen/FighterVariantDatastore.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.datagen;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import com.fs.starfarer.api.loading.FighterWingSpecAPI;
5 | import data.scripts.plugins.MPPlugin;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class FighterVariantDatastore implements BaseDatagen {
11 |
12 | private final Map variants = new HashMap<>();
13 |
14 | @Override
15 | public void generate(MPPlugin plugin) {
16 | for (FighterWingSpecAPI spec : Global.getSettings().getAllFighterWingSpecs()) {
17 | String variant = spec.getVariantId();
18 | String hull = spec.getVariant().getHullSpec().getHullId();
19 |
20 | if (variant != null && hull != null) {
21 | variants.put(hull, variant);
22 | } else {
23 | throw new NullPointerException("fighter wing hullspec id or variant id was null");
24 | }
25 | }
26 | }
27 |
28 | public Map getVariants() {
29 | return variants;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/datagen/ProjectileSpecDatastore.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.datagen;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import com.fs.starfarer.api.SettingsAPI;
5 | import com.fs.starfarer.api.loading.MissileSpecAPI;
6 | import com.fs.starfarer.api.loading.ProjectileSpecAPI;
7 | import com.fs.starfarer.api.loading.WeaponSpecAPI;
8 | import data.scripts.plugins.MPPlugin;
9 | import org.json.JSONArray;
10 | import org.json.JSONException;
11 | import org.json.JSONObject;
12 |
13 | import java.io.IOException;
14 | import java.util.ArrayList;
15 | import java.util.HashMap;
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | public class ProjectileSpecDatastore implements BaseDatagen {
20 |
21 | // private final Map weapons = new HashMap<>();
22 | private final Map missiles = new HashMap<>();
23 | private final Map projectiles = new HashMap<>();
24 | private final Map weaponIDs = new HashMap<>();
25 | private final Map weaponIDKeys = new HashMap<>();
26 | private final Map projectileIDs = new HashMap<>();
27 | private final Map projectileIDKeys = new HashMap<>();
28 | private final Map weaponSpawnIDs = new HashMap<>();
29 |
30 | /**
31 | * Collate weapon and projectile specs
32 | */
33 | public void generate(MPPlugin plugin) {
34 | List weaponIDs = new ArrayList<>(); // obf found in StarfarerSettings.getAllWeaponSpecs();
35 | List projectileIDs = new ArrayList<>();
36 | for (WeaponSpecAPI spec : Global.getSettings().getAllWeaponSpecs()) {
37 | weaponIDs.add(spec.getWeaponId());
38 | Object projSpec = spec.getProjectileSpec();
39 | if (projSpec instanceof ProjectileSpecAPI){
40 | projectileIDs.add(((ProjectileSpecAPI) projSpec).getId());
41 | } else if (projSpec instanceof MissileSpecAPI) {
42 | projectileIDs.add(((MissileSpecAPI) projSpec).getHullSpec().getHullId());
43 | }
44 | }
45 | for (WeaponSpecAPI spec : Global.getSettings().getSystemWeaponSpecs()) {
46 | weaponIDs.add(spec.getWeaponId());
47 | }
48 |
49 | short index = 0;
50 | for (String id : weaponIDs) {
51 | this.weaponIDs.put(id, index);
52 | this.weaponIDKeys.put(index, id);
53 | index++;
54 | }
55 |
56 | // educated guess based on weaponIDs
57 |
58 | index = 0;
59 | for (String id : projectileIDs) {
60 | this.projectileIDs.put(id, index);
61 | this.projectileIDKeys.put(index, id);
62 | index++;
63 | }
64 |
65 | for (String id : weaponIDs) {
66 | WeaponSpecAPI spec = Global.getSettings().getWeaponSpec(id);
67 | Object o = spec.getProjectileSpec();
68 |
69 | if (o instanceof MissileSpecAPI) {
70 | MissileSpecAPI m = (MissileSpecAPI) o;
71 |
72 | // try {
73 | // String mirvProjectile = m.getBehaviorJSON().getString("projectileSpec");
74 | // float f = 0f;
75 | // } catch (Exception e) {
76 | //
77 | // }
78 |
79 | missiles.put(m.getHullSpec().getBaseHullId(), m);
80 | } else if (o instanceof ProjectileSpecAPI) {
81 | ProjectileSpecAPI s = (ProjectileSpecAPI) o;
82 | projectiles.put(s.getId(), s);
83 | } else if (o == null) { // beam
84 | }
85 | }
86 |
87 | SettingsAPI settings = Global.getSettings();
88 | try {
89 | JSONArray data = settings.getMergedSpreadsheetDataForMod("projectileID","data/config/mp/proj_spawns.csv", "multiplayer");
90 |
91 | for (int i = 0; i < data.length(); i++) {
92 | JSONObject row = data.getJSONObject(i);
93 | String projectileID = row.getString("projectileID");
94 | String weaponID = row.getString("weaponID");
95 |
96 | weaponSpawnIDs.put(projectileID, weaponID);
97 | }
98 | } catch (IOException | JSONException e) {
99 | throw new RuntimeException(e);
100 | }
101 | }
102 |
103 | public Map getWeaponIDs() {
104 | return weaponIDs;
105 | }
106 |
107 | public Map getWeaponIDKeys() {
108 | return weaponIDKeys;
109 | }
110 |
111 | public Map getProjectileIDs() {
112 | return projectileIDs;
113 | }
114 |
115 | public Map getProjectileIDKeys() {
116 | return projectileIDKeys;
117 | }
118 |
119 | public Map getMissiles() {
120 | return missiles;
121 | }
122 |
123 | public Map getProjectiles() {
124 | return projectiles;
125 | }
126 |
127 | public Map getWeaponSpawnIDs() {
128 | return weaponSpawnIDs;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/datagen/ShipVariantDatastore.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.datagen;
2 |
3 | import com.fs.starfarer.api.Global;
4 | import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
5 | import com.fs.starfarer.api.fleet.FleetMemberAPI;
6 | import data.scripts.net.data.packables.entities.ships.VariantData;
7 | import data.scripts.plugins.MPPlugin;
8 |
9 | import java.util.*;
10 |
11 | /**
12 | * Collect and package all data that needs to be transferred before remote combat simulation can begin on client
13 | * e.g. variants
14 | */
15 | public class ShipVariantDatastore implements BaseDatagen {
16 |
17 | private final Map generated = new HashMap<>();
18 | private short index = 0;
19 |
20 | /**
21 | * Collects data that needs to be loaded on client side before combat entities can be updated or spawned
22 | */
23 | public void generate(MPPlugin plugin) {
24 | List members = new ArrayList<>();
25 |
26 | CombatFleetManagerAPI manager0 = Global.getCombatEngine().getFleetManager(0);
27 | members.addAll(manager0.getDeployedCopy());
28 | members.addAll(manager0.getReservesCopy());
29 |
30 | CombatFleetManagerAPI manager1 = Global.getCombatEngine().getFleetManager(1);
31 | members.addAll(manager1.getDeployedCopy());
32 | members.addAll(manager1.getReservesCopy());
33 |
34 | for (FleetMemberAPI member : members) {
35 | generated.put(member.getId(), initData(member));
36 | }
37 | }
38 |
39 | public Map getGenerated() {
40 | return generated;
41 | }
42 |
43 | public void checkVariantUpdate() {
44 | Set keys = new HashSet<>(generated.keySet());
45 |
46 | List members = new ArrayList<>();
47 |
48 | CombatFleetManagerAPI manager0 = Global.getCombatEngine().getFleetManager(0);
49 | members.addAll(manager0.getDeployedCopy());
50 | members.addAll(manager0.getReservesCopy());
51 |
52 | CombatFleetManagerAPI manager1 = Global.getCombatEngine().getFleetManager(1);
53 | members.addAll(manager1.getDeployedCopy());
54 | members.addAll(manager1.getReservesCopy());
55 |
56 | for (FleetMemberAPI member : members) {
57 | if (!keys.remove(member.getId())) {
58 | generated.put(member.getId(), initData(member));
59 | }
60 | }
61 | }
62 |
63 | private VariantData initData(FleetMemberAPI member) {
64 | index++;
65 | return new VariantData(index, member.getVariant(), member.getId());
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/DestExecute.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | public interface DestExecute {
4 | void execute(T value, EntityData packable);
5 | }
6 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/EntityData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | import data.scripts.net.data.InstanceData;
4 | import data.scripts.net.data.records.DataRecord;
5 | import data.scripts.net.data.tables.BaseEntityManager;
6 | import data.scripts.net.data.tables.InboundEntityManager;
7 | import data.scripts.plugins.MPPlugin;
8 |
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Map;
13 |
14 | /**
15 | * Used to read/write data
16 | */
17 | public abstract class EntityData {
18 |
19 | protected short instanceID;
20 | protected final List> records;
21 | protected final List> interpolate;
22 | private boolean flush = true;
23 |
24 | public EntityData() {
25 | this((short) -1);
26 | }
27 |
28 | public EntityData(short instanceID) {
29 | this.instanceID = instanceID;
30 |
31 | records = new ArrayList<>();
32 | interpolate = new ArrayList<>();
33 | }
34 |
35 | public short getInstanceID() {
36 | return instanceID;
37 | }
38 |
39 | /**
40 | * Immutable ID type to identify and construct entity when decoding packet
41 | * @return id
42 | */
43 | public abstract byte getTypeID();
44 |
45 | protected void addRecord(RecordLambda> record) {
46 | records.add(record);
47 | }
48 |
49 | protected void addInterpRecord(InterpRecordLambda> recordLambda) {
50 | addRecord(recordLambda);
51 | interpolate.add(recordLambda);
52 | }
53 |
54 | public List> getRecords() {
55 | return records;
56 | }
57 |
58 | /**
59 | * Returns a map of all records that are marked as updated since the last time
60 | * @return deltas
61 | */
62 | public InstanceData sourceExecute(float amount) {
63 | Map> deltas = new HashMap<>();
64 | int size = 0;
65 |
66 | for (byte i = 0; i < records.size(); i++) {
67 | RecordLambda> recordLambda = records.get(i);
68 |
69 | if (recordLambda.sourceExecute(amount) || flush) {
70 | deltas.put(i, recordLambda.record);
71 | size += recordLambda.record.size();
72 | }
73 | }
74 |
75 | flush = false;
76 |
77 | return new InstanceData(size, deltas);
78 | }
79 |
80 | /**
81 | * Update stored data with changes from a delta at dest
82 | * @param deltas incoming deltas
83 | */
84 | public void destExecute(Map deltas, int tick) {
85 | for (byte k : deltas.keySet()) {
86 | RecordLambda> record = records.get(k);
87 | record.overwrite(tick, deltas.get(k));
88 | }
89 |
90 | for (RecordLambda> recordLambda : records) recordLambda.destExecute(this);
91 | }
92 |
93 | public void interp(float delay) {
94 | for (InterpRecordLambda> interpRecordLambda : interpolate) {
95 | interpRecordLambda.interp(delay, this);
96 | }
97 | }
98 |
99 | /**
100 | * Called every time an entity plugin updates on the game thread. May be called by either client or server
101 | */
102 | public abstract void update(float amount, BaseEntityManager manager, MPPlugin plugin);
103 |
104 | /**
105 | * Called when entity is initialised
106 | */
107 | public abstract void init(MPPlugin plugin, InboundEntityManager manager);
108 |
109 | /**
110 | * Called when entity is deleted
111 | */
112 | public abstract void delete();
113 |
114 | /**
115 | * Forces the next sourceExecute() call to return all records
116 | */
117 | public void flush() {
118 | flush = true;
119 | }
120 |
121 | public void setInstanceID(short instanceID) {
122 | this.instanceID = instanceID;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/InterpExecute.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | public interface InterpExecute {
4 |
5 | /**
6 | * Interpolate between values v1 and v2
7 | * @param progressive the progressive 0.0 .. 1.0
8 | * @param v1 the older value
9 | * @param v2 the newer value
10 | * @return interpolated value
11 | */
12 | T interpExecute(float progressive, T v1, T v2);
13 | }
14 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/InterpRecordLambda.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | import cmu.CMUtils;
4 | import data.scripts.net.data.records.DataRecord;
5 |
6 | import java.util.concurrent.TimeUnit;
7 |
8 | public class InterpRecordLambda extends RecordLambda {
9 |
10 | public static final boolean DEBUG_MODE = false;
11 |
12 | private InterpExecute interpExecute;
13 |
14 | private long timestamp;
15 | private float progressive; // 0.0 to 1.0
16 | private float gap;
17 | private T interpValue;
18 | private T v1;
19 | private T v2;
20 | private int tick;
21 |
22 | public InterpRecordLambda(final DataRecord record, SourceExecute sourceExecute, final DestExecute destExecute) {
23 | super(record, sourceExecute, destExecute);
24 |
25 | this.interpExecute = new DefaultLinterp();
26 |
27 | v1 = record.getValue();
28 | v2 = record.getValue();
29 | interpValue = record.getValue();
30 | timestamp = System.nanoTime();
31 | gap = 0f;
32 | progressive = 0f;
33 | tick = -1;
34 | }
35 |
36 | @Override
37 | public void overwrite(int tick, Object delta) {
38 | super.overwrite(tick, delta);
39 |
40 | if (tick > this.tick) {
41 | long n = System.nanoTime();
42 | long diff = n - timestamp;
43 | timestamp = n;
44 | long milli = TimeUnit.MILLISECONDS.convert(diff, TimeUnit.NANOSECONDS);
45 | gap = milli * 0.001f;
46 |
47 | v2 = v1;
48 | v1 = (T) delta;
49 |
50 | progressive = 0f;
51 | this.tick = tick;
52 | }
53 | }
54 |
55 | @Override
56 | public void destExecute(EntityData packable) {
57 |
58 | }
59 |
60 | public void interp(float amount, EntityData packable) {
61 | progressive += amount;
62 |
63 | float linterp = progressive / gap;
64 | linterp = Math.min(linterp, 1f);
65 | interpValue = interpExecute.interpExecute(linterp, v2, v1);
66 |
67 | destExecute.execute(interpValue, packable);
68 |
69 | if (DEBUG_MODE) {
70 | CMUtils.getGuiDebug().putText(
71 | InterpRecordLambda.class,
72 | "interp_" + this.hashCode(),
73 | record.getDebugText() + " gap:" + String.format("%.3f", gap) + " P: " + String.format("%.4f", progressive)
74 | );
75 | }
76 | }
77 |
78 | public class DefaultLinterp implements InterpExecute {
79 | @Override
80 | public T interpExecute(float progressive, T v1, T v2) {
81 | return record.linterp(progressive, v1, v2);
82 | }
83 | }
84 |
85 | public InterpRecordLambda setInterpExecute(InterpExecute interpExecute) {
86 | this.interpExecute = interpExecute;
87 | return this;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/RecordLambda.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | import com.fs.starfarer.api.util.IntervalUtil;
4 | import data.scripts.net.data.records.DataRecord;
5 |
6 | public class RecordLambda {
7 |
8 | public final DataRecord record;
9 | public final SourceExecute sourceExecute;
10 | public final DestExecute destExecute;
11 | private IntervalUtil interval = null;
12 |
13 | public RecordLambda(DataRecord record, SourceExecute sourceExecute, DestExecute destExecute) {
14 | this.record = record;
15 | this.sourceExecute = sourceExecute;
16 | this.destExecute = destExecute;
17 | }
18 |
19 | public boolean sourceExecute(float amount) {
20 | boolean update = record.sourceExecute(sourceExecute);
21 |
22 | if (interval == null) {
23 | return update;
24 | } else {
25 | interval.advance(amount);
26 |
27 | if (interval.intervalElapsed()) {
28 | return update;
29 | }
30 | }
31 |
32 | return false;
33 | }
34 |
35 | public void overwrite(int tick, Object delta) {
36 | record.overwrite(delta);
37 | }
38 |
39 | public void destExecute(EntityData packable) {
40 | destExecute.execute(record.getValue(), packable);
41 | }
42 |
43 | public RecordLambda setRate(float interval) {
44 | this.interval = new IntervalUtil(interval, interval);
45 | return this;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/SourceExecute.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables;
2 |
3 | public interface SourceExecute {
4 | T get();
5 | }
6 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/entities/ships/ShieldData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables.entities.ships;
2 |
3 | import com.fs.starfarer.api.combat.ShieldAPI;
4 | import com.fs.starfarer.api.combat.ShipAPI;
5 | import data.scripts.net.data.packables.*;
6 | import data.scripts.net.data.records.ByteRecord;
7 | import data.scripts.net.data.records.Float16Record;
8 | import data.scripts.net.data.tables.BaseEntityManager;
9 | import data.scripts.net.data.tables.InboundEntityManager;
10 | import data.scripts.net.data.tables.client.combat.entities.ships.ClientShipTable;
11 | import data.scripts.plugins.MPPlugin;
12 | import org.lazywizard.lazylib.MathUtils;
13 |
14 | public class ShieldData extends EntityData {
15 |
16 | public static byte TYPE_ID;
17 |
18 | private final short instanceID;
19 | private final ShipAPI ship;
20 |
21 | private ShieldAPI shield;
22 |
23 | /**
24 | * Shield must be passed in constructor
25 | */
26 | public ShieldData(short instanceID, final ShieldAPI shield, final ShipAPI ship) {
27 | super(instanceID);
28 | this.instanceID = instanceID;
29 | this.ship = ship;
30 |
31 | if (shield == null) throw new NullPointerException("Null shield object");
32 |
33 | addRecord(new RecordLambda<>(
34 | ByteRecord.getDefault().setDebugText("shield active"),
35 | new SourceExecute() {
36 | @Override
37 | public Byte get() {
38 | return shield.isOn() ? (byte) 1 : (byte) 0;
39 | }
40 | },
41 | new DestExecute() {
42 | @Override
43 | public void execute(Byte value, EntityData packable) {
44 | ShieldData shieldData = (ShieldData) packable;
45 | ShieldAPI shield = shieldData.getShield();
46 | if (shield != null) {
47 | if (value == (byte) 1) shield.toggleOn();
48 | else shield.toggleOff();
49 | }
50 | }
51 | }
52 | ));
53 | addInterpRecord(new InterpRecordLambda<>(
54 | Float16Record.getDefault().setDebugText("shield facing"),
55 | new SourceExecute() {
56 | @Override
57 | public Float get() {
58 | return shield.getFacing();
59 | }
60 | },
61 | new DestExecute() {
62 | @Override
63 | public void execute(Float value, EntityData packable) {
64 | ShieldData shieldData = (ShieldData) packable;
65 | ShieldAPI shield = shieldData.getShield();
66 | if (shield != null && shield.isOn()) {
67 | shield.forceFacing(value);
68 | }
69 | }
70 | }
71 | ).setInterpExecute(new InterpExecute() {
72 | @Override
73 | public Float interpExecute(float progressive, Float v1, Float v2) {
74 | return v1 + (progressive * MathUtils.getShortestRotation(v1, v2));
75 | }
76 | }));
77 | addInterpRecord(new InterpRecordLambda<>(
78 | Float16Record.getDefault().setDebugText("shield arc"),
79 | new SourceExecute() {
80 | @Override
81 | public Float get() {
82 | return shield.getActiveArc();
83 | }
84 | },
85 | new DestExecute() {
86 | @Override
87 | public void execute(Float value, EntityData packable) {
88 | ShieldData shieldData = (ShieldData) packable;
89 | ShieldAPI shield = shieldData.getShield();
90 | if (shield != null && shield.isOn()) {
91 | shield.setActiveArc(value);
92 | }
93 | }
94 | }
95 | ).setInterpExecute(new InterpExecute() {
96 | @Override
97 | public Float interpExecute(float progressive, Float v1, Float v2) {
98 | return v1 + (progressive * MathUtils.getShortestRotation(v1, v2));
99 | }
100 | }));
101 | }
102 |
103 | @Override
104 | public byte getTypeID() {
105 | return TYPE_ID;
106 | }
107 |
108 | @Override
109 | public void update(float amount, BaseEntityManager manager, MPPlugin plugin) {
110 | if (plugin.getType() == MPPlugin.PluginType.CLIENT) {
111 | if (shield == null) {
112 | ClientShipTable clientShipTable = (ClientShipTable) manager;
113 |
114 | setShield(clientShipTable.getShipTable().array()[instanceID].getShip().getShield());
115 | }
116 | }
117 | }
118 |
119 | @Override
120 | public void init(MPPlugin plugin, InboundEntityManager manager) {
121 |
122 | }
123 |
124 | @Override
125 | public void delete() {
126 |
127 | }
128 |
129 | public ShieldAPI getShield() {
130 | return shield;
131 | }
132 |
133 | public void setShield(ShieldAPI shield) {
134 | this.shield = shield;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/metadata/ChatListenData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables.metadata;
2 |
3 | import data.scripts.net.data.packables.DestExecute;
4 | import data.scripts.net.data.packables.EntityData;
5 | import data.scripts.net.data.packables.RecordLambda;
6 | import data.scripts.net.data.packables.SourceExecute;
7 | import data.scripts.net.data.records.ByteRecord;
8 | import data.scripts.net.data.records.collections.ListenArrayRecord;
9 | import data.scripts.net.data.tables.BaseEntityManager;
10 | import data.scripts.net.data.tables.InboundEntityManager;
11 | import data.scripts.plugins.MPPlugin;
12 | import data.scripts.plugins.gui.MPChatboxPlugin;
13 |
14 | import java.nio.charset.StandardCharsets;
15 | import java.util.ArrayList;
16 | import java.util.Iterator;
17 | import java.util.List;
18 |
19 | /**
20 | * Facilitates one-way chat text
21 | */
22 | public class ChatListenData extends EntityData {
23 |
24 | public static byte TYPE_ID;
25 |
26 | private final List toWrite = new ArrayList<>();
27 | private final List received = new ArrayList<>();
28 |
29 | public ChatListenData(short instanceID) {
30 | super(instanceID);
31 |
32 | addRecord(new RecordLambda<>(
33 | new ListenArrayRecord<>(new ArrayList(), ByteRecord.TYPE_ID).setDebugText("chat strings"),
34 | new SourceExecute>() {
35 | @Override
36 | public List get() {
37 | List out = new ArrayList<>();
38 |
39 | for (MPChatboxPlugin.ChatEntry entry : toWrite) {
40 | out.add(entry.connectionID);
41 |
42 | byte[] s = entry.text.getBytes(StandardCharsets.UTF_8);
43 | byte l = (byte) (s.length & 0xFF);
44 | out.add(l);
45 |
46 | for (int i = 0; i < Math.min(s.length, 255); i++) {
47 | out.add(s[i]);
48 | }
49 | }
50 |
51 | toWrite.clear();
52 |
53 | return out;
54 | }
55 | },
56 | new DestExecute>() {
57 | @Override
58 | public void execute(List value, EntityData packable) {
59 | for (Iterator iterator = value.iterator(); iterator.hasNext(); ) {
60 | byte id = iterator.next();
61 | byte l = iterator.next();
62 | byte[] s = new byte[l];
63 | for (int i = 0; i < l; i++) {
64 | s[i] = iterator.next();
65 | }
66 |
67 | String text = new String(s, StandardCharsets.UTF_8);
68 |
69 | received.add(new MPChatboxPlugin.ChatEntry(text, "unknown", id));
70 | }
71 | }
72 | }
73 | ));
74 | }
75 |
76 | @Override
77 | public void init(MPPlugin plugin, InboundEntityManager manager) {
78 |
79 | }
80 |
81 | @Override
82 | public void update(float amount, BaseEntityManager manager, MPPlugin plugin) {
83 |
84 | }
85 |
86 | @Override
87 | public void delete() {
88 |
89 | }
90 |
91 | public void submitChatEntry(MPChatboxPlugin.ChatEntry entry) {
92 | toWrite.add(entry);
93 | }
94 |
95 | public List getReceived() {
96 | if (received.isEmpty()) {
97 | return new ArrayList<>();
98 | }
99 | List out = new ArrayList<>(received);
100 | received.clear();
101 | return out;
102 | }
103 |
104 | @Override
105 | public byte getTypeID() {
106 | return TYPE_ID;
107 | }
108 |
109 | public static void setTypeId(byte typeId) {
110 | TYPE_ID = typeId;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/metadata/ServerConnectionData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables.metadata;
2 |
3 | import data.scripts.net.data.packables.DestExecute;
4 | import data.scripts.net.data.packables.EntityData;
5 | import data.scripts.net.data.packables.RecordLambda;
6 | import data.scripts.net.data.packables.SourceExecute;
7 | import data.scripts.net.data.records.ByteRecord;
8 | import data.scripts.net.data.tables.BaseEntityManager;
9 | import data.scripts.net.data.tables.InboundEntityManager;
10 | import data.scripts.net.io.BaseConnectionWrapper;
11 | import data.scripts.plugins.MPPlugin;
12 |
13 | public class ServerConnectionData extends EntityData {
14 |
15 | public static byte TYPE_ID;
16 |
17 | private byte connectionState;
18 | private byte connectionID;
19 | private long timestamp;
20 | private long latency;
21 |
22 | public ServerConnectionData(short instanceID, final byte connectionID, final BaseConnectionWrapper connection) {
23 | super(instanceID);
24 |
25 | addRecord(new RecordLambda<>(
26 | ByteRecord.getDefault().setDebugText("connection state"),
27 | new SourceExecute() {
28 | @Override
29 | public Byte get() {
30 | return (byte) connection.getConnectionState().ordinal();
31 | }
32 | },
33 | new DestExecute() {
34 | @Override
35 | public void execute(Byte value, EntityData packable) {
36 | ServerConnectionData serverConnectionData = (ServerConnectionData) packable;
37 | serverConnectionData.setConnectionState(value);
38 | }
39 | }
40 | ));
41 | addRecord(new RecordLambda<>(
42 | ByteRecord.getDefault().setDebugText("connection id"),
43 | new SourceExecute() {
44 | @Override
45 | public Byte get() {
46 | return connectionID;
47 | }
48 | },
49 | new DestExecute() {
50 | @Override
51 | public void execute(Byte value, EntityData packable) {
52 | ServerConnectionData serverConnectionData = (ServerConnectionData) packable;
53 | serverConnectionData.setConnectionID(value);
54 | }
55 | }
56 | ));
57 | addRecord(new RecordLambda<>(
58 | ByteRecord.getDefault().setDebugText("server flag"),
59 | new SourceExecute() {
60 | @Override
61 | public Byte get() {
62 | if (connection.sReceive == 0) { // this is very much a hack but it works
63 | latency = System.currentTimeMillis() - timestamp;
64 | connection.sReceive = 1;
65 |
66 | timestamp = System.currentTimeMillis();
67 | return (byte) 1;
68 | }
69 |
70 | return (byte) 0;
71 | }
72 | },
73 | new DestExecute() {
74 | @Override
75 | public void execute(Byte value, EntityData packable) {
76 | connection.sListen = value;
77 | }
78 | }
79 | ));
80 | addRecord(new RecordLambda<>(
81 | ByteRecord.getDefault().setDebugText("client listen"),
82 | new SourceExecute() {
83 | @Override
84 | public java.lang.Byte get() {
85 | return connection.cListen;
86 | }
87 | },
88 | new DestExecute() {
89 | @Override
90 | public void execute(Byte value, EntityData packable) {
91 | connection.cReceive = value;
92 | }
93 | }
94 | ));
95 | }
96 |
97 | @Override
98 | public void init(MPPlugin plugin, InboundEntityManager manager) {
99 |
100 | }
101 |
102 | @Override
103 | public void update(float amount, BaseEntityManager manager, MPPlugin plugin) {
104 |
105 | }
106 |
107 | @Override
108 | public void delete() {
109 |
110 | }
111 |
112 | @Override
113 | public byte getTypeID() {
114 | return TYPE_ID;
115 | }
116 |
117 | public byte getConnectionState() {
118 | return connectionState;
119 | }
120 |
121 | public void setConnectionState(byte connectionState) {
122 | this.connectionState = connectionState;
123 | }
124 |
125 | public void setConnectionID(byte connectionID) {
126 | this.connectionID = connectionID;
127 | }
128 |
129 | public byte getConnectionID() {
130 | return connectionID;
131 | }
132 |
133 | public long getLatency() {
134 | return latency;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/packables/metadata/ServerPlayerData.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.packables.metadata;
2 |
3 | import data.scripts.net.data.packables.DestExecute;
4 | import data.scripts.net.data.packables.EntityData;
5 | import data.scripts.net.data.packables.RecordLambda;
6 | import data.scripts.net.data.packables.SourceExecute;
7 | import data.scripts.net.data.records.ShortRecord;
8 | import data.scripts.net.data.tables.BaseEntityManager;
9 | import data.scripts.net.data.tables.InboundEntityManager;
10 | import data.scripts.plugins.MPPlugin;
11 |
12 | public class ServerPlayerData extends EntityData {
13 |
14 | public static byte TYPE_ID;
15 |
16 | private short activeID;
17 | private short hostID;
18 |
19 | public ServerPlayerData(short instanceID) {
20 | super(instanceID);
21 |
22 | addRecord(new RecordLambda<>(
23 | ShortRecord.getDefault().setDebugText("active ship id"),
24 | new SourceExecute() {
25 | @Override
26 | public Short get() {
27 | return activeID;
28 | }
29 | },
30 | new DestExecute() {
31 | @Override
32 | public void execute(Short value, EntityData packable) {
33 | setActiveID(value);
34 | }
35 | }
36 | ));
37 | addRecord(new RecordLambda<>(
38 | ShortRecord.getDefault().setDebugText("host ship id"),
39 | new SourceExecute() {
40 | @Override
41 | public Short get() {
42 | return hostID;
43 | }
44 | },
45 | new DestExecute() {
46 | @Override
47 | public void execute(Short value, EntityData packable) {
48 | setHostID(value);
49 | }
50 | }
51 | ));
52 | }
53 |
54 | @Override
55 | public byte getTypeID() {
56 | return TYPE_ID;
57 | }
58 |
59 | @Override
60 | public void update(float amount, BaseEntityManager manager, MPPlugin plugin) {
61 |
62 | }
63 |
64 | @Override
65 | public void init(MPPlugin plugin, InboundEntityManager manager) {
66 |
67 | }
68 |
69 | @Override
70 | public void delete() {
71 |
72 | }
73 |
74 | public short getActiveID() {
75 | return activeID;
76 | }
77 |
78 | public void setActiveID(short activeID) {
79 | this.activeID = activeID;
80 | }
81 |
82 | public short getHostID() {
83 | return hostID;
84 | }
85 |
86 | public void setHostID(short hostID) {
87 | this.hostID = hostID;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/plugins/ClientScript.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.plugins;
2 |
3 | /**
4 | * General purpose one-way script for sending/receiving arbitrary data
5 | */
6 | public abstract class ClientScript {
7 |
8 | static short SCRIPT_ID = -1;
9 |
10 | /**
11 | * Called on SERVER
12 | * @param amount delta time
13 | */
14 | abstract void advance(float amount);
15 |
16 | /**
17 | * Called on CLIENT
18 | * @param amount delta time
19 | */
20 | abstract void execute(float amount);
21 |
22 | static
23 |
24 | short getID() {
25 | return SCRIPT_ID;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/plugins/DEMPlugin.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.plugins;
2 |
3 | public class DEMPlugin {
4 |
5 |
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/plugins/ServerScript.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.plugins;
2 |
3 | /**
4 | * General purpose one-way script for sending/receiving arbitrary data
5 | */
6 | public abstract class ServerScript {
7 |
8 | static short SCRIPT_ID = -1;
9 |
10 | /**
11 | * Called on SERVER
12 | * @param amount delta time
13 | */
14 | abstract void advance(float amount);
15 |
16 | /**
17 | * Called on CLIENT
18 | * @param amount delta time
19 | */
20 | abstract void execute(float amount);
21 |
22 | static
23 |
24 | short getID() {
25 | return SCRIPT_ID;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/ByteRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class ByteRecord extends DataRecord {
6 |
7 | public static byte TYPE_ID;
8 |
9 | public ByteRecord(byte record) {
10 | super(record);
11 | }
12 |
13 | @Override
14 | public void write(ByteBuf dest) {
15 | dest.writeByte(value);
16 | }
17 |
18 | @Override
19 | public Byte read(ByteBuf in) {
20 | return in.readByte();
21 | }
22 |
23 | @Override
24 | public Byte linterp(float p, Byte v1, Byte v2) {
25 | int i1 = v1 & 0xFF;
26 | int i2 = v2 & 0xFF;
27 | int d = (i2 - i1);
28 | d += 255;
29 | return (byte) (Math.round(d * p) + i1 - 255);
30 | }
31 |
32 | @Override
33 | public boolean checkUpdate(Byte delta) {
34 | return (byte) value != delta;
35 | }
36 |
37 | public static ByteRecord getDefault() {
38 | return new ByteRecord((byte) 0);
39 | }
40 |
41 | public static void setTypeId(byte typeId) {
42 | ByteRecord.TYPE_ID = typeId;
43 | }
44 |
45 | @Override
46 | public byte getTypeId() {
47 | return TYPE_ID;
48 | }
49 |
50 | @Override
51 | public int size() {
52 | return 1;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/ConversionUtils.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | public class ConversionUtils {
4 |
5 | public static byte floatToByte(float value, float range) {
6 | return (byte) (value * 255f / range);
7 | }
8 |
9 | public static float byteToFloat(byte value, float range) {
10 | return (value & 0xFF) / 255f * range;
11 | }
12 |
13 | // https://jvm-gaming.org/t/16-bit-float-conversion-java-code/55621/2
14 | public static short toHalfFloat(final float v) {
15 | //if(Float.isNaN(v)) throw new UnsupportedOperationException("NaN to half conversion not supported!");
16 | if(v == Float.POSITIVE_INFINITY) return(short)0x7c00;
17 | if(v == Float.NEGATIVE_INFINITY) return(short)0xfc00;
18 | if(v == 0.0f) return(short)0x0000;
19 | if(v == -0.0f) return(short)0x8000;
20 | if(v > 65504.0f) return 0x7bff; // max value supported by half float
21 | if(v < -65504.0f) return(short)( 0x7bff | 0x8000 );
22 | if(v > 0.0f && v < 5.96046E-8f) return 0x0001;
23 | if(v < 0.0f && v > -5.96046E-8f) return(short)0x8001;
24 |
25 | final int f = Float.floatToIntBits(v);
26 |
27 | return(short)((( f>>16 ) & 0x8000 ) | (((( f & 0x7f800000 ) - 0x38000000 )>>13 ) & 0x7c00 ) | (( f>>13 ) & 0x03ff ));
28 | }
29 |
30 | public static float toFloat(final short half) {
31 | switch((int)half)
32 | {
33 | case 0x0000 :
34 | return 0.0f;
35 | case 0x7c00 :
36 | return Float.POSITIVE_INFINITY;
37 | default :
38 | return Float.intBitsToFloat((( half & 0x8000 )<<16 ) | ((( half & 0x7c00 ) + 0x1C000 )<<13 ) | (( half & 0x03FF )<<13 ));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/DataRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import data.scripts.net.data.packables.SourceExecute;
4 | import io.netty.buffer.ByteBuf;
5 |
6 | public abstract class DataRecord {
7 | protected T value;
8 | private String debug = "default record description";
9 |
10 | public DataRecord(T value) {
11 | this.value = value;
12 | }
13 |
14 | /**
15 | * Executes the source update lambda
16 | * @param sourceExecute the lambda script
17 | * @return true if the data has updated
18 | */
19 | public boolean sourceExecute(SourceExecute sourceExecute) {
20 | T t = sourceExecute.get();
21 | boolean isUpdated;
22 | try {
23 | isUpdated = checkUpdate(t);
24 | } catch (NullPointerException n) {
25 | throw new NullPointerException("Null value in record delta check: " + debug);
26 | }
27 |
28 | if (isUpdated) {
29 | value = t;
30 | }
31 |
32 | return isUpdated;
33 | }
34 |
35 | /**
36 | * Get raw data without writing IDs
37 | * @param dest buffer to write to
38 | */
39 | public abstract void write(ByteBuf dest);
40 |
41 | public abstract T read(ByteBuf in);
42 |
43 | public T linterp(float p, T v1, T v2) {
44 | return value;
45 | }
46 |
47 | public abstract byte getTypeId();
48 |
49 | public abstract int size();
50 |
51 | /**
52 | * Return true if updated
53 | * @param delta incoming delta
54 | * @return result
55 | */
56 | protected abstract boolean checkUpdate(T delta);
57 |
58 | public T getValue() {
59 | return value;
60 | }
61 |
62 | /**
63 | * Overwrite the stored record with new data
64 | * @param delta incoming delta
65 | */
66 | public void overwrite(Object delta) {
67 | value = (T) delta;
68 | }
69 |
70 | public DataRecord setDebugText(String debug) {
71 | this.debug = debug;
72 | return this;
73 | }
74 |
75 | public String getDebugText() {
76 | return debug;
77 | }
78 |
79 | @Override
80 | public String toString() {
81 | return "value=" + value +
82 | ", debug='" + debug + '\'' +
83 | '}';
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/Float16Record.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | /**
6 | * 16 bit float
7 | */
8 | public class Float16Record extends DataRecord {
9 |
10 | public static byte TYPE_ID;
11 |
12 | public Float16Record(float record) {
13 | super(record);
14 | }
15 |
16 | @Override
17 | public void write(ByteBuf dest) {
18 | dest.writeShort(ConversionUtils.toHalfFloat(value));
19 | }
20 |
21 | @Override
22 | public Float read(ByteBuf in) {
23 | short value = in.readShort();
24 | return ConversionUtils.toFloat(value);
25 | }
26 |
27 | @Override
28 | public Float linterp(float p, Float v1, Float v2) {
29 | return (p * (v2 - v1)) + v1;
30 | }
31 |
32 | @Override
33 | protected boolean checkUpdate(Float delta) {
34 | return !value.equals(delta);
35 | }
36 |
37 | public static DataRecord getDefault() {
38 | return new Float16Record(0f);
39 | }
40 |
41 | public static void setTypeId(byte typeId) {
42 | Float16Record.TYPE_ID = typeId;
43 | }
44 |
45 | @Override
46 | public byte getTypeId() {
47 | return TYPE_ID;
48 | }
49 |
50 | @Override
51 | public int size() {
52 | return 2;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/Float32Record.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | import java.util.Objects;
6 |
7 | public class Float32Record extends DataRecord {
8 | public static byte TYPE_ID;
9 |
10 | public Float32Record(Float record) {
11 | super(record);
12 | }
13 |
14 | @Override
15 | protected boolean checkUpdate(Float delta) {
16 | return !Objects.equals(value, delta);
17 | }
18 |
19 | @Override
20 | public void write(ByteBuf dest) {
21 | dest.writeFloat(value);
22 | }
23 |
24 | @Override
25 | public Float read(ByteBuf in) {
26 | return in.readFloat();
27 | }
28 |
29 | @Override
30 | public Float linterp(float p, Float v1, Float v2) {
31 | return (p * (v2 - v1)) + v1;
32 | }
33 |
34 | public static void setTypeId(byte typeId) {
35 | Float32Record.TYPE_ID = typeId;
36 | }
37 |
38 | @Override
39 | public byte getTypeId() {
40 | return TYPE_ID;
41 | }
42 |
43 | public static DataRecord getDefault() {
44 | return new Float32Record(0f);
45 | }
46 |
47 | @Override
48 | public int size() {
49 | return 4;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/IntRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class IntRecord extends DataRecord {
6 | public static byte TYPE_ID;
7 |
8 | public IntRecord(Integer record) {
9 | super(record);
10 | }
11 |
12 | @Override
13 | protected boolean checkUpdate(Integer delta) {
14 | return value != (int) delta;
15 | }
16 |
17 | @Override
18 | public void write(ByteBuf dest) {
19 | dest.writeInt(value);
20 | }
21 |
22 | @Override
23 | public Integer read(ByteBuf in) {
24 | return in.readInt();
25 | }
26 |
27 | @Override
28 | public Integer linterp(float p, Integer v1, Integer v2) {
29 | return (int) ((v2 - v1) * p) + v1;
30 | }
31 |
32 | public static void setTypeId(byte typeId) {
33 | IntRecord.TYPE_ID = typeId;
34 | }
35 |
36 | @Override
37 | public byte getTypeId() {
38 | return TYPE_ID;
39 | }
40 |
41 | public static IntRecord getDefault() {
42 | return new IntRecord(0);
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "IntRecord{" +
48 | "record=" + value +
49 | '}';
50 | }
51 |
52 | @Override
53 | public int size() {
54 | return 4;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/ShortRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class ShortRecord extends DataRecord {
6 | public static byte TYPE_ID;
7 |
8 | public ShortRecord(Short record) {
9 | super(record);
10 | }
11 |
12 | @Override
13 | public boolean checkUpdate(Short delta) {
14 | return value != (short) delta;
15 | }
16 |
17 | @Override
18 | public void write(ByteBuf dest) {
19 | dest.writeShort(value);
20 | }
21 |
22 | @Override
23 | public Short read(ByteBuf in) {
24 | return in.readShort();
25 | }
26 |
27 | @Override
28 | public Short linterp(float p, Short v1, Short v2) {
29 | return (short) ((p * (v2 - v1)) + v1);
30 | }
31 |
32 | public static void setTypeId(byte typeId) {
33 | ShortRecord.TYPE_ID = typeId;
34 | }
35 |
36 | @Override
37 | public byte getTypeId() {
38 | return TYPE_ID;
39 | }
40 |
41 | public static ShortRecord getDefault() {
42 | return new ShortRecord((short) 0);
43 | }
44 |
45 | @Override
46 | public int size() {
47 | return 2;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/StringRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | import java.nio.charset.Charset;
6 | import java.nio.charset.StandardCharsets;
7 |
8 | public class StringRecord extends DataRecord {
9 | public static byte TYPE_ID;
10 |
11 | public static final String NULL = "NULL";
12 |
13 | private static final Charset CHARSET = StandardCharsets.UTF_8;
14 |
15 | public StringRecord(String value) {
16 | super(value);
17 | }
18 |
19 | @Override
20 | public void write(ByteBuf dest) {
21 | byte[] bytes = value == null ? NULL.getBytes(CHARSET) : value.getBytes(CHARSET);
22 |
23 | if (bytes.length > Byte.MAX_VALUE) {
24 | byte[] b = new byte[Byte.MAX_VALUE];
25 | System.arraycopy(bytes, 0, b, 0, b.length);
26 | bytes = b;
27 | }
28 |
29 | dest.writeByte(bytes.length);
30 | dest.writeBytes(bytes);
31 | }
32 |
33 | @Override
34 | public String read(ByteBuf in) {
35 | int length = in.readByte();
36 | String value = in.readCharSequence(length, CHARSET).toString();
37 | if (value.equals("NONE")) value = null;
38 |
39 | return value;
40 | }
41 |
42 | @Override
43 | public boolean checkUpdate(String delta) {
44 | return value != null && !value.equals(delta);
45 | }
46 |
47 | public static void setTypeId(byte typeId) {
48 | StringRecord.TYPE_ID = typeId;
49 | }
50 |
51 | @Override
52 | public byte getTypeId() {
53 | return TYPE_ID;
54 | }
55 |
56 | public static StringRecord getDefault() {
57 | return new StringRecord("DEFAULT");
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return "StringRecord{" +
63 | "record='" + value + '\'' +
64 | '}';
65 | }
66 |
67 | @Override
68 | public synchronized int size() {
69 | if (value == null) return 1 + NULL.getBytes(CHARSET).length;
70 | return 1 + value.getBytes(CHARSET).length;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/Vector2f16Record.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import org.lwjgl.util.vector.Vector2f;
5 |
6 | public class Vector2f16Record extends DataRecord {
7 | public static byte TYPE_ID;
8 |
9 | public Vector2f16Record(Vector2f record) {
10 | super(record);
11 | }
12 |
13 | @Override
14 | public boolean checkUpdate(Vector2f delta) {
15 | boolean isUpdated;
16 |
17 | isUpdated = (value.x != delta.x) || (value.y != delta.y);
18 |
19 | return isUpdated;
20 | }
21 |
22 | @Override
23 | public void write(ByteBuf dest) {
24 | dest.writeShort(ConversionUtils.toHalfFloat(value.x));
25 | dest.writeShort(ConversionUtils.toHalfFloat(value.y));
26 | }
27 |
28 | @Override
29 | public Vector2f read(ByteBuf in) {
30 | float x = ConversionUtils.toFloat(in.readShort());
31 | float y = ConversionUtils.toFloat(in.readShort());
32 | return new Vector2f(x, y);
33 | }
34 |
35 | @Override
36 | public Vector2f linterp(float p, Vector2f v1, Vector2f v2) {
37 | float x = (p * (v2.x - v1.x)) + v1.x;
38 | float y = (p * (v2.y - v1.y)) + v1.y;
39 | return new Vector2f(x, y);
40 | }
41 |
42 | public static void setTypeId(byte typeId) {
43 | Vector2f16Record.TYPE_ID = typeId;
44 | }
45 |
46 | @Override
47 | public byte getTypeId() {
48 | return TYPE_ID;
49 | }
50 |
51 | public static Vector2f16Record getDefault() {
52 | return new Vector2f16Record(new Vector2f(0f, 0f));
53 | }
54 |
55 | @Override
56 | public int size() {
57 | return 4;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/Vector2f32Record.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import org.lwjgl.util.vector.Vector2f;
5 |
6 | public class Vector2f32Record extends DataRecord {
7 | public static byte TYPE_ID;
8 |
9 | public Vector2f32Record(Vector2f record) {
10 | super(record);
11 | }
12 |
13 | @Override
14 | public boolean checkUpdate(Vector2f delta) {
15 | boolean isUpdated;
16 |
17 | isUpdated = (value.x != delta.x) || (value.y != delta.y);
18 |
19 | return isUpdated;
20 | }
21 |
22 | @Override
23 | public void write(ByteBuf dest) {
24 | dest.writeFloat(value.x);
25 | dest.writeFloat(value.y);
26 | }
27 |
28 | @Override
29 | public Vector2f read(ByteBuf in) {
30 | float x = in.readFloat();
31 | float y = in.readFloat();
32 | return new Vector2f(x, y);
33 | }
34 |
35 | @Override
36 | public Vector2f linterp(float p, Vector2f v1, Vector2f v2) {
37 | float x = (p * (v2.x - v1.x)) + v1.x;
38 | float y = (p * (v2.y - v1.y)) + v1.y;
39 | return new Vector2f(x, y);
40 | }
41 |
42 | public static void setTypeId(byte typeId) {
43 | Vector2f32Record.TYPE_ID = typeId;
44 | }
45 |
46 | @Override
47 | public byte getTypeId() {
48 | return TYPE_ID;
49 | }
50 |
51 | public static Vector2f32Record getDefault() {
52 | return new Vector2f32Record(new Vector2f(0f, 0f));
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return "Vector2fRecord{" +
58 | "record=" + value +
59 | '}';
60 | }
61 |
62 | @Override
63 | public int size() {
64 | return 8;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/Vector3f32Record.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import org.lwjgl.util.vector.Vector3f;
5 |
6 | public class Vector3f32Record extends DataRecord {
7 |
8 | public static byte TYPE_ID;
9 |
10 | public Vector3f32Record(Vector3f record) {
11 | super(record);
12 | }
13 |
14 | @Override
15 | public void write(ByteBuf dest) {
16 | dest.writeFloat(value.x);
17 | dest.writeFloat(value.y);
18 | dest.writeFloat(value.z);
19 | }
20 |
21 | @Override
22 | public Vector3f read(ByteBuf in) {
23 | float x = in.readFloat();
24 | float y = in.readFloat();
25 | float z = in.readFloat();
26 | return new Vector3f(x, y, z);
27 | }
28 |
29 | @Override
30 | public Vector3f linterp(float p, Vector3f v1, Vector3f v2) {
31 | float x = (p * (v2.x - v1.x)) + v1.x;
32 | float y = (p * (v2.y - v1.y)) + v1.y;
33 | float z = (p * (v2.z - v1.z)) + v1.z;
34 | return new Vector3f(x, y, z);
35 | }
36 |
37 | @Override
38 | public boolean checkUpdate(Vector3f delta) {
39 | boolean isUpdated;
40 |
41 | isUpdated = (value.x != delta.x) || (value.y != delta.y) || (value.z != delta.z);
42 |
43 | return isUpdated;
44 | }
45 |
46 | public static void setTypeId(byte typeId) {
47 | Vector3f32Record.TYPE_ID = typeId;
48 | }
49 |
50 | @Override
51 | public byte getTypeId() {
52 | return TYPE_ID;
53 | }
54 |
55 | public static Vector3f32Record getDefault() {
56 | return new Vector3f32Record(new Vector3f(0f, 0f, 0f));
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return "Vector3fRecord{" +
62 | "value=" + value +
63 | '}';
64 | }
65 |
66 | @Override
67 | public int size() {
68 | return 12;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/collections/ListenArrayRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records.collections;
2 |
3 | import data.scripts.net.data.records.DataRecord;
4 | import data.scripts.net.data.DataGenManager;
5 | import io.netty.buffer.ByteBuf;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | /**
11 | * Sends a one-way array of values. Useful for lists of data that don't need feedback.
12 | * @param Value type
13 | */
14 | public class ListenArrayRecord extends DataRecord> {
15 |
16 | public static byte TYPE_ID;
17 | private final byte elementTypeID;
18 |
19 | private final DataRecord writer;
20 |
21 | public ListenArrayRecord(List value, byte elementTypeID) {
22 | super(value);
23 |
24 | this.elementTypeID = elementTypeID;
25 |
26 | if (elementTypeID != (byte) -1) {
27 | writer = (DataRecord) DataGenManager.recordFactory(elementTypeID);
28 | } else {
29 | writer = null;
30 | }
31 | }
32 |
33 | @Override
34 | public void overwrite(Object delta) {
35 | super.overwrite(delta);
36 | }
37 |
38 | @Override
39 | public void write(ByteBuf dest) {
40 | if (value.size() > 0b11111111) {
41 | throw new RuntimeException("List size exceeded " + 0b11111111 + " elements");
42 | }
43 |
44 | dest.writeByte(elementTypeID);
45 | dest.writeByte(value.size());
46 |
47 | for (E e : value) {
48 | writer.overwrite(e);
49 | writer.write(dest);
50 | }
51 | }
52 |
53 | @Override
54 | public List read(ByteBuf in) {
55 | List out = new ArrayList<>();
56 |
57 | byte type = in.readByte();
58 | int num = in.readByte() & 0xFF;
59 |
60 | DataRecord reader = (DataRecord) DataGenManager.recordFactory(type);
61 |
62 | for (int i = 0; i < num; i++) {
63 | out.add(reader.read(in));
64 | }
65 |
66 | return out;
67 | }
68 |
69 | @Override
70 | public byte getTypeId() {
71 | return TYPE_ID;
72 | }
73 |
74 | @Override
75 | protected boolean checkUpdate(List delta) {
76 | return !delta.isEmpty();
77 | }
78 |
79 | public static void setTypeId(byte typeId) {
80 | ListenArrayRecord.TYPE_ID = typeId;
81 | }
82 |
83 | @Override
84 | public int size() {
85 | return 2 + (value.size() * writer.size());
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/collections/SyncingListRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records.collections;
2 |
3 | import data.scripts.net.data.packables.SourceExecute;
4 | import data.scripts.net.data.records.DataRecord;
5 | import data.scripts.net.data.DataGenManager;
6 | import io.netty.buffer.ByteBuf;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * Attempts to sync a List of values
15 | * broken pls fix
16 | * @param Value type
17 | */
18 | public class SyncingListRecord extends DataRecord> {
19 | public static byte TYPE_ID;
20 | private final byte elementTypeID;
21 |
22 | private final DataRecord writer;
23 |
24 | private final Map toWrite = new HashMap<>();
25 |
26 | public SyncingListRecord(List collection, byte elementTypeID) {
27 | super(collection);
28 | this.elementTypeID = elementTypeID;
29 |
30 | if (elementTypeID != (byte) -1) {
31 | writer = (DataRecord) DataGenManager.recordFactory(elementTypeID);
32 | } else {
33 | writer = null;
34 | }
35 | }
36 |
37 | @Override
38 | public boolean sourceExecute(SourceExecute> sourceExecute) {
39 | // List delta = sourceExecute.get();
40 | //
41 | // boolean update = false;
42 | //
43 | // for (byte i = 0; i < delta.size(); i++) {
44 | // E d = delta.get(i);
45 | //
46 | // if (i + 1 > value.size()) {
47 | // toWrite.put(i, d);
48 | // update = true;
49 | // } else if (!d.equals(value.get(i))) {
50 | // toWrite.put(i, d);
51 | // update = true;
52 | // }
53 | // }
54 | //
55 | // value = delta;
56 | //
57 | // return update;
58 | value = sourceExecute.get();
59 | return true;
60 | }
61 |
62 |
63 | @Override
64 | public void write(ByteBuf dest) {
65 | if (value.size() > Byte.MAX_VALUE) {
66 | throw new RuntimeException("List size exceeded " + Byte.MAX_VALUE + " elements");
67 | }
68 |
69 | // if (toWrite.size() == 0) return;
70 | //
71 | // dest.writeByte(elementTypeID);
72 | // dest.writeByte(toWrite.size());
73 | //
74 | // for (byte i : toWrite.keySet()) {
75 | // // write index
76 | // dest.writeByte(i);
77 | //
78 | // // write data
79 | // writer.overwrite(toWrite.get(i));
80 | // writer.write(dest);
81 | // }
82 | //
83 | // toWrite.clear();
84 |
85 | dest.writeByte(elementTypeID);
86 | dest.writeByte(value.size());
87 |
88 | for (byte i = 0; i < value.size(); i++) {
89 | E e = value.get(i);
90 |
91 | dest.writeByte(i);
92 |
93 | writer.overwrite(e);
94 | writer.write(dest);
95 | }
96 | }
97 |
98 | @Override
99 | public List read(ByteBuf in) {
100 | byte type = in.readByte();
101 | byte num = in.readByte();
102 |
103 | DataRecord reader = (DataRecord) DataGenManager.recordFactory(type);
104 |
105 | Map data = new HashMap<>();
106 | int max = 0;
107 | for (int i = 0; i < num; i++) {
108 | byte index = in.readByte();
109 |
110 | max = Math.max(index, max);
111 |
112 | E e = reader.read(in);
113 |
114 | data.put(index, e);
115 | }
116 | max++;
117 |
118 | List value = new ArrayList<>(max);
119 | for (int i = 0; i < max; i++) {
120 | value.add(null);
121 | }
122 |
123 | for (byte b : data.keySet()) {
124 | value.set(b, data.get(b));
125 | }
126 |
127 | return value;
128 | }
129 |
130 | @Override
131 | public void overwrite(Object o) {
132 | List delta = (List) o;
133 |
134 | List temp;
135 | int size = Math.max(delta.size(), value.size());
136 | temp = new ArrayList<>(size);
137 | for (int i = 0; i < size; i++) {
138 | temp.add(null);
139 | }
140 |
141 | for (int i = 0; i < size; i++) {
142 | E d = i < delta.size() ? delta.get(i) : null;
143 | E v = i < value.size() ? value.get(i) : null;
144 |
145 | if (d != null) {
146 | temp.set(i, d);
147 | } else if (v != null) {
148 | temp.set(i, v);
149 | }
150 | }
151 |
152 | value = temp;
153 | }
154 |
155 | public static void setTypeId(byte typeId) {
156 | SyncingListRecord.TYPE_ID = typeId;
157 | }
158 |
159 | @Override
160 | public byte getTypeId() {
161 | return TYPE_ID;
162 | }
163 |
164 | @Override
165 | protected boolean checkUpdate(List delta) {
166 | return true;
167 | }
168 |
169 | @Override
170 | public int size() {
171 | return 2 + (value.size() * writer.size());
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/data/scripts/net/data/records/collections/SyncingMapRecord.java:
--------------------------------------------------------------------------------
1 | package data.scripts.net.data.records.collections;
2 |
3 | import data.scripts.net.data.records.DataRecord;
4 | import io.netty.buffer.ByteBuf;
5 |
6 | import java.util.Map;
7 |
8 | public class SyncingMapRecord extends DataRecord