Repository navigation
PointHelper
Sur Nova Life, ce que nous appelons "les points" sont les cercles bleus avec lesquels les joueurs peuvent interagir dès que leur personnage entre en collision avec ceux-ci.
PointHelper simplifie la création, la gestion et l'enregistrement de point dynamique en base de données en passant par le module externe
Pour commencer, il est crucial de comprendre la logique sur laquelle je me suis appuyé pour concevoir PointHelper.
Nous avons des type de points (votre classe), des modèles (vos instances), puis les points eux-mêmes.
Chacune de vos classes doit hériter de l'interface
Cette interface garantit à ModKit que votre classe respecte une certaine structure:
//Inutile de créer l'interface, elle est déjà dans modKit prêt à l'emploi, je l'expose uniquement pour faciliter votre compréhension.
public interface PatternData
{
//Identifiant unique de l'instance de votre modèle
int Id { get; set; }
//Nom du type de point
string TypeName{ get; set; }
//Nom du modèle
string PatternName{ get; set; }
//Référence à ModKit pour profiter de ses fonctionnalités depuis votre classe
ModKit Context { get; set; }
//Action à effectuer lorsqu'un joueur interagit avec le point
void OnPlayerTrigger(Player player);
//Applique les valeurs récupérés en base de données lors de la génération du point
Task SetProperties(int id);
//Récupère les NPoints du type en cours.
//Cette fonction doit ensuite rediriger vers la fonction "SelectNPoint" listant les NPoints
Task GetNPoints(Player player);
//Création d'un nouveau modèle depuis AAMenu
void SetPatternData(Player player);
//Sélection d'un modèle depuis AAMenu avant de rediriger vers SelectPattern
Task GetPatternData(Player player, bool forEdit);
//Panel permettant au joueur de créer ou générer un point depuis un modèle existant
void CreateOrGenerate(Player player);
}Ne prenez pas peur, le code peut sembler massif mais il est relativement simple et assure une bonne structure.
La majorité permet d'indiquer à ModKit et plus précisément au module externe
Les fonctions englobés dans la
Les fonctions englobés dans la
Vous pouvez copier/coller ce code pour chaque type de point que vous souhaitez réaliser.
//Vous aurez probablement des références suviantes:
using Life.Network;
using Life.UI;
using SQLite;
using System.Threading.Tasks;
using ModKit.Helper;
using ModKit.Helper.PointHelper;
using mk = ModKit.Helper.TextFormattingHelper;
using System.Collections.Generic;
using System.Linq;
// - - - - - - - - - - - - - - - - -
public class MyPointPattern : ModKit.ORM.ModEntity<MyPointPattern>, PatternData
{
[AutoIncrement][PrimaryKey] public int Id { get; set; }
public string TypeName { get; set; }
public string PatternName { get; set; }
//Declare your other properties here
[Ignore] public ModKit.ModKit Context { get; set; }
public MyPointPattern() { }
public MyPointPattern(bool isCreated)
{
TypeName = nameof(MyPointPattern);
}
/// <summary>
/// Applies the properties retrieved from the database during the generation of a point in the game using this model.
/// </summary>
/// <param name="patternId">The identifier of the pattern in the database.</param>
public async Task SetProperties(int patternId)
{
var result = await Query(patternId);
Id = patternId;
TypeName = nameof(MyPointPattern);
PatternName = result.PatternName;
//Add your other properties here
}
/// <summary>
/// Contains the action to perform when a player interacts with the point.
/// </summary>
/// <param name="player">The player interacting with the point.</param>
public void OnPlayerTrigger(Player player)
{
}
/// <summary>
/// Triggers the function to begin creating a new model.
/// </summary>
/// <param name="player">The player initiating the creation of the new model.</param>
public void SetPatternData(Player player)
{
//Set the function to be called when a player clicks on the “create new model” button
SetName(player);
}
/// <summary>
/// Displays all properties of the pattern specified as parameter.
/// The user can select one of the properties to make modifications.
/// </summary>
/// <param name="player">The player requesting to edit the pattern.</param>
/// <param name="patternId">The ID of the pattern to be edited.</param>
public async void EditPattern(Player player, int patternId)
{
MyPointPattern pattern = new MyPointPattern(false);
pattern.Context = Context;
await pattern.SetProperties(patternId);
Panel panel = Context.PanelHelper.Create($"Modifier un {pattern.TypeName}", UIPanel.PanelType.Tab, player, () => EditPattern(player, patternId));
panel.AddTabLine($"{mk.Color("Nom:", mk.Colors.Info)} {pattern.PatternName}", _ => {
pattern.SetName(player, true);
});
//Add tablines for your other properties here
panel.NextButton("Sélectionner", () => panel.SelectTab());
panel.PreviousButton();
panel.CloseButton();
panel.Display();
}
/// <summary>
/// Allows the player to set a name for the pattern, either during creation or modification.
/// </summary>
/// <param name="player">The player interacting with the panel.</param>
/// <param name="inEdition">A flag indicating if the pattern is being edited.</param>
public void SetName(Player player, bool isEditing = false)
{
Panel panel = Context.PanelHelper.Create($"{(!isEditing ? "Créer" : "Modifier")} un modèle de {TypeName}", UIPanel.PanelType.Input, player, () =>
SetName(player));
panel.TextLines.Add("Donner un nom à votre modèle");
panel.inputPlaceholder = "3 caractères minimum";
if (!isEditing)
{
panel.NextButton("Suivant", () =>
{
if (panel.inputText.Length >= 3)
{
PatternName = panel.inputText;
//function to call for the following property
// If you want to generate your point
// await Save();
// ConfirmGeneratePoint(player, this);
}
else
{
player.Notify("Attention", "Vous devez donner un nom à votre modèle (3 caractères minimum)", Life.NotificationManager.Type.Warning);
SetName(player);
}
});
}
else
{
panel.PreviousButtonWithAction("Confirmer", async () =>
{
if (panel.inputText.Length >= 3)
{
PatternName = panel.inputText;
if (await Save()) return true;
else
{
player.Notify("Erreur", "échec lors de la sauvegarde de vos changements", Life.NotificationManager.Type.Error);
return false;
}
}
else
{
player.Notify("Attention", "Vous devez donner un nom à votre modèle (3 caractères minimum)", Life.NotificationManager.Type.Warning);
return false;
}
});
}
panel.PreviousButton();
panel.CloseButton();
panel.Display();
}
#region REPLACE YOUR CLASS/TYPE AS PARAMETER
/// <summary>
/// Displays a panel allowing the player to select a pattern from a list of patterns.
/// </summary>
/// <param name="player">The player selecting the pattern.</param>
/// <param name="patterns">The list of patterns to choose from.</param>
/// <param name="configuring">A flag indicating if the player is configuring.</param>
public void SelectPattern(Player player, List<MyPointPattern> patterns, bool configuring)
{
Panel panel = Context.PanelHelper.Create("Choisir un modèle", UIPanel.PanelType.Tab, player, () => SelectPattern(player, patterns, configuring));
foreach (var pattern in patterns)
{
panel.AddTabLine($"{pattern.PatternName}", _ => { });
}
if (patterns.Count == 0) panel.AddTabLine($"Vous n'avez aucun modèle de {TypeName}", _ => { });
if (!configuring && patterns.Count != 0)
{
panel.CloseButtonWithAction("Confirmer", async () =>
{
if (await Context.PointHelper.CreateNPoint(player, patterns[panel.selectedTab])) return true;
else return false;
});
}
else
{
panel.NextButton("Modifier", () => {
EditPattern(player, patterns[panel.selectedTab].Id);
});
panel.NextButton("Supprimer", () => {
ConfirmDeletePattern(player, patterns[panel.selectedTab]);
});
}
panel.AddButton("Retour", ui =>
{
AAMenu.AAMenu.menu.AdminPointsSettingPanel(player);
});
panel.CloseButton();
panel.Display();
}
/// <summary>
/// Confirms the generation of a point with a previously saved pattern.
/// </summary>
/// <param name="player">The player confirming the point generation.</param>
/// <param name="pattern">The pattern to generate the point from.</param>
public void ConfirmGeneratePoint(Player player, MyPointPattern pattern)
{
Panel panel = Context.PanelHelper.Create($"Modèle \"{pattern.PatternName}\" enregistré !", UIPanel.PanelType.Text, player, () =>
ConfirmGeneratePoint(player, pattern));
panel.TextLines.Add($"Voulez-vous générer un point sur votre position avec ce modèle \"{PatternName}\"");
panel.CloseButtonWithAction("Générer", async () =>
{
if (await Context.PointHelper.CreateNPoint(player, pattern)) return true;
else return false;
});
panel.PreviousButton();
panel.CloseButton();
panel.Display();
}
#endregion
#region DO NOT EDIT
/// <summary>
/// Base panel allowing the user to choose between creating a pattern from scratch
/// or generating a point from an existing pattern.
/// </summary>
/// <param name="player">The player initiating the creation or generation.</param>
public void CreateOrGenerate(Player player)
{
Panel panel = Context.PanelHelper.Create($"Créer ou générer un {TypeName}", UIPanel.PanelType.Text, player, () => CreateOrGenerate(player));
panel.TextLines.Add(mk.Pos($"{mk.Align($"{mk.Color("Générer", mk.Colors.Info)} utiliser un modèle existant. Les données sont partagés entre les points utilisant un même modèle.", mk.Aligns.Left)}", 5));
panel.TextLines.Add("");
panel.TextLines.Add($"{mk.Align($"{mk.Color("Créer:", mk.Colors.Info)} définir un nouveau modèle de A à Z.", mk.Aligns.Left)}");
panel.NextButton("Créer", () =>
{
SetPatternData(player);
});
panel.NextButton("Générer", async () =>
{
await GetPatternData(player, false);
});
panel.AddButton("Retour", ui =>
{
AAMenu.AAMenu.menu.AdminPointsPanel(player);
});
panel.CloseButton();
panel.Display();
}
/// <summary>
/// Retrieves all patterns before redirecting to a panel allowing the user various actions (CRUD).
/// </summary>
/// <param name="player">The player initiating the retrieval of pattern data.</param>
/// <param name="configuring">A flag indicating if the user is configuring.</param>
public async Task GetPatternData(Player player, bool configuring)
{
var patterns = await QueryAll();
SelectPattern(player, patterns, configuring);
}
/// <summary>
/// Confirms the deletion of the specified pattern.
/// </summary>
/// <param name="player">The player confirming the deletion.</param>
/// <param name="patternData">The pattern data to be deleted.</param>
public async void ConfirmDeletePattern(Player player, PatternData patternData)
{
var pattern = await Query(patternData.Id);
Panel panel = Context.PanelHelper.Create($"Supprimer un modèle de {pattern.TypeName}", UIPanel.PanelType.Text, player, () =>
ConfirmDeletePattern(player, patternData));
panel.TextLines.Add($"Cette suppression entrainera également celle des points.");
panel.TextLines.Add($"Êtes-vous sûr de vouloir supprimer le modèle \"{pattern.PatternName}\" ?");
panel.PreviousButtonWithAction("Confirmer", async () =>
{
if (await Context.PointHelper.DeleteNPointsByPattern(player, pattern))
{
if (await pattern.Delete())
{
return true;
}
else
{
player.Notify("Erreur", $"Nous n'avons pas pu supprimer le modèle \"{PatternName}\"", Life.NotificationManager.Type.Error, 6);
return false;
}
}
else
{
player.Notify("Erreur", "Certains points n'ont pas pu être supprimés.", Life.NotificationManager.Type.Error, 6);
return false;
}
});
panel.PreviousButton();
panel.CloseButton();
panel.Display();
}
/// <summary>
/// Retrieves all NPoints before redirecting to a panel allowing various actions by the user.
/// </summary>
/// <param name="player">The player retrieving the NPoints.</param>
public async Task GetNPoints(Player player)
{
var points = await NPoint.Query(e => e.TypeName == nameof(MyPointPattern));
SelectNPoint(player, points);
}
/// <summary>
/// Lists the points using this pattern.
/// </summary>
/// <param name="player">The player selecting the points.</param>
/// <param name="points">The list of points to choose from.</param>
public async void SelectNPoint(Player player, List<NPoint> points)
{
var patterns = await QueryAll();
Panel panel = Context.PanelHelper.Create($"Points de type {nameof(MyPointPattern)}", UIPanel.PanelType.Tab, player, () => SelectNPoint(player, points));
if (points.Count > 0)
{
foreach (var point in points)
{
var currentPattern = patterns.FirstOrDefault(p => p.Id == point.PatternId);
panel.AddTabLine($"point n° {point.Id}: {(currentPattern != default ? currentPattern.PatternName : "???")}", _ => { });
}
panel.NextButton("Voir", () =>
{
DisplayNPoint(player, points[panel.selectedTab]);
});
panel.NextButton("Supprimer", async () =>
{
await Context.PointHelper.DeleteNPoint(points[panel.selectedTab]);
await GetNPoints(player);
});
}
else
{
panel.AddTabLine($"Aucun point de ce type", _ => { });
}
panel.AddButton("Retour", ui =>
{
AAMenu.AAMenu.menu.AdminPointsSettingPanel(player);
});
panel.CloseButton();
panel.Display();
}
/// <summary>
/// Displays the information of a point and allows the user to modify it.
/// </summary>
/// <param name="player">The player viewing the point information.</param>
/// <param name="point">The point to display information for.</param>
public async void DisplayNPoint(Player player, NPoint point)
{
var pattern = await Query(p => p.Id == point.PatternId);
Panel panel = Context.PanelHelper.Create($"Point n° {point.Id}", UIPanel.PanelType.Tab, player, () => DisplayNPoint(player, point));
panel.AddTabLine($"Type: {point.TypeName}", _ => { });
panel.AddTabLine($"Modèle: {(pattern[0] != null ? pattern[0].PatternName : "???")}", _ => { });
panel.AddTabLine($"", _ => { });
panel.AddTabLine($"Position: {point.Position}", _ => { });
panel.AddButton("TP", ui =>
{
Context.PointHelper.PlayerSetPositionToNPoint(player, point);
});
panel.AddButton("Définir pos.", async ui =>
{
await Context.PointHelper.SetNPointPosition(player, point);
panel.Refresh();
});
panel.PreviousButton();
panel.CloseButton();
panel.Display();
}
#endregion
}Dans le code partagé précédemment, les fonctions en dehors des regions doivent être complétés.
-
${\color{NavyBlue}\normalsize{\textsf{SetProperties(int patternId)}}}$ : Applique les propriétés récupérées en base de données lors de la génération d'un point dans le jeu. -
${\color{NavyBlue}\normalsize{\textsf{OnPlayerTrigger(Player player)}}}$ : Contient l'action à effectuer lorsqu'un joueur interagit avec le point. -
${\color{NavyBlue}\normalsize{\textsf{SetPatternData(Player player)}}}$ : Déclenche la fonction pour commencer à créer un nouveau modèle. -
${\color{NavyBlue}\normalsize{\textsf{EditPattern(Player player, int patternId)}}}$ : L'utilisateur peut sélectionner l'une des propriétés pour effectuer des modifications à des fins d'édition. -
${\color{NavyBlue}\normalsize{\textsf{SetName(Player player, bool isEditing = false)}}}$ : Permet au joueur de définir le nom du modèle, soit lors de la création, soit lors de la modification selon la valeur du flag (isEditing) en paramètre.
Vous devrez très probablement créer d'autres fonctions similaire à
Utilisons l'ORM de ModKit en appelant la méthode
La méthode
public override void OnPluginInit()
{
base.OnPluginInit();
Orm.RegisterTable<MyPointsPattern>();
PointHelper.AddPattern("MyPointsPattern", new MyPointsPattern(false));
}Avec la fonction
Les admins de votre serveurs pourront facilement créer/modifier/supprimer les modèles et les points associés à votre type de point.
public override void OnPluginInit()
{
AAMenu.AAMenu.menu.AddBuilder(PluginInformations, "TextPoint", new TextPoint(false), this);
}- Getting Started
- Ajouter une compétence métier
- Ajouter une interaction
- Ajouter une proximité
- Ajouter une proximité d'activité
- Ajouter une action admin
- Ajouter un plugin
- Retourner vers AAMenu
- Introduction
- Ajouter une activité personnalisé
- Associer une société à une activité personnalisées
- Connaitre l'activité d'un joueur
- Introduction
- PatternData
- Classe de base
- Fonctions à compléter ou créer
- Enregistrer votre type de point en base de donées
- Intégrer votre type de point à AAMenu
- Introduction
- Peupler la base de donées
- Créer un vêtement personnalisés
- Equiper un vêtement
- Afficher les vêtements selon leurs type
- Attribuer/Retirer un vêtement à un joueur
- Recipe & Ingredient
- Récupérer les recettes
- Récupérer les recettes selon la catégorie
- Ajouter une recette
- Comment l'utiliser
