Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanpoland authored Oct 16, 2024
1 parent fc2c890 commit 31148f7
Showing 1 changed file with 59 additions and 190 deletions.
249 changes: 59 additions & 190 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# RecipeSmith

RecipeSmith is a rs-based module designed by: Asterisk for use with games that utilize the stars beyond horizon Server Backend as a framework for managing recipes, ingredients, and their interactions within a recipe book. This system integrates with PebbleVault for data storage and retrieval while being capable of communication with other submodules, ensuring modularity and independence. The goal is to enable dynamic recipe management, including creating, storing, retrieving, and crafting recipes based on available ingredients.
RecipeSmith is a Rust-based plugin designed for use with games that utilize the Stars Beyond Horizon Server Backend. It provides a framework for managing recipes, ingredients, and their interactions within a recipe book. This system is designed to be modular and independent, capable of communicating with other plugins through custom events. The goal is to enable dynamic recipe management, including creating, storing, retrieving, and crafting recipes based on available ingredients.

## Features

- **Dynamic Recipe Management:** Create, store, retrieve, and craft recipes based on available ingredients.
- **Integration with PebbleVault:** Seamless data storage and retrieval with PebbleVault.
- **Modularity:** Designed to communicate with other submodules independently.
- **Event-Driven Architecture:** Utilizes custom events for communication with other plugins.
- **Ingredient Interaction:** Detailed tracking and management of ingredients and their quantities.
- **Outcome Prediction:** Automatically determine the outcome of recipes based on input ingredients.
- **Loosely Coupled Architecture:** Ensures components can function independently, enhancing flexibility and scalability.
Expand All @@ -17,37 +16,11 @@ RecipeSmith is a rs-based module designed by: Asterisk for use with games that u

### 1. Dynamic Recipe Management

#### Definition

Recipes are defined in a JSON file containing the name, ingredients, and outcome of each recipe. Here is an example structure:

```json
{
"recipes": [
{
"name": "Bread",
"ingredients": [
{"name": "Flour", "quantity": 2},
{"name": "Water", "quantity": 1},
{"name": "Salt", "quantity": 1},
{"name": "Yeast", "quantity": 1}
],
"outcome": "Bread",
"crafters": ["Oven", "Bakery"],
"recipe_craftable": true,
"base_cook_time": 30,
"cook_count": 0
}
// Add other recipes
]
}
```

#### Recipe Structure

The `Recipe` struct represents a recipe with its name, ingredients, outcome, crafters, base cook time, and cook count.

```rs
```rust
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Recipe {
pub name: String,
Expand All @@ -61,50 +34,31 @@ pub struct Recipe {

#### Adding Recipes

Recipes can be added to the `RecipeBook` using the `add_recipe` method.
Recipes can be added to the `RecipeBook` using the `add_new_recipe` method.

```rs
pub fn add_recipe(&mut self, recipe: Recipe) {
for crafter in &recipe.crafters {
self.crafters.entry(crafter.clone()).or_insert_with(Vec::new).push(recipe.name.clone());
}
self.recipes.insert(recipe.name.clone(), recipe.clone());
let serialized_recipe = serde_json::to_string(&recipe).unwrap();
self.vault.collect("recipe", &recipe.name, &serialized_recipe);
```rust
pub async fn add_new_recipe(&self, recipe: Recipe) {
let mut recipe_book = self.recipe_book.write().await;
recipe_book.add_recipe(recipe);
}
```

### 2. Integration with PebbleVault

#### Seamless Data Storage and Retrieval

Recipes and ingredients are securely stored and easily accessible through integration with PebbleVault. This ensures efficient operation within a larger ecosystem, enabling modular and independent submodule communication.

```rs
let vault = Vault::new();
vault.define_class("recipe", r#"{
"name": "string",
"ingredients": "array",
"outcome": "string",
"base_cook_time": "u32",
"cook_count": "u32",
"crafters": "array"
}"#);
```

### 3. Modularity

#### Independent Communication
### 2. Event-Driven Architecture

RecipeSmith is designed to communicate with other submodules independently, allowing for flexible and scalable integration into various projects.
RecipeSmith uses custom events for communication. Here are some of the key events:

### 4. Ingredient Interaction
- `craft_item`: Attempts to craft an item for a player.
- `add_recipe`: Adds a new recipe to the recipe book.
- `get_player_inventory`: Retrieves a player's inventory contents.
- `add_item_to_inventory`: Adds an item to a player's inventory.
- `remove_item_from_inventory`: Removes an item from a player's inventory.
- `create_storage_container`: Creates a new storage container.

#### Detailed Tracking and Management
### 3. Ingredient Interaction

The `Ingredient` struct represents an ingredient with its name, quantity, and whether it can be crafted from a recipe.

```rs
```rust
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Ingredient {
pub name: String,
Expand All @@ -113,162 +67,77 @@ pub struct Ingredient {
}
```

### 5. Outcome Prediction

#### Automatically Determine Recipe Outcomes
### 4. Outcome Prediction

When crafting a recipe, the outcome is determined based on the input ingredients.

```rs
pub fn craft(&mut self, recipe_name: &str, inventory: &mut HashMap<String, Ingredient>) -> Option<String> {
if self.can_craft(recipe_name, inventory) {
let recipe = self.get_recipe(recipe_name).unwrap().clone();
for ingredient in &recipe.ingredients {
if let Some(inventory_ingredient) = inventory.get_mut(&ingredient.name) {
if inventory_ingredient.recipe_craftable {
inventory_ingredient.quantity -= ingredient.quantity;
}
}
}
Some(recipe.outcome.clone())
} else {
None
}
```rust
pub async fn craft_item(&self, player_id: &str, recipe_name: &str, context: &mut PluginContext) -> Option<String> {
// Implementation details...
}
```

### 6. Loosely Coupled Architecture

#### Flexibility and Scalability

Components can function independently, which enhances the flexibility and scalability of the system.

### 7. Full Error Logging Functionality

#### Comprehensive Error Logging

Error logging captures and logs errors to facilitate debugging and maintain system integrity. This feature ensures that any issues can be quickly identified and resolved.

```rs
// Initialize logger
env_logger::init();

// Setup error log file
let log_dir = "errorlogs";
let log_file_path = format!("{}/lastlog.txt", log_dir);

// Ensure log directory exists
fs::create_dir_all(log_dir).unwrap();

// Open log file
let log_file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&log_file_path)
.unwrap();
```

### 8. Extendable and Customizable

#### Adding New Features

RecipeSmith is easily extendable to add new features or customize existing ones to fit specific needs. This flexibility makes it suitable for a wide range of applications.

## Example Usage

### Initialization

1. **Clone the Repository:**
```sh
git clone https://github.com/Stars-Beyond/RecipeSmith.git
```

2. **Navigate to the Project Directory:**
```sh
cd RecipeSmith
```

3. **Build the Project:**
```sh
cargo build
```

4. **Run the Project:**
```sh
cargo run
```
The RecipeSmith plugin is initialized as part of the plugin system. It automatically registers for custom events and loads recipes from files.

### Recipe Management

#### Adding a Recipe

```rs
let mut recipe_book = RecipeBook::new();
recipe_book.add_recipe(Recipe {
To add a new recipe, emit a custom event:

```rust
let new_recipe = Recipe {
name: "Bread".to_string(),
ingredients: vec![
Ingredient {
name: "Flour".to_string(),
quantity: 2,
recipe_craftable: true,
},
Ingredient {
name: "Water".to_string(),
quantity: 1,
recipe_craftable: true,
},
Ingredient { name: "Flour".to_string(), quantity: 2, recipe_craftable: true },
Ingredient { name: "Water".to_string(), quantity: 1, recipe_craftable: true },
],
outcome: "Bread".to_string(),
crafters: vec![Crafter { name: "Oven".to_string() }],
base_cook_time: 30,
cook_count: 0,
});
};

context.dispatch_custom_event(CustomEvent {
event_type: "add_recipe".to_string(),
data: Arc::new(new_recipe),
}).await;
```

#### Crafting a Recipe

```rs
let mut inventory = HashMap::new();
inventory.insert("Flour".to_string(), Ingredient {
name: "Flour".to_string(),
quantity: 2,
recipe_craftable: true,
});
inventory.insert("Water".to_string(), Ingredient {
name: "Water".to_string(),
quantity: 1,
recipe_craftable: true,
});

if recipe_book.can_craft("Bread", &inventory) {
if let Some(outcome) = recipe_book.craft("Bread", &mut inventory) {
println!("Crafted: {}", outcome);
} else {
println!("Failed to craft Bread.");
}
} else {
println!("Not enough ingredients to craft Bread.");
}
To craft a recipe, emit a custom event:

```rust
context.dispatch_custom_event(CustomEvent {
event_type: "craft_item".to_string(),
data: Arc::new(("player1".to_string(), "Bread".to_string())),
}).await;
```

## SkillScript Integration
### Inventory Management

#### Adding an Item to Inventory

### Experience Gain and Reducing Cooking Time
```rust
let new_item = Item { /* ... */ };
context.dispatch_custom_event(CustomEvent {
event_type: "add_item_to_inventory".to_string(),
data: Arc::new(("player1".to_string(), new_item)),
}).await;
```

SkillScript can be integrated to give players experience over time, reduce cooking time, or gain rewards. This can be done by collecting experience points and updating the crafting system.
#### Removing an Item from Inventory

```rs
if recipe_book.can_craft("Bread", &inventory) {
if let Some(outcome) = recipe_book.craft("Bread", &mut inventory) {
recipe_book.vault.collect("skill_experience", "crafting", r#"{"experience": 10}"#);
println!("Crafted: {}", outcome);
} else {
println!("Failed to craft Bread.");
}
} else {
println!("Not enough ingredients to craft Bread.");
}
```rust
context.dispatch_custom_event(CustomEvent {
event_type: "remove_item_from_inventory".to_string(),
data: Arc::new(("player1".to_string(), "Bread".to_string())),
}).await;
```

## Contributing
Expand All @@ -277,4 +146,4 @@ Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.

0 comments on commit 31148f7

Please sign in to comment.