コード例 #1
0
ファイル: Wrapper.cs プロジェクト: UAVXP/SharpLife-Wrapper
        internal unsafe Wrapper(EngineFuncs engineFuncs, GlobalVars.Internal *pGlobals)
            : base(new EngineShared(engineFuncs))
        {
            Log.Message("Initializing wrapper");

            EntityDictionary = new EntityDictionary(engineFuncs);

            //Make sure this knows how to convert edicts
            EntVars.EntityDictionary = EntityDictionary;

            EngineFuncs = engineFuncs;

            Globals = new GlobalVars(pGlobals, EntityDictionary);

            EntityDictionary.SetGlobals(Globals);

            StringPool = new StringPool(Globals);

            EngineString.StringPool = StringPool;

            //Create interface implementations
            EngineServer = new EngineServer(EngineFuncs, StringPool, EntityDictionary, Globals, FileSystem);

            CVar = new CVar.CVar(EngineFuncs);
        }
コード例 #2
0
        internal void LoadEntities(string data)
        {
            try
            {
                //Refresh the cache
                EngineServer.MapStartedLoading();

                var pEdictList = EngineFuncs.pfnPEntityOfEntOffset(0);

                Log.Message($"Initializing entity dictionary with 0x{(uint)pEdictList:X} as edict list address");

                EntityDictionary.Initialize(pEdictList, Globals.MaxEntities);

                Log.Message("Finished initializing entity dictionary");

                Entities.LoadEntities(data);
            }
            catch (Exception e)
            {
                Log.Exception(e);
                throw;
            }
            finally
            {
                EngineServer.MapFinishedLoading();
            }
        }
コード例 #3
0
 public EngineOverrides(
     EngineFuncs engineFuncs,
     IGlobalVars globals,
     EntityDictionary entityDictionary,
     EngineServer engineServer,
     IEntities entities
     )
 {
     EngineFuncs      = engineFuncs ?? throw new ArgumentNullException(nameof(engineFuncs));
     Globals          = globals ?? throw new ArgumentNullException(nameof(globals));
     EntityDictionary = entityDictionary ?? throw new ArgumentNullException(nameof(entityDictionary));
     EngineServer     = engineServer ?? throw new ArgumentNullException(nameof(engineServer));
     Entities         = entities ?? throw new ArgumentNullException(nameof(entities));
 }
コード例 #4
0
ファイル: Networking.cs プロジェクト: UAVXP/SharpLife-Game
        public void SetupVisibility(Edict pViewEntity, Edict pClient, out IntPtr pvs, out IntPtr pas)
        {
            var client = pClient.Entity();

            // Find the client's PVS
            var view = pViewEntity?.TryGetEntity() ?? client;

            if ((client.Flags & EntFlags.Proxy) != 0)
            {
                pvs = IntPtr.Zero;    // the spectator proxy sees
                pas = IntPtr.Zero;    // and hears everything
                return;
            }

            var org = view.Origin + view.ViewOffset;

            if ((view.Flags & EntFlags.Ducking) != 0)
            {
                org += (WorldConstants.HULL_MIN - WorldConstants.DUCK_HULL_MIN);
            }

            pvs = EngineServer.SetFatPVS(org);
            pas = EngineServer.SetFatPAS(org);
        }
コード例 #5
0
ファイル: Networking.cs プロジェクト: UAVXP/SharpLife-Game
        public void UpdateClientData(Edict ent, bool sendWeapons, ClientData cd)
        {
            if (ent == null || ent.PrivateData == null)
            {
                return;
            }

            var player = ent.TryGetEntity <BasePlayer>();

            BasePlayer originalPlayer = null;

            // if user is spectating different player in First person, override some vars
            if (player?.pev.UserInt1 == (int)ObserverMode.InEye && player.m_hObserverTarget)
            {
                originalPlayer = player;
                player         = player.m_hObserverTarget;
            }

            cd.Flags  = player.Flags;
            cd.Health = player.Health;

            cd.ViewModel = EngineModel.IndexOf(player.ViewModelName);

            cd.WaterLevel = player.WaterLevel;
            cd.WaterType  = player.WaterType;
            cd.Weapons    = player.pev.Weapons;

            // Vectors
            cd.Origin     = player.Origin;
            cd.Velocity   = player.Velocity;
            cd.ViewOffset = player.ViewOffset;
            cd.PunchAngle = player.PunchAngle;

            cd.InDuck        = player.pev.InDuck;
            cd.TimeStepSound = player.pev.TimeStepSound;
            cd.DuckTime      = player.pev.DuckTime;
            cd.SwimTime      = player.pev.SwimTime;
            cd.WaterJumpTime = (int)player.pev.TeleportTime;

            cd.SetPhysInfo(EngineServer.GetUnmanagedClientPhysicsInfoBuffer(ent));

            cd.MaxSpeed    = player.pev.MaxSpeed;
            cd.FieldOfView = player.pev.FieldOfView;
            cd.WeaponAnim  = player.pev.WeaponAnim;

            cd.PushMSec = player.pev.PushMSec;

            //Spectator mode
            if (originalPlayer != null)
            {
                // don't use spec vars from chased player
                cd.UserInt1 = originalPlayer.pev.UserInt1;
                cd.UserInt2 = originalPlayer.pev.UserInt2;
            }
            else
            {
                cd.UserInt1 = player.pev.UserInt1;
                cd.UserInt2 = player.pev.UserInt2;
            }

#if CLIENT_WEAPONS
            if (sendWeapons && player != null)
            {
                cd.NextAttack = player.m_flNextAttack;
                cd.UserFloat2 = player.m_flNextAmmoBurn;
                cd.UserFloat3 = player.m_flAmmoStartCharge;

                cd.UserVector1 = new Vector(
                    player.ammo_9mm,
                    player.ammo_357,
                    player.ammo_argrens
                    );

                cd.AmmoNails   = player.ammo_bolts;
                cd.AmmoShells  = player.ammo_buckshot;
                cd.AmmoRockets = player.ammo_rockets;
                cd.AmmoCells   = player.ammo_uranium;
                var vector2 = cd.UserVector2;
                vector2.x      = player.ammo_hornets;
                cd.UserVector2 = vector2;

                if (player.m_pActiveItem != null)
                {
                    BasePlayerWeapon gun = player.m_pActiveItem as BasePlayerWeapon;

                    if (gun?.IsPredicted() == true)
                    {
                        //TODO:
#if false
                        ItemInfo II;
                        memset(&II, 0, sizeof(II));
                        gun.GetItemInfo(&II);

                        cd.m_iId = II.iId;

                        cd.vuser3.z = gun.m_iSecondaryAmmoType;
                        cd.vuser4.x = gun.m_iPrimaryAmmoType;
                        cd.vuser4.y = player.m_rgAmmo[gun.m_iPrimaryAmmoType];
                        cd.vuser4.z = player.m_rgAmmo[gun.m_iSecondaryAmmoType];

                        if (player.m_pActiveItem.m_iId == WEAPON_RPG)
                        {
                            cd.vuser2.y = ((Rpg)player.m_pActiveItem).m_fSpotActive;
                            cd.vuser2.z = ((Rpg)player.m_pActiveItem).m_cActiveRockets;
                        }
#endif
                    }
                }
            }
#endif
        }
コード例 #6
0
ファイル: Networking.cs プロジェクト: UAVXP/SharpLife-Game
        public bool AddToFullPack(EntityState state, int e, Edict ent, Edict host, HostFlags hostFlags, bool isPlayer, IntPtr pSet)
        {
            //Never add entities that aren't in use
            if (ent.Free)
            {
                return(false);
            }

            var entity     = ent.Entity();
            var hostEntity = host.Entity();

            // don't send if flagged for NODRAW and it's not the host getting the message
            if ((entity.Effects & EntityEffects.NoDraw) != 0 &&
                (entity != hostEntity))
            {
                return(false);
            }

            // Ignore ents without valid / visible models
            if (entity.ModelIndex == 0 || string.IsNullOrEmpty(entity.ModelName))
            {
                return(false);
            }

            // Don't send spectators to other players
            if ((entity.Flags & EntFlags.Spectator) != 0 && (entity != hostEntity))
            {
                return(false);
            }

            // Ignore if not the host and not touching a PVS/PAS leaf
            // If pSet is NULL, then the test will always succeed and the entity will be added to the update
            if (entity != hostEntity)
            {
                if (!EngineServer.CheckVisibility(ent, pSet))
                {
                    return(false);
                }
            }

            // Don't send entity to local client if the client says it's predicting the entity itself.
            if ((entity.Flags & EntFlags.SkipLocalHost) != 0)
            {
                if ((hostFlags & HostFlags.SkipLocalEnts) != 0 && (entity.Owner == hostEntity))
                {
                    return(false);
                }
            }

            if (hostEntity.GroupInfo != 0)
            {
                Trace.PushGroupTrace(hostEntity.GroupInfo, GroupOp.And);

                try
                {
                    Trace.GetGroupTrace(out var currentMask, out var currentOp);

                    // Should always be set, of course
                    if (entity.GroupInfo != 0)
                    {
                        if (currentOp == GroupOp.And)
                        {
                            if ((entity.GroupInfo & hostEntity.GroupInfo) == 0)
                            {
                                return(false);
                            }
                        }
                        else if (currentOp == GroupOp.NAnd)
                        {
                            if ((entity.GroupInfo & hostEntity.GroupInfo) != 0)
                            {
                                return(false);
                            }
                        }
                    }
                }
                finally
                {
                    //There is a bug in the SDK that can cause the last group trace to remain if it failed the tests above
                    Trace.PopGroupTrace();
                }
            }

            //This is done by the wrapper since there's no memset in managed code
            //memset(state, 0, sizeof( * state) );

            // Assign index so we can track this entity from frame to frame and
            //  delta from it.
            state.Number     = e;
            state.EntityType = EntityType.Normal;

            // Flag custom entities.
            if ((entity.Flags & EntFlags.CustomEntity) != 0)
            {
                state.EntityType = EntityType.Beam;
            }

            //
            // Copy state data
            //

            // Round animtime to nearest millisecond
            state.AnimTime = (float)((int)(1000.0 * entity.AnimationTime) / 1000.0);

            state.Origin = entity.Origin;
            state.Angles = entity.Angles;
            state.Mins   = entity.Mins;
            state.Maxs   = entity.Maxs;

            state.EndPos   = entity.EndPosition;
            state.StartPos = entity.StartPosition;

            state.ImpactTime = entity.ImpactTime;
            state.StartTime  = entity.StartTime;

            state.ModelIndex = entity.ModelIndex;

            state.Frame = entity.Frame;

            state.Skin    = (short)entity.Skin;
            state.Effects = entity.Effects;

            // This non-player entity is being moved by the game .dll and not the physics simulation system
            //  make sure that we interpolate it's position on the client if it moves
            if (!isPlayer &&
                entity.AnimationTime != 0 &&
                entity.Velocity[0] == 0 &&
                entity.Velocity[1] == 0 &&
                entity.Velocity[2] == 0)
            {
                state.EFlags |= EntityStateFlags.SLerp;
            }

            state.Scale    = entity.Scale;
            state.Solid    = entity.Solid;
            state.ColorMap = entity.ColorMap;

            state.MoveType  = entity.MoveType;
            state.Sequence  = entity.Sequence;
            state.FrameRate = entity.FrameRate;
            state.Body      = entity.Body;

            for (var i = 0; i < 4; ++i)
            {
                state.SetController(i, entity.GetController(i));
            }

            for (var i = 0; i < 2; ++i)
            {
                state.SetBlending(i, entity.GetBlending(i));
            }

            state.RenderMode   = entity.RenderMode;
            state.RenderAmount = (int)entity.RenderAmount;
            state.RenderEffect = entity.RenderEffect;

            state.RenderColor = new Color24
            {
                r = (byte)entity.RenderColor.x,
                g = (byte)entity.RenderColor.y,
                b = (byte)entity.RenderColor.z
            };

            state.AimEnt = 0;
            if (entity.AimEntity != null)
            {
                state.AimEnt = entity.AimEntity.EntIndex();
            }

            state.Owner = 0;
            if (entity.Owner != null)
            {
                var owner = entity.Owner.EntIndex();

                // Only care if owned by a player
                if (owner >= 1 && owner <= Globals.MaxClients)
                {
                    state.Owner = owner;
                }
            }

            // HACK:  Somewhat...
            // Class is overridden for non-players to signify a breakable glass object ( sort of a class? )
            if (!isPlayer)
            {
                state.PlayerClass = entity.PlayerClass;
            }

            // Special stuff for players only
            if (isPlayer)
            {
                state.BaseVelocity = entity.BaseVelocity;

                state.WeaponModel  = EngineModel.IndexOf(entity.WeaponModelName);
                state.GaitSequence = entity.GaitSequence;
                state.Spectator    = (entity.Flags & EntFlags.Spectator) != 0;
                state.Friction     = entity.Friction;

                state.Gravity = entity.Gravity;
                //		state.Team			= entity.Team;
                //
                state.UseHull = (entity.Flags & EntFlags.Ducking) != 0 ? 1 : 0;
                state.Health  = (int)entity.Health;
            }

            return(true);
        }
コード例 #7
0
 public EngineEntities(EngineFuncs engineFuncs, EngineServer engineServer, IStringPool stringPool)
 {
     EngineFuncs  = engineFuncs ?? throw new ArgumentNullException(nameof(engineFuncs));
     EngineServer = engineServer ?? throw new ArgumentNullException(nameof(engineServer));
     StringPool   = stringPool ?? throw new ArgumentNullException(nameof(stringPool));
 }
コード例 #8
0
        public Engine(HostType hostType, ICommandLine commandLine, string gameDirectory, EngineConfiguration engineConfiguration, ILogger logger, ForwardingTextWriter forwardingTextWriter)
        {
            _hostType = hostType;

            CommandLine         = commandLine ?? throw new ArgumentNullException(nameof(commandLine));
            GameDirectory       = gameDirectory ?? throw new ArgumentNullException(nameof(gameDirectory));
            EngineConfiguration = engineConfiguration ?? throw new ArgumentNullException(nameof(engineConfiguration));
            Log.Logger          = Logger = logger ?? throw new ArgumentNullException(nameof(logger));
            LogTextWriter       = forwardingTextWriter ?? throw new ArgumentNullException(nameof(forwardingTextWriter));

            FileSystem = new DiskFileSystem();

            SetupFileSystem(GameDirectory);

            CommandSystem = new SharpLife.CommandSystem.CommandSystem(Logger, CultureInfo.InvariantCulture);

            EngineContext = CommandSystem.CreateContext("EngineContext");

            var startupState = new EngineStartupState(Logger, GameDirectory,
                                                      new IModelFormatProvider[]
            {
                new SpriteModelFormatProvider(),
                new StudioModelFormatProvider(),
                //BSP loader comes last due to not having a way to positively recognize the format
                new BSPModelFormatProvider(Framework.BSPModelNamePrefix)
            });

            //Add the engine assembly so builtin data gets added
            startupState.EntitySystemMetaData.AddAssembly(typeof(Engine).Assembly);

            //create the game window if this is a client
            if (_hostType == HostType.Client)
            {
                Client = new EngineClient(this, startupState);
            }

            Server = new EngineServer(this, Logger, startupState);

            PluginManager = startupState.PluginManager.Build();

            //Automatically add in all plugin assemblies to the entity system
            foreach (var pluginAssembly in PluginManager.Assemblies)
            {
                startupState.EntitySystemMetaData.AddAssembly(pluginAssembly);
            }

            var renderer = (IRenderer)Client?.UserInterface.Renderer ?? new ServerRenderer();

            World = new WorldState(
                Logger,
                EventSystem,
                FileSystem,
                startupState.EntitySystemMetaData.Build(),
                renderer,
                startupState.ModelFormats);

            _engineTimeStopwatch.Start();

            EngineContext.AddStuffCmds(Logger, CommandLine);
            EngineContext.AddExec(Logger, FileSystem, ExecPathIDs);
            EngineContext.AddEcho(Logger);
            EngineContext.AddAlias(Logger);
            EngineContext.AddFind(Logger);
            EngineContext.AddHelp(Logger);

            _fpsMax = EngineContext.RegisterVariable(
                new VirtualVariableInfo <uint>("fps_max", DefaultFPS)
                .WithHelpInfo("Sets the maximum frames per second")
                .WithChangeHandler((ref VariableChangeEvent <uint> @event) =>
            {
                @event.Value = Math.Min(@event.Value, MaximumFPS);

                var desiredFPS = @event.Value;

                if (desiredFPS == 0)
                {
                    desiredFPS = MaximumFPS;
                }

                _desiredFrameLengthSeconds = 1.0 / desiredFPS;
            }));

            EngineContext.RegisterVariable("engine_builddate", () => BuildDate, "The engine's build date");

            EngineContext.RegisterCommand(new CommandInfo("map", StartNewMap).WithHelpInfo("Loads the specified map"));

            //Get the build date from the generated resource file
            var assembly = typeof(Engine).Assembly;

            using (var reader = new StreamReader(assembly.GetManifestResourceStream($"{assembly.GetName().Name}.Resources.BuildDate.txt")))
            {
                string buildTimestamp = reader.ReadToEnd();

                BuildDate = DateTimeOffset.Parse(buildTimestamp);

                Logger.Information($"Exe: {BuildDate.ToString("HH:mm:ss MMM dd yyyy")}");
            }

            //TODO: initialize subsystems
        }