/// <summary>
        /// Generate a network behavior from a class object and a button that contains key information about the class
        /// </summary>
        /// <param name="cObj">The class object</param>
        /// <param name="btn">The button containing key information</param>
        /// <returns>The generated string to save to a file</returns>
        public string SourceCodeNetworkBehavior(ForgeClassObject cObj, ForgeEditorButton btn)
        {
            string behaviorPath = string.Empty;

            if (btn.BaseType == ForgeBaseClassType.NetworkBehavior)
            {
                behaviorPath = EDITOR_RESOURCES_DIR + "/StandAloneNetworkBehaviorTemplate";
            }
            else
            {
                behaviorPath = EDITOR_RESOURCES_DIR + "/NetworkBehaviorTemplate";
            }

            TextAsset      asset    = Resources.Load <TextAsset>(behaviorPath);
            TemplateSystem template = new TemplateSystem(asset.text);

            template.AddVariable("className", btn.StrippedSearchName + "Behavior");
            template.AddVariable("networkObject", btn.StrippedSearchName + "NetworkObject");
            StringBuilder generatedJSON            = new StringBuilder();
            StringBuilder generatedHelperTypesJSON = new StringBuilder();

            string          caps      = "QWERTYUIOPASDFGHJKLZXCVBNM";
            List <object[]> rpcs      = new List <object[]>();
            List <object[]> constRpcs = new List <object[]>();

            for (int i = 0; i < btn.RPCVariables.Count; ++i)
            {
                StringBuilder innerTypes           = new StringBuilder();
                StringBuilder helperNames          = new StringBuilder();
                StringBuilder innerJSON            = new StringBuilder();
                StringBuilder innerHelperTypesJSON = new StringBuilder();
                for (int x = 0; x < btn.RPCVariables[i].ArgumentCount; ++x)
                {
                    Type t = ForgeClassFieldRPCValue.GetTypeFromAcceptable(btn.RPCVariables[i].FieldTypes[x].Type);

                    helperNames.AppendLine("\t\t/// " + _referenceVariables[t.Name] + " " + btn.RPCVariables[i].FieldTypes[x].HelperName);

                    string fieldHelper = btn.RPCVariables[i].FieldTypes[x].HelperName;
                    if (x + 1 < btn.RPCVariables[i].ArgumentCount)
                    {
                        innerTypes.Append(", typeof(" + _referenceVariables[t.Name] + ")");
                        innerJSON.Append("\"" + _referenceVariables[t.Name] + "\", ");
                        innerHelperTypesJSON.Append("\"" + fieldHelper + "\", ");
                    }
                    else
                    {
                        innerTypes.Append(", typeof(" + _referenceVariables[t.Name] + ")");
                        innerJSON.Append("\"" + _referenceVariables[t.Name] + "\"");
                        innerHelperTypesJSON.Append("\"" + fieldHelper + "\"");
                    }
                }

                object[] rpcData = new object[]
                {
                    btn.RPCVariables[i].FieldName,                                              // The function name
                    innerTypes.ToString(),                                                      // The list of types
                    helperNames.ToString().TrimEnd()
                };

                string constRpc = "";
                for (int j = 0; j < btn.RPCVariables[i].FieldName.Length; j++)
                {
                    if (constRpc.Length > 0 && caps.Contains(btn.RPCVariables[i].FieldName[j]))
                    {
                        constRpc += "_";
                    }

                    constRpc += btn.RPCVariables[i].FieldName[j].ToString().ToUpper();
                }
                constRpc = constRpc.Replace("R_P_C_", "");

                object[] constRpcData = new object[]
                {
                    constRpc,                                                                       // The function name
                    innerTypes.ToString(),                                                          // The list of types
                    helperNames.ToString().TrimEnd()
                };

                rpcs.Add(rpcData);
                constRpcs.Add(constRpcData);
                generatedJSON.Append("[");
                generatedJSON.Append(innerJSON.ToString());
                generatedJSON.Append("]");
                generatedHelperTypesJSON.Append("[");
                generatedHelperTypesJSON.Append(innerHelperTypesJSON.ToString());
                generatedHelperTypesJSON.Append("]");
            }

            template.AddVariable("generatedTypes", generatedJSON.ToString().Replace("\"", "\\\""));
            template.AddVariable("generatedHelperTypes", generatedHelperTypesJSON.ToString().Replace("\"", "\\\""));
            template.AddVariable("rpcs", rpcs.ToArray());
            template.AddVariable("constRpcs", constRpcs.ToArray());

            return(template.Parse());
        }
Example #2
0
        public ForgeClassObject(string location)
        {
            this.FileLocation  = location;
            this.Filename      = Path.GetFileName(FileLocation);
            this.ExactFilename = Path.GetFileNameWithoutExtension(FileLocation);

            if (ExactFilename == "NetworkManager")
            {
                return;
            }

            List <float>          _interpolationValues = new List <float>();
            JSONNode              typeData             = null;
            JSONNode              typeHelperData       = null;
            JSONNode              interpolData         = null;
            Type                  currentType          = GetType("BeardedManStudios.Forge.Networking.Generated." + this.ExactFilename);
            GeneratedRPCAttribute aRPC = (GeneratedRPCAttribute)Attribute.GetCustomAttribute(currentType, typeof(GeneratedRPCAttribute));
            GeneratedRPCVariableNamesAttribute aNames    = (GeneratedRPCVariableNamesAttribute)Attribute.GetCustomAttribute(currentType, typeof(GeneratedRPCVariableNamesAttribute));
            GeneratedInterpolAttribute         aInterpol = (GeneratedInterpolAttribute)Attribute.GetCustomAttribute(currentType, typeof(GeneratedInterpolAttribute));

            if (aRPC != null && !string.IsNullOrEmpty(aRPC.JsonData))
            {
                typeData = JSON.Parse(aRPC.JsonData);
            }
            else
            {
                typeData = new JSONClass();
            }

            if (aNames != null && !string.IsNullOrEmpty(aNames.JsonData))
            {
                typeHelperData = JSON.Parse(aNames.JsonData);
            }
            else
            {
                typeHelperData = new JSONClass();
            }

            if (aInterpol != null && !string.IsNullOrEmpty(aInterpol.JsonData))
            {
                interpolData = JSON.Parse(aInterpol.JsonData);
            }
            else
            {
                interpolData = new JSONClass();
            }

#if FORGE_EDITOR_DEBUGGING
            string forgeClassDebug = "Loaded - " + this.ExactFilename + System.Environment.NewLine;
#endif

            List <MethodInfo>   uniqueMethods    = new List <MethodInfo>();
            List <PropertyInfo> uniqueProperties = new List <PropertyInfo>();
            List <FieldInfo>    uniqueFields     = new List <FieldInfo>();

            if (currentType == null)
            {
                throw new NullReferenceException("CANNOT PUT SOURCE CODE IN GENERATED FOLDER! PLEASE REMOVE NON GENERATED CODE!");
            }

            MethodInfo[]   methods    = currentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy).Where(m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType.FullName == "BeardedManStudios.Forge.Networking.RpcArgs").ToArray();
            PropertyInfo[] properties = currentType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
            FieldInfo[]    fields     = currentType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

            uniqueMethods.AddRange(methods);
            uniqueProperties.AddRange(properties);
            uniqueFields.AddRange(fields);

            if (currentType.BaseType != null)
            {
                Type baseType         = currentType.BaseType;
                Type networkBehavior  = currentType.GetInterface("INetworkBehavior");
                Type factoryInterface = currentType.GetInterface("INetworkObjectFactory");
                bool isMonobehavior   = currentType.IsSubclassOf(typeof(MonoBehaviour));

                if (baseType.FullName == "BeardedManStudios.Forge.Networking.NetworkObject")
                {
                    ObjectClassType = ForgeBaseClassType.NetworkObject;
                    IdentityValue   = ++IDENTITIES;
                }
                else if (networkBehavior != null && !isMonobehavior)
                {
                    ObjectClassType = ForgeBaseClassType.NetworkBehavior;
                }
                else if (baseType == typeof(MonoBehaviour) || isMonobehavior)
                {
                    ObjectClassType = ForgeBaseClassType.MonoBehavior;
                }
                else if (factoryInterface != null)
                {
                    ObjectClassType = ForgeBaseClassType.ObjectFactory;
                }
                else if (baseType == typeof(Enum))
                {
                    ObjectClassType = ForgeBaseClassType.Enums;
                }
                else
                {
                    ObjectClassType = ForgeBaseClassType.Custom;
                }

                MethodInfo[]   baseMethods    = baseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                PropertyInfo[] baseProperties = baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                FieldInfo[]    baseFields     = baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

                for (int i = 0; i < baseMethods.Length; ++i)
                {
                    for (int x = 0; x < uniqueMethods.Count; ++x)
                    {
                        if (uniqueMethods[x].Name == baseMethods[i].Name &&
                            uniqueMethods[x].GetParameters().Length == baseMethods[i].GetParameters().Length)
                        {
                            var  argsA = uniqueMethods[x].GetParameters();
                            var  argsB = baseMethods[i].GetParameters();
                            bool same  = true;

                            for (int j = 0; j < argsA.Length; j++)
                            {
                                if (!argsA[j].Equals(argsB[j]))
                                {
                                    same = false;
                                    break;
                                }
                            }

                            if (same)
                            {
                                uniqueMethods.RemoveAt(x);
                            }

                            break;
                        }
                    }
                }

                for (int i = 0; i < baseProperties.Length; ++i)
                {
                    for (int x = 0; x < uniqueProperties.Count; ++x)
                    {
                        if (uniqueProperties[x].Name == baseProperties[i].Name)
                        {
                            uniqueProperties.RemoveAt(x);
                            break;
                        }
                    }
                }

                for (int i = 0; i < baseFields.Length; ++i)
                {
                    for (int x = 0; x < uniqueFields.Count; ++x)
                    {
                        if (uniqueFields[x].Name == baseFields[i].Name)
                        {
                            uniqueFields.RemoveAt(x);
                            break;
                        }
                    }
                }
            }

            #region IGNORES
            for (int i = 0; i < uniqueFields.Count; ++i)
            {
                switch (uniqueFields[i].Name)
                {
                case "IDENTITY":
                case "networkObject":
                case "fieldAltered":
                case "_dirtyFields":
                case "dirtyFields":
                    uniqueFields.RemoveAt(i--);
                    //TODO: Store the types for re-use
                    continue;
                }

                if (uniqueFields[i].Name.EndsWith("Changed"))
                {
                    uniqueFields.RemoveAt(i--);
                    continue;
                }

                if (uniqueFields[i].Name.EndsWith("Interpolation"))
                {
                    uniqueFields.RemoveAt(i--);

                    //TODO: Store the types for re-use
                    continue;
                }
            }

            for (int i = 0; i < uniqueMethods.Count; ++i)
            {
                switch (uniqueMethods[i].Name.ToLower())
                {
                case "initialize":
                case "networkcreateobject":
                    uniqueMethods.RemoveAt(i--);
                    continue;
                }

                if (uniqueMethods[i].Name.EndsWith("Changed"))
                {
                    uniqueMethods.RemoveAt(i--);
                    continue;
                }

                if (uniqueMethods[i].Name.StartsWith("get_") ||
                    uniqueMethods[i].Name.StartsWith("set_"))
                {
                    uniqueMethods.RemoveAt(i--);
                    continue;
                }
            }
            #endregion

#if FORGE_EDITOR_DEBUGGING
            forgeClassDebug += "Properties:\n";
            foreach (PropertyInfo a in uniqueProperties)
            {
                forgeClassDebug += a.Name + " (" + a.PropertyType + ")" + System.Environment.NewLine;
            }
            forgeClassDebug += System.Environment.NewLine;

            forgeClassDebug += "Fields:\n";
#endif
            if (ObjectClassType != ForgeBaseClassType.Enums)
            {
                if (interpolData != null)
                {
                    JSONArray currentInterpolationVariables = interpolData["inter"].AsArray;
                    if (currentInterpolationVariables != null)
                    {
                        for (int i = 0; i < currentInterpolationVariables.Count; ++i)
                        {
                            float interPolVal = currentInterpolationVariables[i].AsFloat;
                            _interpolationValues.Add(interPolVal);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < uniqueFields.Count; ++i)
                    {
                        _interpolationValues.Add(ForgeNetworkingEditor.DEFAULT_INTERPOLATE_TIME);
                    }
                }

                for (int i = 0; i < uniqueFields.Count; ++i)
                {
                    if (_interpolationValues.Count == 0)
                    {
                        break;
                    }

                    ForgeClassFieldValue val = ForgeClassFieldValue.GetClassField(uniqueFields[i], currentType, _interpolationValues[i] > 0, _interpolationValues[i]);
                    Fields.Add(val);
#if FORGE_EDITOR_DEBUGGING
                    Debug.Log(val);
                    forgeClassDebug += uniqueFields[i].Name + " (" + uniqueFields[i].FieldType + ")" + System.Environment.NewLine;
#endif
                }
            }
#if FORGE_EDITOR_DEBUGGING
            forgeClassDebug += System.Environment.NewLine;

            forgeClassDebug += "Methods:\n";
#endif
            List <List <ForgeAcceptableRPCTypes> > rpcSupportedTypes = new List <List <ForgeAcceptableRPCTypes> >();
            if (typeData != null)
            {
                JSONArray currentRPCVariables = typeData["types"].AsArray;
                if (currentRPCVariables != null)
                {
                    for (int i = 0; i < currentRPCVariables.Count; ++i)
                    {
                        JSONArray singularArray = currentRPCVariables[i].AsArray;
                        if (singularArray != null)
                        {
                            List <ForgeAcceptableRPCTypes> singularSupportedTypes = new List <ForgeAcceptableRPCTypes>();
                            for (int x = 0; x < singularArray.Count; ++x)
                            {
                                ForgeAcceptableRPCTypes singularType = ForgeClassFieldRPCValue.GetTypeFromAcceptable(singularArray[x].Value);
                                singularSupportedTypes.Add(singularType);
                            }
                            rpcSupportedTypes.Add(singularSupportedTypes);
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < uniqueMethods.Count; ++i)
                {
                    rpcSupportedTypes.Add(new List <ForgeAcceptableRPCTypes>());
                }
            }

            List <List <string> > typeHelpers = new List <List <string> >();
            if (typeHelperData != null)
            {
                JSONArray currentHelperRPCTypes = typeHelperData["types"].AsArray;
                if (currentHelperRPCTypes != null)
                {
                    for (int i = 0; i < currentHelperRPCTypes.Count; ++i)
                    {
                        JSONArray singularHelperArray = currentHelperRPCTypes[i].AsArray;
                        if (singularHelperArray != null)
                        {
                            List <string> singularSupportedTypes = new List <string>(new string[Mathf.Max(singularHelperArray.Count, rpcSupportedTypes.Count)]);
                            for (int x = 0; x < singularHelperArray.Count; ++x)
                            {
                                string singularHelperType = singularHelperArray[x].Value.Replace(" ", string.Empty);
                                singularSupportedTypes[x] = singularHelperType;
                            }
                            typeHelpers.Add(singularSupportedTypes);
                        }
                    }
                }
            }
            else
            {
                //This is missing the type helper data
                for (int i = 0; i < rpcSupportedTypes.Count; ++i)
                {
                    typeHelpers.Add(new List <string>(new string[rpcSupportedTypes[i].Count]));
                }
            }

            for (int i = 0; i < uniqueMethods.Count; ++i)
            {
                RPCS.Add(new ForgeClassRPCValue(uniqueMethods[i], rpcSupportedTypes[i], typeHelpers[i]));
#if FORGE_EDITOR_DEBUGGING
                ParameterInfo[] paramsInfo = a.GetParameters();
                string          parameters = "";
                foreach (ParameterInfo info in paramsInfo)
                {
                    parameters += info.ParameterType + ", ";
                }

                forgeClassDebug += a.Name + " (" + parameters + ")" + System.Environment.NewLine;
#endif
            }

#if FORGE_EDITOR_DEBUGGING
            forgeClassDebug += "Class Type: " + ObjectClassType;
            forgeClassDebug += "\nSearchName: " + StrippedSearchName;
            forgeClassDebug += "\nIsNetworkedObject: " + IsNetworkObject;
            forgeClassDebug += "\nIsNetworkBehavior: " + IsNetworkBehavior;
            forgeClassDebug += System.Environment.NewLine;

            Debug.Log(forgeClassDebug);
#endif
        }