Changed how Locations are handled
+ Each location type is now a struct containing LocationData and location specific data. + Each type has its own place its own tree + Both were done in order to allow clear deserializationmain
parent
0bcb28bc47
commit
2bf1b8ab1c
|
@ -20,15 +20,20 @@ impl Database {
|
|||
Ok(self.db.open_tree::<String>(T::tree())?)
|
||||
}
|
||||
|
||||
pub fn insert<'a, T>(&self, mut model: T) -> Result<T> where T: GeoffreyDatabaseModel {
|
||||
let id = self.db.generate_id()?;
|
||||
pub fn insert<T>(&self, mut model: T) -> Result<T> where T: GeoffreyDatabaseModel {
|
||||
let id = match model.id() {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
let id = self.db.generate_id()?;
|
||||
model.set_id(id);
|
||||
id
|
||||
}
|
||||
};
|
||||
|
||||
let tree = self.get_tree::<T>()?;
|
||||
let data = serde_json::to_vec(&model).unwrap();
|
||||
let id_bytes = u64_to_bytes(id);
|
||||
|
||||
tree.insert(id_bytes, data)?;
|
||||
|
||||
model.set_id(id);
|
||||
tree.insert(id_bytes, model.to_bytes()?)?;
|
||||
|
||||
Ok(model)
|
||||
}
|
||||
|
@ -39,7 +44,7 @@ impl Database {
|
|||
let id_bytes = u64_to_bytes(id);
|
||||
|
||||
if let Some(bytes) = tree.get(id_bytes)? {
|
||||
Ok(Some(T::try_from_bytes(&bytes).unwrap()))
|
||||
Ok(Some(T::try_from_bytes(&bytes)?))
|
||||
}
|
||||
else {
|
||||
Ok(None)
|
||||
|
@ -54,6 +59,8 @@ mod tests {
|
|||
use std::path::Path;
|
||||
use geoffrey_models::models::player::{Player, UserID};
|
||||
use lazy_static::lazy_static;
|
||||
use geoffrey_models::models::shop::Shop;
|
||||
use geoffrey_models::models::{Location, Position};
|
||||
|
||||
|
||||
lazy_static! {
|
||||
|
@ -87,5 +94,20 @@ mod tests {
|
|||
assert_eq!(p3.unwrap().name, player.name);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shop() {
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
let player= DB.insert::<Player>(player.clone()).unwrap();
|
||||
let shop = Shop::new("cool shop123", Position::default(), player.id.unwrap(), None);
|
||||
|
||||
let shop2 = DB.insert::<Shop>(shop.clone()).unwrap();
|
||||
assert_eq!(shop.name(), shop2.name());
|
||||
|
||||
let shop3 = DB.get::<Shop>(shop2.id.unwrap()).unwrap().unwrap();
|
||||
|
||||
assert_eq!(shop3.id, shop2.id);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![allow(dead_code)]
|
||||
use byteorder::{WriteBytesExt, BigEndian};
|
||||
|
||||
pub mod database;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#[allow(dead_code)]
|
||||
|
||||
#![allow(dead_code)]
|
||||
use serde::{Serialize};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
|
@ -10,8 +9,20 @@ pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned {
|
|||
fn set_id(&mut self, id: u64);
|
||||
fn tree() -> String;
|
||||
|
||||
fn try_from_bytes(v: &[u8]) -> Result<Self, serde_json::Error> {
|
||||
Ok(serde_json::from_slice::<Self>(v)?)
|
||||
fn to_json_string(&self) -> Result<String, serde_json::Error> {
|
||||
serde_json::to_string(self)
|
||||
}
|
||||
|
||||
fn try_from_str(s: &str) -> Result<Self, serde_json::Error> {
|
||||
serde_json::from_str(s)
|
||||
}
|
||||
|
||||
fn to_bytes(&self) -> Result<Vec<u8>, serde_json::Error> {
|
||||
serde_json::to_vec(self)
|
||||
}
|
||||
|
||||
fn try_from_bytes(b: &[u8]) -> Result<Self, serde_json::Error> {
|
||||
serde_json::from_slice(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use crate::models::{LocationData, Location, Position, Tunnel};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Attraction {
|
||||
pub id: Option<u64>,
|
||||
pub location_data: LocationData
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Attraction {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"attraction".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for Attraction {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
location_data: LocationData::new(name, position, owner, tunnel)
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use crate::models::{LocationData, Location, Position, Tunnel};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Base {
|
||||
pub id: Option<u64>,
|
||||
pub location_data: LocationData
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Base {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"base".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for Base {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
location_data: LocationData::new(name, position, owner, tunnel)
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
|
@ -1,8 +1,44 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::models::{LocationData, Location, Position, Tunnel};
|
||||
use crate::models::item::Item;
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct FarmData {
|
||||
pub items_produced: Vec<Item>
|
||||
pub struct Farm {
|
||||
pub id: Option<u64>,
|
||||
pub location_data: LocationData,
|
||||
pub items_produced: HashSet<Item>
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Farm {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"farm".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for Farm {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
location_data: LocationData::new(name, position, owner, tunnel),
|
||||
items_produced: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct Item {
|
||||
pub name: String,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,44 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::models::{LocationData, Location, Position, Tunnel};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct MarketData {
|
||||
pub shops: Vec<u64>,
|
||||
pub struct Market {
|
||||
pub id: Option<u64>,
|
||||
pub location_data: LocationData,
|
||||
pub shops: HashSet<u64>
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Market {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"farm".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for Market {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
location_data: LocationData::new(name, position, owner, tunnel),
|
||||
shops: HashSet::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::player::Player;
|
||||
use crate::models::shop::ShopData;
|
||||
use crate::models::town::TownData;
|
||||
use crate::models::market::MarketData;
|
||||
use crate::models::farm::FarmData;
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub mod player;
|
||||
pub mod shop;
|
||||
|
@ -13,17 +9,9 @@ pub mod town;
|
|||
pub mod farm;
|
||||
pub mod market;
|
||||
pub mod token;
|
||||
mod meta;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum LocationData {
|
||||
Base,
|
||||
Shop(ShopData),
|
||||
Town(TownData),
|
||||
Market(MarketData),
|
||||
Attraction,
|
||||
PublicFarm(FarmData),
|
||||
}
|
||||
pub mod meta;
|
||||
mod base;
|
||||
pub mod attraction;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
||||
pub enum Dimension {
|
||||
|
@ -50,7 +38,17 @@ pub enum Direction {
|
|||
pub struct Position {
|
||||
pub x: i64,
|
||||
pub y: i64,
|
||||
dimension: Dimension,
|
||||
pub dimension: Dimension,
|
||||
}
|
||||
|
||||
impl Position {
|
||||
pub fn new(x: i64, y: i64, dimension: Dimension) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
dimension
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
@ -59,53 +57,68 @@ pub struct Tunnel {
|
|||
number: i64
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Location {
|
||||
id: Option<u64>,
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct LocationData {
|
||||
name: String,
|
||||
position: Position,
|
||||
owners: Vec<Player>,
|
||||
owners: HashSet<u64>,
|
||||
tunnel: Option<Tunnel>,
|
||||
loc_data: LocationData,
|
||||
}
|
||||
|
||||
|
||||
impl Location {
|
||||
pub fn new (name: &str, position: Position, owners: Vec<Player>, tunnel: Option<Tunnel>, loc_data: LocationData) -> Self {
|
||||
Location {
|
||||
id: None,
|
||||
impl LocationData {
|
||||
pub fn new (name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
let mut owners = HashSet::new();
|
||||
owners.insert(owner);
|
||||
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
position,
|
||||
owners,
|
||||
tunnel,
|
||||
loc_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Location {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
pub trait Location: Serialize + DeserializeOwned + Clone {
|
||||
fn new (name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self;
|
||||
fn mut_location_data(&mut self) -> &mut LocationData;
|
||||
fn location_data(&self) -> &LocationData;
|
||||
|
||||
fn name(&self) -> String {
|
||||
self.location_data().name.clone()
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
fn owners(&self) -> Vec<u64> {
|
||||
self.location_data().owners.iter().cloned().collect()
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"location".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::{Location, Position, Dimension, LocationData};
|
||||
use crate::models::player::{Player, UserID};
|
||||
|
||||
#[test]
|
||||
fn test_new_base() {
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
Location::new("test", Position {x: 0, y: 0, dimension: Dimension::Overworld}, vec![player], None, LocationData::Base);
|
||||
fn position(&self) -> Position {
|
||||
self.location_data().position.clone()
|
||||
}
|
||||
|
||||
fn tunnel(&self) -> Option<Tunnel> {
|
||||
self.location_data().tunnel.clone()
|
||||
}
|
||||
|
||||
fn add_owner(&mut self, owner: u64) {
|
||||
self.mut_location_data().owners.insert(owner);
|
||||
}
|
||||
|
||||
fn remove_owner(&mut self, owner: u64) {
|
||||
self.mut_location_data().owners.remove(&owner);
|
||||
}
|
||||
|
||||
fn set_position(&mut self, position: Position) {
|
||||
self.mut_location_data().position = position;
|
||||
}
|
||||
|
||||
fn set_tunnel(&mut self, tunnel: Tunnel) {
|
||||
self.mut_location_data().tunnel = Some(tunnel);
|
||||
}
|
||||
|
||||
fn set_name(&mut self, name: &str) {
|
||||
self.mut_location_data().name = name.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum UserID {
|
||||
DiscordUUID(u64),
|
||||
MinecraftUUID(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct Player {
|
||||
pub id: Option<u64>,
|
||||
pub name: String,
|
||||
|
|
|
@ -2,8 +2,11 @@ use serde::{Deserialize, Serialize};
|
|||
use chrono::{DateTime, Utc};
|
||||
|
||||
use crate::models::item::Item;
|
||||
use std::collections::HashSet;
|
||||
use crate::models::{LocationData, Location, Tunnel, Position};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct ItemListing {
|
||||
pub item: Item,
|
||||
pub price: u64,
|
||||
|
@ -22,8 +25,58 @@ impl ItemListing {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ShopData {
|
||||
pub item_listings: Vec<ItemListing>
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Shop {
|
||||
pub id: Option<u64>,
|
||||
pub item_listings: HashSet<ItemListing>,
|
||||
pub location_data: LocationData
|
||||
}
|
||||
|
||||
impl Location for Shop {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
item_listings: Default::default(),
|
||||
location_data: LocationData::new(name, position, owner, tunnel)
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Shop {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"shop".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::{Position, Dimension, LocationData, Location};
|
||||
use crate::models::player::{Player, UserID};
|
||||
use crate::models::shop::Shop;
|
||||
|
||||
fn create_shop() -> Shop {
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
let shop = Shop::new("Cool Shop 123", Position::default(), player, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_shop() {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_token() {
|
||||
let mut token = Token::new(0);
|
||||
let mut token = Token::new();
|
||||
|
||||
token.set_permission(Permissions::ModelGet);
|
||||
assert_eq!(token.permission, 0x1u64);
|
||||
|
|
|
@ -1,7 +1,45 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::{LocationData, Location, Position, Tunnel};
|
||||
use crate::models::player::Player;
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct TownData {
|
||||
pub resident: Vec<u64>
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Town {
|
||||
pub id: Option<u64>,
|
||||
pub location_data: LocationData,
|
||||
pub residents: HashSet<Player>
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Town {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"town".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for Town {
|
||||
fn new(name: &str, position: Position, owner: u64, tunnel: Option<Tunnel>) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
location_data: LocationData::new(name, position, owner, tunnel),
|
||||
residents: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_location_data(&mut self) -> &mut LocationData {
|
||||
&mut self.location_data
|
||||
}
|
||||
|
||||
fn location_data(&self) -> &LocationData {
|
||||
&self.location_data
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue