예제 #1
0
        /// <summary>
        /// Expands the Composite Texture to a texture atlas friendly version and populates the Baked field
        /// </summary>
        public void LoadAlternates(IAssetManager assetManager, ILogger logger)
        {
            if (Base.Path.EndsWith("*"))
            {
                List <IAsset> assets = assetManager.GetMany("shapes/" + Base.Path.Substring(0, Base.Path.Length - 1), Base.Domain);

                if (assets.Count == 0)
                {
                    logger.Warning("Could not find any variants for shape {0}, will use standard cube shape.", Base.Path);
                    Base = new AssetLocation("block/basic/cube");
                }

                if (assets.Count == 1)
                {
                    Base = assets[0].Location.CopyWithPath(assets[0].Location.Path.Substring("shapes/".Length));
                    Base.RemoveEnding();
                }

                if (assets.Count > 1)
                {
                    int origLength = (Alternates == null ? 0 : Alternates.Length);
                    CompositeShape[] alternates = new CompositeShape[origLength + assets.Count];
                    if (Alternates != null)
                    {
                        Array.Copy(Alternates, alternates, Alternates.Length);
                    }

                    int i = 0;
                    foreach (IAsset asset in assets)
                    {
                        AssetLocation newLocation = asset.Location.CopyWithPath(asset.Location.Path.Substring("shapes/".Length));
                        newLocation.RemoveEnding();

                        if (i == 0)
                        {
                            Base = newLocation.Clone();
                        }

                        alternates[origLength + i] = new CompositeShape()
                        {
                            Base = newLocation, rotateX = rotateX, rotateY = rotateY, rotateZ = rotateZ
                        };

                        i++;
                    }

                    Alternates = alternates;
                }
            }

            if (Alternates != null)
            {
                BakedAlternates               = new CompositeShape[Alternates.Length + 1];
                BakedAlternates[0]            = this.Clone();
                BakedAlternates[0].Alternates = null;

                for (int i = 0; i < Alternates.Length; i++)
                {
                    BakedAlternates[i + 1] = Alternates[i].Clone();

                    if (BakedAlternates[i + 1].Base == null)
                    {
                        BakedAlternates[i + 1].Base = Base.Clone();
                    }

                    if (BakedAlternates[i + 1].QuantityElements == null)
                    {
                        BakedAlternates[i + 1].QuantityElements = QuantityElements;
                    }

                    if (BakedAlternates[i + 1].SelectiveElements == null)
                    {
                        BakedAlternates[i + 1].SelectiveElements = SelectiveElements;
                    }
                }
            }
        }
예제 #2
0
        private void updateEyeHeight(float dt)
        {
            IPlayer player = World.PlayerByUid(PlayerUID);

            PrevFrameCanStandUp = true;

            if (player != null && player?.WorldData?.CurrentGameMode != EnumGameMode.Spectator)
            {
                PrevFrameCanStandUp = !servercontrols.Sneak && canStandUp();
                bool   moving       = (servercontrols.TriesToMove && SidedPos.Motion.LengthSq() > 0.00001) && !servercontrols.NoClip && !servercontrols.FlyMode && OnGround;
                double newEyeheight = Properties.EyeHeight;

                if (player.ImmersiveFpMode)
                {
                    updateLocalEyePosImmersiveFpMode();

                    newEyeheight = LocalEyePos.Y;
                }
                else
                {
                    double newModelHeight = Properties.CollisionBoxSize.Y;

                    if (servercontrols.FloorSitting)
                    {
                        newEyeheight   *= 0.5f;
                        newModelHeight *= 0.55f;
                    }
                    else if ((servercontrols.Sneak || !PrevFrameCanStandUp) && !servercontrols.IsClimbing && !servercontrols.IsFlying)
                    {
                        newEyeheight   *= 0.8f;
                        newModelHeight *= 0.8f;
                    }
                    else if (!Alive)
                    {
                        newEyeheight   *= 0.25f;
                        newModelHeight *= 0.25f;
                    }


                    double diff = (newEyeheight - LocalEyePos.Y) * 5 * dt;
                    LocalEyePos.Y = diff > 0 ? Math.Min(LocalEyePos.Y + diff, newEyeheight) : Math.Max(LocalEyePos.Y + diff, newEyeheight);

                    diff = (newModelHeight - OriginSelectionBox.Y2) * 5 * dt;
                    OriginSelectionBox.Y2 = SelectionBox.Y2 = (float)(diff > 0 ? Math.Min(SelectionBox.Y2 + diff, newModelHeight) : Math.Max(SelectionBox.Y2 + diff, newModelHeight));

                    diff = (newModelHeight - OriginCollisionBox.Y2) * 5 * dt;
                    OriginCollisionBox.Y2 = CollisionBox.Y2 = (float)(diff > 0 ? Math.Min(CollisionBox.Y2 + diff, newModelHeight) : Math.Max(CollisionBox.Y2 + diff, newModelHeight));

                    LocalEyePos.X = 0;
                    LocalEyePos.Z = 0;

                    if (MountedOn?.SuggestedAnimation == "sleep")
                    {
                        LocalEyePos.Y = 0.3;
                    }
                }



                double frequency = dt * servercontrols.MovespeedMultiplier * GetWalkSpeedMultiplier(0.3) * (servercontrols.Sprint ? 0.9 : 1.2) * (servercontrols.Sneak ? 1.2f : 1);

                walkCounter = moving ? walkCounter + frequency : 0;
                walkCounter = walkCounter % GameMath.TWOPI;

                double sneakDiv = (servercontrols.Sneak ? 3 : 1.8);

                double amplitude = (FeetInLiquid ? 0.8 : 1 + (servercontrols.Sprint ? 0.07 : 0)) / (3 * sneakDiv);
                double offset    = -0.2 / sneakDiv;

                double stepHeight = -Math.Max(0, Math.Abs(GameMath.Sin(5.5f * walkCounter) * amplitude) + offset);

                if (World.Side == EnumAppSide.Client)
                {
                    ICoreClientAPI capi = World.Api as ICoreClientAPI;
                    if (capi.Settings.Bool["viewBobbing"] && capi.Render.CameraType == EnumCameraMode.FirstPerson)
                    {
                        LocalEyePos.Y += stepHeight / 3f * dt * 60f;
                    }
                }


                if (moving)
                {
                    if (stepHeight > prevStepHeight)
                    {
                        if (direction == -1)
                        {
                            float volume = controls.Sneak ? 0.5f : 1f;

                            EntityPos pos           = SidedPos;
                            int       blockIdUnder  = BlockUnderPlayer(pos);
                            int       blockIdInside = BlockInsidePlayer(pos);

                            AssetLocation soundwalk   = World.Blocks[blockIdUnder].GetSounds(Api.World.BlockAccessor, new BlockPos((int)pos.X, (int)(pos.Y - 0.1f), (int)pos.Z))?.Walk;
                            AssetLocation soundinside = World.Blocks[blockIdInside].GetSounds(Api.World.BlockAccessor, new BlockPos((int)pos.X, (int)(pos.Y + 0.1f), (int)pos.Z))?.Inside;

                            if (!Swimming && soundwalk != null)
                            {
                                if (blockIdInside != blockIdUnder && soundinside != null)
                                {
                                    World.PlaySoundAt(soundwalk, this, player, true, 12, volume * 0.5f);
                                    World.PlaySoundAt(soundinside, this, player, true, 12, volume);
                                }
                                else
                                {
                                    World.PlaySoundAt(soundwalk, this, player, true, 12, volume);
                                }

                                OnFootStep?.Invoke();
                            }
                        }
                        direction = 1;
                    }
                    else
                    {
                        direction = -1;
                    }
                }

                prevStepHeight = stepHeight;
            }
        }
예제 #3
0
        protected Shape addGearToShape(ItemSlot slot, Shape entityShape, string shapePathForLogging)
        {
            if (slot.Empty)
            {
                return(entityShape);
            }
            ItemStack  stack   = slot.Itemstack;
            JsonObject attrObj = stack.Collectible.Attributes;


            string[] disableElements = attrObj?["disableElements"]?.AsArray <string>(null);
            if (disableElements != null)
            {
                foreach (var val in disableElements)
                {
                    entityShape.RemoveElementByName(val);
                }
            }

            if (attrObj?["wearableAttachment"].Exists != true)
            {
                return(entityShape);
            }

            CompositeShape compArmorShape = !attrObj["attachShape"].Exists ? (stack.Class == EnumItemClass.Item ? stack.Item.Shape : stack.Block.Shape) : attrObj["attachShape"].AsObject <CompositeShape>(null, stack.Collectible.Code.Domain);

            AssetLocation shapePath = shapePath = compArmorShape.Base.CopyWithPath("shapes/" + compArmorShape.Base.Path + ".json");



            IAsset asset = Api.Assets.TryGet(shapePath);

            if (asset == null)
            {
                Api.World.Logger.Warning("Entity armor shape {0} defined in {1} {2} not found, was supposed to be at {3}. Armor piece will be invisible.", compArmorShape.Base, stack.Class, stack.Collectible.Code, shapePath);
                return(null);
            }

            Shape armorShape;

            try
            {
                armorShape = asset.ToObject <Shape>();
            }
            catch (Exception e)
            {
                Api.World.Logger.Warning("Exception thrown when trying to load entity armor shape {0} defined in {1} {2}. Armor piece will be invisible. Exception: {3}", compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code, e);
                return(null);
            }

            bool added = false;

            foreach (var val in armorShape.Elements)
            {
                ShapeElement elem;

                if (val.StepParentName != null)
                {
                    elem = entityShape.GetElementByName(val.StepParentName, StringComparison.InvariantCultureIgnoreCase);
                    if (elem == null)
                    {
                        Api.World.Logger.Warning("Entity armor shape {0} defined in {1} {2} requires step parent element with name {3}, but no such element was found in shape {4}. Will not be visible.", compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code, val.StepParentName, shapePathForLogging);
                        continue;
                    }
                }
                else
                {
                    Api.World.Logger.Warning("Entity armor shape element {0} in shape {1} defined in {2} {3} did not define a step parent element. Will not be visible.", val.Name, compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code);
                    continue;
                }

                if (elem.Children == null)
                {
                    elem.Children = new ShapeElement[] { val };
                }
                else
                {
                    elem.Children = elem.Children.Append(val);
                }

                val.SetJointIdRecursive(elem.JointId);
                val.WalkRecursive((el) =>
                {
                    foreach (var face in el.Faces)
                    {
                        face.Value.Texture = "#" + stack.Collectible.Code + "-" + face.Value.Texture.TrimStart('#');
                    }
                });

                added = true;
            }

            if (added && armorShape.Textures != null)
            {
                Dictionary <string, AssetLocation> newdict = new Dictionary <string, AssetLocation>();
                foreach (var val in armorShape.Textures)
                {
                    newdict[stack.Collectible.Code + "-" + val.Key] = val.Value;
                }

                // Item overrides
                var collDict = stack.Class == EnumItemClass.Block ? stack.Block.Textures : stack.Item.Textures;
                foreach (var val in collDict)
                {
                    newdict[stack.Collectible.Code + "-" + val.Key] = val.Value.Base;
                }

                armorShape.Textures = newdict;

                foreach (var val in armorShape.Textures)
                {
                    CompositeTexture ctex = new CompositeTexture()
                    {
                        Base = val.Value
                    };

                    entityShape.TextureSizes[val.Key] = new int[] { armorShape.TextureWidth, armorShape.TextureHeight };

                    AssetLocation armorTexLoc = val.Value;

                    // Weird backreference to the shaperenderer. Should be refactored.
                    var texturesByLoc  = extraTextureByLocation;
                    var texturesByName = extraTexturesByTextureName;

                    BakedCompositeTexture bakedCtex;

                    ICoreClientAPI capi = Api as ICoreClientAPI;

                    if (!texturesByLoc.TryGetValue(armorTexLoc, out bakedCtex))
                    {
                        int textureSubId = 0;
                        TextureAtlasPosition texpos;

                        IAsset texAsset = Api.Assets.TryGet(val.Value.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"));
                        if (texAsset != null)
                        {
                            BitmapRef bmp = texAsset.ToBitmap(capi);
                            capi.EntityTextureAtlas.InsertTexture(bmp, out textureSubId, out texpos);
                        }
                        else
                        {
                            capi.World.Logger.Warning("Entity armor shape {0} defined texture {1}, no such texture found.", shapePath, val.Value);
                        }

                        ctex.Baked = new BakedCompositeTexture()
                        {
                            BakedName = val.Value, TextureSubId = textureSubId
                        };

                        texturesByName[val.Key]    = ctex;
                        texturesByLoc[armorTexLoc] = ctex.Baked;
                    }
                    else
                    {
                        ctex.Baked = bakedCtex;
                        texturesByName[val.Key] = ctex;
                    }
                }

                foreach (var val in armorShape.TextureSizes)
                {
                    entityShape.TextureSizes[val.Key] = val.Value;
                }
            }

            return(entityShape);
        }
예제 #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="code">Any unique Identifier</param>
        /// <param name="cshape"></param>
        /// <param name="entityShape"></param>
        /// <param name="shapePathForLogging"></param>
        /// <param name="disableElements"></param>
        /// <returns></returns>
        protected Shape addGearToShape(string code, CompositeShape cshape, Shape entityShape, string shapePathForLogging, string[] disableElements = null, Dictionary <string, AssetLocation> textureOverrides = null)
        {
            AssetLocation shapePath = shapePath = cshape.Base.CopyWithPath("shapes/" + cshape.Base.Path + ".json");

            if (disableElements != null)
            {
                foreach (var val in disableElements)
                {
                    entityShape.RemoveElementByName(val);
                }
            }

            IAsset asset = Api.Assets.TryGet(shapePath);

            if (asset == null)
            {
                Api.World.Logger.Warning("Compositshape {0} (code: {2}) defined but not found, was supposed to be at {1}. Part will be invisible.", cshape.Base, shapePath, code);
                return(null);
            }

            Shape armorShape;

            try
            {
                armorShape = asset.ToObject <Shape>();
            }
            catch (Exception e)
            {
                Api.World.Logger.Warning("Exception thrown when trying to load gear shape {0} (code: {2}) . Will be invisible. Exception: {1}", cshape.Base, e, code);
                return(null);
            }

            bool added = applyStepParents(null, armorShape.Elements, entityShape, code, cshape, shapePathForLogging);


            if (added && armorShape.Textures != null)
            {
                Dictionary <string, AssetLocation> newdict = new Dictionary <string, AssetLocation>();
                foreach (var val in armorShape.Textures)
                {
                    newdict[code + "-" + val.Key] = val.Value;
                }

                // Texture overrides
                if (textureOverrides != null)
                {
                    foreach (var val in textureOverrides)
                    {
                        newdict[code + "-" + val.Key] = val.Value;
                    }
                }

                armorShape.Textures = newdict;

                foreach (var val in armorShape.Textures)
                {
                    CompositeTexture ctex = new CompositeTexture()
                    {
                        Base = val.Value
                    };

                    entityShape.TextureSizes[val.Key] = new int[] { armorShape.TextureWidth, armorShape.TextureHeight };

                    AssetLocation armorTexLoc = val.Value;

                    // Weird backreference to the shaperenderer. Should be refactored.
                    var texturesByLoc  = extraTextureByLocation;
                    var texturesByName = extraTexturesByTextureName;

                    BakedCompositeTexture bakedCtex;

                    ICoreClientAPI capi = Api as ICoreClientAPI;

                    if (!texturesByLoc.TryGetValue(armorTexLoc, out bakedCtex))
                    {
                        int textureSubId = 0;
                        TextureAtlasPosition texpos;

                        IAsset texAsset = Api.Assets.TryGet(val.Value.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"));
                        if (texAsset != null)
                        {
                            BitmapRef bmp = texAsset.ToBitmap(capi);
                            capi.EntityTextureAtlas.InsertTexture(bmp, out textureSubId, out texpos);
                        }
                        else
                        {
                            capi.World.Logger.Warning("Entity armor shape {0} defined texture {1}, not no such texture found.", shapePath, val.Value);
                        }

                        ctex.Baked = new BakedCompositeTexture()
                        {
                            BakedName = val.Value, TextureSubId = textureSubId
                        };

                        texturesByName[val.Key]    = ctex;
                        texturesByLoc[armorTexLoc] = ctex.Baked;
                    }
                    else
                    {
                        ctex.Baked = bakedCtex;
                        texturesByName[val.Key] = ctex;
                    }
                }

                foreach (var val in armorShape.TextureSizes)
                {
                    entityShape.TextureSizes[val.Key] = val.Value;
                }
            }

            return(entityShape);
        }
예제 #5
0
 /// <summary>
 /// Returns true if given wildcard matches the blocks/items code. E.g. water-* will match all water blocks
 /// </summary>
 /// <param name="wildCard"></param>
 /// <returns></returns>
 public bool WildCardMatch(AssetLocation wildCard)
 {
     return(Code != null && WildcardUtil.Match(wildCard, Code));
 }