2020-06-03 01:12:03 +00:00
using System ;
2020-06-04 23:00:03 +00:00
using System.Collections.Generic ;
2020-06-03 01:12:03 +00:00
using System.Linq ;
2020-06-04 23:00:03 +00:00
using Gamecraft.Wires.ChannelsCommon ;
2020-06-03 01:12:03 +00:00
using GamecraftModdingAPI ;
2020-06-04 23:00:03 +00:00
using GamecraftModdingAPI.Blocks ;
2020-06-03 01:12:03 +00:00
using GamecraftModdingAPI.Commands ;
using GamecraftModdingAPI.Engines ;
using GamecraftModdingAPI.Players ;
using GamecraftModdingAPI.Utility ;
using HarmonyLib ;
using IllusionPlugin ;
using RobocraftX.Character.Weapons ;
2020-06-04 23:00:03 +00:00
using RobocraftX.CommandLine.Custom ;
2020-06-03 01:12:03 +00:00
using RobocraftX.Common.Players ;
using Svelto.ECS ;
using Svelto.ECS.Internal ;
using Unity.Mathematics ;
2020-06-04 23:00:03 +00:00
using Main = GamecraftModdingAPI . Main ;
2020-06-03 01:12:03 +00:00
namespace BlockMod
{
public class BlockMod : IPlugin
{
public void OnApplicationStart ( )
{
Main . Init ( ) ;
GameClient . SetDebugInfo ( "BlockModInfo" , GetBlockInfo ) ;
Block [ ] blocks = new Block [ 0 ] ;
2020-06-04 23:00:03 +00:00
Block refBlock = null ;
CommandBuilder . Builder ( "scaleBlocks" ,
2020-06-03 01:12:03 +00:00
"Scales the blocks you're looking at, relative to current size (current scale * new scale)." +
" The block you're looking at stays where it is, everything else is moved next to it." +
" The command remembers the cluster of blocks, use forgetBlocks to forget it." )
. Action < float , float , float > ( ( scaleX , scaleY , scaleZ ) = >
{
2020-06-04 23:00:03 +00:00
if ( CheckNoBlocks ( blocks ) ) return ;
// ReSharper disable once PossibleNullReferenceException
float3 reference = refBlock . Position ;
2020-06-03 01:12:03 +00:00
float3 scale = new float3 ( scaleX , scaleY , scaleZ ) ;
2020-06-04 23:00:03 +00:00
foreach ( var block in blocks )
2020-06-03 01:12:03 +00:00
{
block . Scale * = scale ;
block . Position = reference + ( block . Position - reference ) * scale ;
}
Logging . CommandLog ( "Blocks scaled." ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "scaleIndividually" , "Scales the blocks you're looking at, but doesn't move them." +
"The scale is relative, 1 means no change. Look at a block previously scaled to scale all of the blocks that were connected to it." )
. Action < float , float , float > ( ( scaleX , scaleY , scaleZ ) = >
{
2020-06-04 23:00:03 +00:00
if ( CheckNoBlocks ( blocks ) ) return ;
2020-06-03 01:12:03 +00:00
float3 scale = new float3 ( scaleX , scaleY , scaleZ ) ;
2020-06-04 23:00:03 +00:00
foreach ( var block in blocks )
2020-06-03 01:12:03 +00:00
block . Scale * = scale ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "moveBlocks" , "Moves the blocks around." )
. Action < float , float , float > ( ( x , y , z ) = >
{
2020-06-04 23:00:03 +00:00
if ( CheckNoBlocks ( blocks ) ) return ;
if ( GameState . IsBuildMode ( ) )
foreach ( var block in blocks )
block . Position + = new float3 ( x , y , z ) ;
else if ( GameState . IsSimulationMode ( ) )
foreach ( var body in GetSimBodies ( blocks ) )
body . Position + = new float3 ( x , y , z ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "colorBlocks" , "Colors the blocks you're looking at" )
. Action < string , byte > ( ( color , darkness ) = >
{
if ( CheckNoBlocks ( blocks ) ) return ;
if ( ! Enum . TryParse ( color , true , out BlockColors clr ) )
{
Logging . CommandLogWarning ( "Color " + color + " not found" ) ;
}
foreach ( var block in blocks )
block . Color = new BlockColor { Color = clr , Darkness = darkness } ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "selectBlocksLookedAt" , "Selects blocks (1 or more) to change. Only works in build mode, however the blocks can be changed afterwards." +
" Paramter: whether one (true) or all connected (false) blocks should be selected." )
. Action < bool > ( single = >
{
refBlock = new Player ( PlayerType . Local ) . GetBlockLookedAt ( ) ;
blocks = single ? new [ ] { refBlock } : refBlock ? . GetConnectedCubes ( ) ? ? new Block [ 0 ] ;
Logging . CommandLog ( blocks = = null ? "Selection cleared." : blocks . Length + " blocks selected." ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "selectBlocksWithID" , "Selects blocks with a specific object ID." )
. Action < char > ( id = >
blocks = ( refBlock = ObjectIdentifier . GetByID ( id ) . FirstOrDefault ( ) ) ? . GetConnectedCubes ( ) ? ?
new Block [ 0 ] ) . Build ( ) ;
ConsoleCommands . RegisterWithChannel ( "selectBlocksFromChannel" , id = >
{
blocks = ObjectIdentifier . GetBySimID ( id ) . SelectMany ( block = > block . GetConnectedCubes ( ) ) . ToArray ( ) ;
} ,
BinaryChannelUtilities . ChannelType . Object ) ;
CommandBuilder . Builder ( "pushBlocks" , "Adds velocity to the selected blocks. Only works in simulation." )
. Action < float , float , float > ( ( x , y , z ) = >
{
foreach ( var block in GetSimBodies ( blocks ) )
block . Velocity + = new float3 ( x , y , z ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "pushRotateBlocks" , "Adds angular velocity to the selected blocks. Only works in simulation." )
. Action < float , float , float > ( ( x , y , z ) = >
{
foreach ( var block in GetSimBodies ( blocks ) )
block . AngularVelocity + = new float3 ( x , y , z ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "pushPlayer" , "Adds velocity to the player." )
. Action < float , float , float > ( ( x , y , z ) = >
{
new Player ( PlayerType . Local ) . Velocity + = new float3 ( x , y , z ) ;
} ) . Build ( ) ;
CommandBuilder . Builder ( "pushRotatePlayer" , "Adds angular velocity to the player." )
. Action < float , float , float > ( ( x , y , z ) = >
{
new Player ( PlayerType . Local ) . AngularVelocity + = new float3 ( x , y , z ) ;
2020-06-03 01:12:03 +00:00
} ) . Build ( ) ;
GameEngineManager . AddGameEngine ( new Test ( ) ) ;
}
private class Test : IApiEngine
{
public void Ready ( )
{
try
{
CommandBuilder . Builder ( "weaponTest" ) . Action ( ( ) = >
{
var type = AccessTools . TypeByName ( "RobocraftX.Character.Weapons.CharacterEquippedWeaponStruct" ) ;
var dict = QueryEntitiesAndIndexInternal (
new EGID ( new Player ( PlayerType . Local ) . Id , PlayersExclusiveGroups . LocalPlayers ) ,
out uint i , type ) ;
var dtype = typeof ( ITypeSafeDictionary < > ) . MakeGenericType ( type ) ;
var obj = Convert . ChangeType ( dict , dtype ) ;
Array arr = ( Array ) AccessTools . PropertyGetter ( dtype , "unsafeValues" )
. Invoke ( obj , new object [ 0 ] ) ;
foreach ( var element in arr )
element . GetType ( ) . GetField ( "equippedWeaponType" )
. SetValue ( element , WeaponType . PISTOL ) ;
} ) . Build ( ) ;
}
catch
{
// ignored
}
}
private ITypeSafeDictionary QueryEntitiesAndIndexInternal ( EGID entityGID , out uint index , Type type )
{
index = 0 U ;
ITypeSafeDictionary typeSafeDictionary ;
if ( ! QueryEntityDictionary ( entityGID . groupID , out typeSafeDictionary , type ) )
return null ;
return ! typeSafeDictionary . TryFindIndex ( entityGID . entityID , out index ) ? null : typeSafeDictionary ;
}
private bool QueryEntityDictionary (
uint group ,
out ITypeSafeDictionary typeSafeDictionary ,
Type type )
{
object [ ] ps = { group , type , null } ;
bool ret = ( bool ) AccessTools . Method ( "Svelto.ECS.EntitiesDB:UnsafeQueryEntityDictionary" )
. Invoke ( entitiesDB , ps ) ;
typeSafeDictionary = ( ITypeSafeDictionary ) ps [ 2 ] ;
return ret ;
}
public EntitiesDB entitiesDB { get ; set ; }
public void Dispose ( )
{
}
public string Name { get ; } = "TestEngine" ;
public bool isRemovable { get ; } = true ;
}
private string GetBlockInfo ( )
{
if ( GameState . IsBuildMode ( ) )
{
var block = new Player ( PlayerType . Local ) . GetBlockLookedAt ( ) ;
float3 pos = block . Position ;
float3 rot = block . Rotation ;
float3 scale = block . Scale ;
return $"Block: {block.Type} at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
$"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
$"- Color: {block.Color.Color} darkness: {block.Color.Darkness}\n" +
$"- Scale: {scale.x:F} {scale.y:F} {scale.z:F}\n" +
$"- Label: {block.Label}" ;
}
if ( GameState . IsSimulationMode ( ) )
{
var body = new Player ( PlayerType . Local ) . GetSimBodyLookedAt ( ) ;
float3 pos = body . Position ;
float3 rot = body . Rotation ;
float3 vel = body . Velocity ;
float3 ave = body . AngularVelocity ;
float3 com = body . CenterOfMass ;
return $"Body at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
$"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
$"- Velocity: {vel.x:F} {vel.y:F} {vel.z:F}\n" +
$"- Angular velocity: {ave.x:F} {ave.y:F} {ave.z:F}\n" +
$"- {(body.Static ? " Static body " : $" Mass : { body . Mass : F } center : { com . x : F } { com . y : F } { com . z : F } ")}" ;
}
return "Switching modes..." ;
}
2020-06-04 23:00:03 +00:00
private bool CheckNoBlocks ( Block [ ] blocks )
2020-06-03 01:12:03 +00:00
{
2020-06-04 23:00:03 +00:00
if ( blocks . Length = = 0 )
{
Logging . CommandLogWarning ( "No blocks selected. Use selectBlocks first." ) ;
return true ;
}
2020-06-03 01:12:03 +00:00
2020-06-04 23:00:03 +00:00
return false ;
2020-06-03 01:12:03 +00:00
}
2020-06-04 23:00:03 +00:00
public IEnumerable < SimBody > GetSimBodies ( Block [ ] blocks )
= > blocks . Select ( block = > block . GetSimBody ( ) ) . Distinct ( ) ;
2020-06-03 01:12:03 +00:00
public void OnApplicationQuit ( )
{
}
public void OnLevelWasLoaded ( int level )
{
}
public void OnLevelWasInitialized ( int level )
{
}
public void OnUpdate ( )
{
}
public void OnFixedUpdate ( )
{
}
public string Name { get ; } = "BlockMod" ;
public string Version { get ; } = "v1.0.0" ;
}
}