Compare commits
No commits in common. "9895a4797ffd056b1ff63be3959b5f3e6f84bd86" and "8b9b5db2992e1ca67f6820d036aaba31ea404954" have entirely different histories.
9895a4797f
...
8b9b5db299
7 changed files with 56 additions and 160 deletions
|
@ -9,7 +9,6 @@
|
||||||
var mapOffsetX = 0.0;
|
var mapOffsetX = 0.0;
|
||||||
var mapOffsetY = 0.0;
|
var mapOffsetY = 0.0;
|
||||||
var draggedToken = { token: null, offX: 0, offY: 0 };
|
var draggedToken = { token: null, offX: 0, offY: 0 };
|
||||||
var draggedDiv = { div: null, offX: 0, offY: 0 };
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
let view = document.getElementById('game-view');
|
let view = document.getElementById('game-view');
|
||||||
|
@ -41,8 +40,6 @@
|
||||||
document.body.onclick = (e) => {
|
document.body.onclick = (e) => {
|
||||||
document.getElementById('msg-context-menu').style.display = 'none';
|
document.getElementById('msg-context-menu').style.display = 'none';
|
||||||
}
|
}
|
||||||
document.body.onmousemove = onMoveableDivDrag;
|
|
||||||
document.body.onmouseup = onMoveableDivMouseUp;
|
|
||||||
// TODO: Remove when done dev-ing
|
// TODO: Remove when done dev-ing
|
||||||
tavern.onmessage({ text: 'test', id: 1, source: 'rusty', character: 'bart' });
|
tavern.onmessage({ text: 'test', id: 1, source: 'rusty', character: 'bart' });
|
||||||
}
|
}
|
||||||
|
@ -153,7 +150,7 @@
|
||||||
}
|
}
|
||||||
function onGameMouseMove(event) {
|
function onGameMouseMove(event) {
|
||||||
if(event.buttons == 2) {
|
if(event.buttons == 2) {
|
||||||
// right click
|
// middle click
|
||||||
let map = document.getElementById('map');
|
let map = document.getElementById('map');
|
||||||
let mult = event.ctrlKey ? 2.0 : 1.0;
|
let mult = event.ctrlKey ? 2.0 : 1.0;
|
||||||
mapOffsetX += event.movementX * mult;
|
mapOffsetX += event.movementX * mult;
|
||||||
|
@ -206,7 +203,7 @@
|
||||||
holder.appendChild(row);
|
holder.appendChild(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.getElementById('dice-roll-title').innerText = action.display_name ?? action.name;
|
document.getElementById('dice-roll-title').innerText = action.display_name ?? action.display;
|
||||||
document.getElementById('dice-roll-popup').style.display = 'flex';
|
document.getElementById('dice-roll-popup').style.display = 'flex';
|
||||||
}
|
}
|
||||||
function rollPopup() {
|
function rollPopup() {
|
||||||
|
@ -242,30 +239,6 @@
|
||||||
console.log(rolls);
|
console.log(rolls);
|
||||||
tavern.action_result(holder.action.name, 'Louise', [], rolls);
|
tavern.action_result(holder.action.name, 'Louise', [], rolls);
|
||||||
}
|
}
|
||||||
function onMoveableDivMouseDown(e, id) {
|
|
||||||
if(e.buttons == 1) {
|
|
||||||
let div = document.getElementById(id);
|
|
||||||
let rect = div.getBoundingClientRect();
|
|
||||||
draggedDiv.div = div;
|
|
||||||
draggedDiv.offX = e.clientX - rect.x;
|
|
||||||
draggedDiv.offY = e.clientY - rect.y;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onMoveableDivDrag(e) {
|
|
||||||
if(draggedDiv.div) {
|
|
||||||
draggedDiv.div.style.right = '';
|
|
||||||
draggedDiv.div.style.top = `${e.clientY - draggedDiv.offY}px`;
|
|
||||||
draggedDiv.div.style.left = `${e.clientX - draggedDiv.offX}px`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onMoveableDivMouseUp(e, id) {
|
|
||||||
draggedDiv.div = null;
|
|
||||||
}
|
|
||||||
function showHideDiv(id) {
|
|
||||||
let div = document.getElementById(id);
|
|
||||||
div.style.display = div.style.display == 'none' ? 'flex' : 'none';
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
html, body {
|
html, body {
|
||||||
|
@ -369,10 +342,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="game-view" style="display: flex; overflow: hidden; position: relative; top: 0px; left: 0px; flex-grow: 1;" >
|
<div id="game-view" style="display: flex; overflow: hidden; position: relative; top: 0px; left: 0px; flex-grow: 1;" >
|
||||||
<div style="position:absolute; top: 10px; left: 5px; background-color: rgb(255, 166, 0); z-index: 5;" >
|
<div style="position:absolute; top: 10px; left: 5px; background-color: rgb(255, 166, 0); z-index: 1;" >
|
||||||
floating<br>stuff
|
floating<br>stuff
|
||||||
</div>
|
</div>
|
||||||
<div id="dice-roll-popup" style="display:none; justify-content: center; width: 100%; height: 100%; background-color: transparent; position: absolute; z-index: 10; top: 0px; left: 0px">
|
<div id="dice-roll-popup" style="display:none; justify-content: center; width: 100%; height: 100%; background-color: transparent; position: absolute; z-index: 2; top: 0px; left: 0px">
|
||||||
<div style="display:flex; width: 50%; justify-content: center; flex-direction: column;">
|
<div style="display:flex; width: 50%; justify-content: center; flex-direction: column;">
|
||||||
<div style="display: flex; height: fit-content; flex-direction: column; background-color: #ffffd6; color: black; border: black solid 1px; padding: 8px; border-radius: 8px;">
|
<div style="display: flex; height: fit-content; flex-direction: column; background-color: #ffffd6; color: black; border: black solid 1px; padding: 8px; border-radius: 8px;">
|
||||||
<h3 id="dice-roll-title" style="align-self: center;">
|
<h3 id="dice-roll-title" style="align-self: center;">
|
||||||
|
@ -388,10 +361,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="position: absolute; top: 10px; right: 10px; color: black; z-index: 5; display: flex; flex-direction: row;">
|
|
||||||
<button style="background-color: #ffffd6;"><b>s</b></button>
|
|
||||||
<button style="background-color: #ffffd6;" onclick="showHideDiv('initiative-tracker')"><b>i</b></button>
|
|
||||||
</div>
|
|
||||||
<div id="map" style="position:absolute; transform-origin: top left;">
|
<div id="map" style="position:absolute; transform-origin: top left;">
|
||||||
<img src="https://rustystriker.dev/molly.jpg" height="200%" >
|
<img src="https://rustystriker.dev/molly.jpg" height="200%" >
|
||||||
</div>
|
</div>
|
||||||
|
@ -402,25 +371,5 @@
|
||||||
<li>Delete (TODO)</li>
|
<li>Delete (TODO)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="initiative-tracker" style="position: absolute; background-color: #ffffd6; color:black; display: none; flex-direction: column; top: 40px; right: 8px">
|
|
||||||
<div style="background-color: black; color:#ffffd6; margin-top: 0px; margin-bottom: 8px; padding: 0 4px; min-width: 150px; user-select: none; display: flex;"
|
|
||||||
onmousedown="onMoveableDivMouseDown(event, 'initiative-tracker')">
|
|
||||||
<h3 style="flex-grow: 1;">Initiative</h3>
|
|
||||||
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
|
||||||
<button onclick="document.getElementById('initiative-tracker').style.display = 'none';"
|
|
||||||
style="height: fit-content; align-self: center; background-color: transparent; color:#ffffd6; font-size: 20px; border: 0;">
|
|
||||||
X
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
aaaa
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
bbbb
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
cccc
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
48
readme.md
48
readme.md
|
@ -1,31 +1,23 @@
|
||||||
# WTF how do i implement a game???
|
# WTF how do i implement a game???
|
||||||
|
|
||||||
## Features
|
## Client todo
|
||||||
|
|
||||||
[x] Simple chat
|
[ ] implement tavern functions
|
||||||
[ ] Simple map view with moveable tokens
|
[x] token drag & drop
|
||||||
[ ] spawn tokens
|
[ ] Chat
|
||||||
[x] move tokens
|
[x] Send new chat messages
|
||||||
[ ] change map
|
[x] recv new chat messages
|
||||||
[ ] show grid
|
[ ] roll a die when chat message requests that
|
||||||
[ ] multiple maps
|
[ ] figure out how to zoom on the mouse instead of the center of the div
|
||||||
[ ] Chat actions
|
[ ] data reqs
|
||||||
[x] Define chat action
|
|
||||||
[x] show roll dialog on chat aciton
|
## Server todo
|
||||||
[ ] send action roll and get result
|
|
||||||
[ ] allow modify action roll stuff
|
[ ] impl different requests
|
||||||
[ ] allow adding custom rolls to action roll stuff
|
[ ] actual normal login
|
||||||
[ ] Roll dice for no reason
|
[x] allow sending of old info
|
||||||
[ ] roll dice animation because its fun
|
[x] chat history
|
||||||
[ ] Character sheet
|
[ ] send texture (map/token/image)
|
||||||
[ ] Create new character sheet
|
[ ] force show something
|
||||||
[ ] view sheet
|
[ ] mouse ping (ideally multiple types)
|
||||||
[ ] assign sheet (and character by extention) to user
|
[ ] data reqs
|
||||||
[ ] Display image
|
|
||||||
[ ] Free move / Turn based movement
|
|
||||||
[ ] clickable stuff
|
|
||||||
[ ] only gm visible stuff (like traps and info stuff)
|
|
||||||
[ ] combat fog
|
|
||||||
[ ] Characters in current map/scene
|
|
||||||
[ ] initiative tracker
|
|
||||||
[ ] cards system (for a playstyle that relies less on the map)
|
|
|
@ -17,25 +17,15 @@ pub trait Character<E: GameEntry> : CharacterSheet {
|
||||||
|
|
||||||
pub trait CharacterSheet : Default {
|
pub trait CharacterSheet : Default {
|
||||||
/// Character sheet inputs (stuff that are not calculated from different items), such as Name, Age, Strength
|
/// Character sheet inputs (stuff that are not calculated from different items), such as Name, Age, Strength
|
||||||
fn inputs(&self, access: AccessLevel) -> Vec<(String, EntryType)>;
|
fn inputs(&self) -> Vec<(String, EntryType)>;
|
||||||
/// All fields in the character sheet, maybe change it to only a vec of strings?
|
/// All fields in the character sheet
|
||||||
fn fields(&self) -> Vec<(String, EntryType)>;
|
fn fields(&self) -> Vec<(String, EntryType)>;
|
||||||
/// Character sheet to display, ordered. `None`s can be used to convey a seperator (of any sort)
|
/// Character sheet to display, ordered. `None`s can be used to convey a seperator (of any sort)
|
||||||
fn display(&self, access: AccessLevel) -> Vec<Option<(String, EntryType)>>;
|
fn display(&self) -> Vec<Option<(String, EntryType)>>;
|
||||||
/// Gets a character sheet entry value
|
/// Gets a character sheet entry value
|
||||||
fn get(&self, entry: &str, access: AccessLevel) -> Option<EntryType>;
|
fn get(&self, entry: &str) -> Option<EntryType>;
|
||||||
/// Sets a cahrater sheet entry value
|
/// Sets a cahrater sheet entry value
|
||||||
fn set(&mut self, entry: &str, value: EntryType, access: AccessLevel);
|
fn set(&mut self, entry: &str, value: EntryType);
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum AccessLevel {
|
|
||||||
Admin = 0, Owner = 1, PartyMember = 2, World = 3,
|
|
||||||
}
|
|
||||||
impl AccessLevel {
|
|
||||||
pub fn has_access(self, other: Self) -> bool {
|
|
||||||
(self as u8) <= (other as u8)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -9,10 +9,8 @@ pub mod chat_message;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
|
||||||
pub trait GameImpl<C: Character<A> + Serialize, A: entry::GameEntry + Serialize> {
|
pub trait GameImpl<C: Character<A> + Serialize, A: entry::GameEntry + Serialize> {
|
||||||
/// Creates a new game
|
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
/// Creates a new character, returning the character id
|
fn create_character(&mut self);
|
||||||
fn create_character(&mut self) -> usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Game<C: Character<A> + Serialize, A: entry::GameEntry + Serialize> {
|
pub struct Game<C: Character<A> + Serialize, A: entry::GameEntry + Serialize> {
|
||||||
|
@ -29,8 +27,7 @@ impl<C: Character<A> + Serialize, A: entry::GameEntry + Serialize> GameImpl<C, A
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_character(&mut self) -> usize {
|
fn create_character(&mut self) {
|
||||||
self.characters.push(C::default());
|
self.characters.push(C::default());
|
||||||
self.characters.len() - 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ impl GameServer {
|
||||||
.with_roll(DiceRoll::new("Pierce".to_string(), 12, 1).constant(1))
|
.with_roll(DiceRoll::new("Pierce".to_string(), 12, 1).constant(1))
|
||||||
.with_roll(DiceRoll::new("Fire".to_string(), 4, 2))
|
.with_roll(DiceRoll::new("Fire".to_string(), 4, 2))
|
||||||
)
|
)
|
||||||
.with_action(ActionDefinition::new("Attack +3".to_string()).with_roll(DiceRoll::new("Base".to_string(), 20, 1)))
|
.with_action(ActionDefinition::new("Attack +3".to_string()))
|
||||||
.with_action(ActionDefinition::new("Attack -1".to_string()))
|
.with_action(ActionDefinition::new("Attack -1".to_string()))
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -48,7 +48,6 @@ impl GameServer {
|
||||||
println!("Got message from {}: {:?}", &id, &req);
|
println!("Got message from {}: {:?}", &id, &req);
|
||||||
|
|
||||||
match req {
|
match req {
|
||||||
// ignore errors and re-login requests
|
|
||||||
api::Request::Error => {}
|
api::Request::Error => {}
|
||||||
api::Request::Login(_) => {}
|
api::Request::Login(_) => {}
|
||||||
api::Request::Message(mut msg) => {
|
api::Request::Message(mut msg) => {
|
||||||
|
|
|
@ -9,7 +9,6 @@ use entry::{Entry, Weapon};
|
||||||
pub struct Pathfinder2rCharacterSheet {
|
pub struct Pathfinder2rCharacterSheet {
|
||||||
// Genral stuff
|
// Genral stuff
|
||||||
#[Input("Name")]
|
#[Input("Name")]
|
||||||
#[Access(World)]
|
|
||||||
name: String,
|
name: String,
|
||||||
#[Input("Weapons")]
|
#[Input("Weapons")]
|
||||||
#[InputExpr(set_items, get_items)]
|
#[InputExpr(set_items, get_items)]
|
||||||
|
@ -31,7 +30,6 @@ pub struct Pathfinder2rCharacterSheet {
|
||||||
// Skills
|
// Skills
|
||||||
#[Seperator]
|
#[Seperator]
|
||||||
#[Field("Acrobatics")]
|
#[Field("Acrobatics")]
|
||||||
#[Access(PartyMember)]
|
|
||||||
#[FieldExpr(self.dex + self.acrobatics_prof * 2)]
|
#[FieldExpr(self.dex + self.acrobatics_prof * 2)]
|
||||||
_acro: i32,
|
_acro: i32,
|
||||||
#[Input("Acrobatics Prof")]
|
#[Input("Acrobatics Prof")]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use proc_macro2::{Delimiter, Group, Span, TokenStream};
|
use proc_macro2::{Delimiter, Group, Span, TokenStream};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::{parse_macro_input, Attribute, DeriveInput, Ident};
|
use syn::{parse_macro_input, DeriveInput, Ident};
|
||||||
|
|
||||||
#[proc_macro_derive(CharacterSheet, attributes(Input, InputExpr, Field, FieldExpr, Seperator, Access, AccessSet))]
|
#[proc_macro_derive(CharacterSheet, attributes(Input, InputExpr, Field, FieldExpr, Seperator))]
|
||||||
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
|
let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
|
||||||
let mut output = quote! {
|
let mut output = quote! {
|
||||||
|
@ -49,21 +49,13 @@ fn get_type_ident_set(ty: &syn::Type) -> Option<Ident> {
|
||||||
_ => panic!("Invalid data type"),
|
_ => panic!("Invalid data type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get_access_level(attrs: &Vec<Attribute>, ident: &str) -> Ident {
|
|
||||||
attrs.iter()
|
|
||||||
.find(|a| a.path.is_ident(ident))
|
|
||||||
.map(|a| a.parse_args().unwrap_or(None))
|
|
||||||
.flatten()
|
|
||||||
.unwrap_or(Ident::new(&"Owner", Span::call_site()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn impl_inputs(data: &syn::Data) -> TokenStream {
|
fn impl_inputs(data: &syn::Data) -> TokenStream {
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
fn inputs(&self, access: AccessLevel) -> Vec<(String, EntryType)>
|
fn inputs(&self) -> Vec<(String, EntryType)>
|
||||||
});
|
});
|
||||||
let mut items = TokenStream::new();
|
let mut items = TokenStream::new();
|
||||||
let mut count = 0_usize;
|
|
||||||
if let syn::Data::Struct(ds) = data {
|
if let syn::Data::Struct(ds) = data {
|
||||||
if let syn::Fields::Named(fs) = &ds.fields {
|
if let syn::Fields::Named(fs) = &ds.fields {
|
||||||
for f in &fs.named {
|
for f in &fs.named {
|
||||||
|
@ -72,17 +64,13 @@ fn impl_inputs(data: &syn::Data) -> TokenStream {
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
||||||
let exp: Option<&syn::Attribute> = f.attrs.iter().find(|a| a.path.is_ident("InputExpr"));
|
let exp: Option<&syn::Attribute> = f.attrs.iter().find(|a| a.path.is_ident("InputExpr"));
|
||||||
let access = get_access_level(&f.attrs, "AccessSet");
|
|
||||||
count += 1;
|
|
||||||
if let Some(attr) = exp {
|
if let Some(attr) = exp {
|
||||||
let exp: syn::Meta = attr.parse_meta().expect("Failed to parse MetaList!");
|
let exp: syn::Meta = attr.parse_meta().expect("Failed to parse MetaList!");
|
||||||
if let syn::Meta::List(l) = exp {
|
if let syn::Meta::List(l) = exp {
|
||||||
let from_input = &l.nested[1];
|
let from_input = &l.nested[1];
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
(#arg.to_string(), self.#from_input()),
|
||||||
v.push((#arg.to_string(), self.#from_input()));
|
})
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic!("Failed parsing InputExpr attribute, expected `(&mut self, EntryType), (&self) -> EntryType`");
|
panic!("Failed parsing InputExpr attribute, expected `(&mut self, EntryType), (&self) -> EntryType`");
|
||||||
|
@ -91,18 +79,15 @@ fn impl_inputs(data: &syn::Data) -> TokenStream {
|
||||||
else {
|
else {
|
||||||
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
(#arg.to_string(), EntryType::#t(self.#name.clone())),
|
||||||
v.push((#arg.to_string(), EntryType::#t(self.#name.clone())));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut vec = quote! { let mut v = Vec::with_capacity(#count); };
|
let mut vec = quote! { Vec::from };
|
||||||
vec.extend(items);
|
vec.append(Group::new(Delimiter::Parenthesis, Group::new(Delimiter::Bracket, items).to_token_stream()));
|
||||||
vec.extend(quote! { v });
|
|
||||||
output.append(Group::new(Delimiter::Brace, vec));
|
output.append(Group::new(Delimiter::Brace, vec));
|
||||||
|
|
||||||
output
|
output
|
||||||
|
@ -174,14 +159,13 @@ fn impl_fields(data: &syn::Data) -> TokenStream {
|
||||||
fn impl_get(data: &syn::Data) -> TokenStream {
|
fn impl_get(data: &syn::Data) -> TokenStream {
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
fn get(&self, entry: &str, access: AccessLevel) -> Option<EntryType>
|
fn get(&self, entry: &str) -> Option<EntryType>
|
||||||
});
|
});
|
||||||
let mut match_hands = TokenStream::new();
|
let mut match_hands = TokenStream::new();
|
||||||
if let syn::Data::Struct(ds) = data {
|
if let syn::Data::Struct(ds) = data {
|
||||||
if let syn::Fields::Named(fs) = &ds.fields {
|
if let syn::Fields::Named(fs) = &ds.fields {
|
||||||
for f in &fs.named {
|
for f in &fs.named {
|
||||||
let name = f.ident.clone().unwrap();
|
let name = f.ident.clone().unwrap();
|
||||||
let access = get_access_level(&f.attrs, "Access");
|
|
||||||
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
||||||
if let Some(attr) = input_attr {
|
if let Some(attr) = input_attr {
|
||||||
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
||||||
|
@ -191,7 +175,7 @@ fn impl_get(data: &syn::Data) -> TokenStream {
|
||||||
if let syn::Meta::List(l) = exp {
|
if let syn::Meta::List(l) = exp {
|
||||||
let from_input = &l.nested[1];
|
let from_input = &l.nested[1];
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { Some(self.#from_input()) } else { None },
|
#arg => Some(self.#from_input()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -201,7 +185,7 @@ fn impl_get(data: &syn::Data) -> TokenStream {
|
||||||
else {
|
else {
|
||||||
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { Some(EntryType::#t(self.#name.clone())) } else { None },
|
#arg => Some(EntryType::#t(self.#name.clone())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,13 +197,13 @@ fn impl_get(data: &syn::Data) -> TokenStream {
|
||||||
if let Some(exp) = field_expr {
|
if let Some(exp) = field_expr {
|
||||||
let exp: syn::Expr = exp.parse_args().expect("Invalid expression");
|
let exp: syn::Expr = exp.parse_args().expect("Invalid expression");
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { Some(EntryType::Number(#exp)) } else { None },
|
#arg => Some(EntryType::Number(#exp)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No expression, guess we just push this and nothing special (should prob be an input but mehhh)
|
// No expression, guess we just push this and nothing special (should prob be an input but mehhh)
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { Some(EntryType::#t(self.#name.clone())) } else { None },
|
#arg => Some(EntryType::#t(self.#name.clone())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +221,7 @@ fn impl_get(data: &syn::Data) -> TokenStream {
|
||||||
fn impl_set(data: &syn::Data) -> TokenStream {
|
fn impl_set(data: &syn::Data) -> TokenStream {
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
fn set(&mut self, entry: &str, value: EntryType, access: AccessLevel)
|
fn set(&mut self, entry: &str, value: EntryType)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut match_hands = TokenStream::new();
|
let mut match_hands = TokenStream::new();
|
||||||
|
@ -246,7 +230,6 @@ fn impl_set(data: &syn::Data) -> TokenStream {
|
||||||
for f in &fs.named {
|
for f in &fs.named {
|
||||||
let name = f.ident.clone().unwrap();
|
let name = f.ident.clone().unwrap();
|
||||||
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
||||||
let access = get_access_level(&f.attrs, "AccessSet");
|
|
||||||
if let Some(attr) = input_attr {
|
if let Some(attr) = input_attr {
|
||||||
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
||||||
let exp = f.attrs.iter().find(|a| a.path.is_ident("InputExpr"));
|
let exp = f.attrs.iter().find(|a| a.path.is_ident("InputExpr"));
|
||||||
|
@ -255,7 +238,7 @@ fn impl_set(data: &syn::Data) -> TokenStream {
|
||||||
if let syn::Meta::List(l) = exp {
|
if let syn::Meta::List(l) = exp {
|
||||||
let to_input = &l.nested[0];
|
let to_input = &l.nested[0];
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { self.#to_input(value) },
|
#arg => self.#to_input(value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -265,7 +248,7 @@ fn impl_set(data: &syn::Data) -> TokenStream {
|
||||||
else {
|
else {
|
||||||
let t = get_type_ident_set(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
let t = get_type_ident_set(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
||||||
match_hands.extend(quote! {
|
match_hands.extend(quote! {
|
||||||
#arg => if AccessLevel::#access.has_access(access) { self.#name = value.#t() },
|
#arg => self.#name = value.#t(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,20 +266,17 @@ fn impl_set(data: &syn::Data) -> TokenStream {
|
||||||
fn impl_display(data: &syn::Data) -> TokenStream {
|
fn impl_display(data: &syn::Data) -> TokenStream {
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
fn display(&self, access: AccessLevel) -> Vec<Option<(String, EntryType)>>
|
fn display(&self) -> Vec<Option<(String, EntryType)>>
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut items = TokenStream::new();
|
let mut items = TokenStream::new();
|
||||||
let mut count = 0_usize;
|
|
||||||
if let syn::Data::Struct(ds) = data {
|
if let syn::Data::Struct(ds) = data {
|
||||||
if let syn::Fields::Named(fs) = &ds.fields {
|
if let syn::Fields::Named(fs) = &ds.fields {
|
||||||
for f in &fs.named {
|
for f in &fs.named {
|
||||||
let name = f.ident.clone().unwrap();
|
let name = f.ident.clone().unwrap();
|
||||||
if f.attrs.iter().any(|a| a.path.is_ident("Seperator")) {
|
if f.attrs.iter().any(|a| a.path.is_ident("Seperator")) {
|
||||||
items.extend(quote! { v.push(None); })
|
items.extend(quote! { None, })
|
||||||
}
|
}
|
||||||
let access = get_access_level(&f.attrs, "Access");
|
|
||||||
count += 1;
|
|
||||||
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
let input_attr = f.attrs.iter().find(|a| a.path.is_ident("Input"));
|
||||||
if let Some(attr) = input_attr {
|
if let Some(attr) = input_attr {
|
||||||
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
let arg: syn::LitStr = attr.parse_args().expect("No arguments supplied for Input attribute, usage: `Input(\"Name\")`");
|
||||||
|
@ -306,9 +286,7 @@ fn impl_display(data: &syn::Data) -> TokenStream {
|
||||||
if let syn::Meta::List(l) = exp {
|
if let syn::Meta::List(l) = exp {
|
||||||
let from_input = &l.nested[1];
|
let from_input = &l.nested[1];
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
Some((#arg.to_string(), self.#from_input())),
|
||||||
v.push(Some((#arg.to_string(), self.#from_input())));
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -318,9 +296,7 @@ fn impl_display(data: &syn::Data) -> TokenStream {
|
||||||
else {
|
else {
|
||||||
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
let t = get_type_ident(&f.ty).expect(&format!("Invalid type for input: {}", name));
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
Some((#arg.to_string(), EntryType::#t(self.#name.clone()))),
|
||||||
Some((#arg.to_string(), EntryType::#t(self.#name.clone())));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,17 +308,13 @@ fn impl_display(data: &syn::Data) -> TokenStream {
|
||||||
if let Some(exp) = field_expr {
|
if let Some(exp) = field_expr {
|
||||||
let exp: syn::Expr = exp.parse_args().expect("Invalid expression");
|
let exp: syn::Expr = exp.parse_args().expect("Invalid expression");
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
Some((#arg.to_string(), EntryType::Number(#exp))),
|
||||||
Some((#arg.to_string(), EntryType::Number(#exp)));
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No expression, guess we just push this and nothing special (should prob be an input but mehhh)
|
// No expression, guess we just push this and nothing special (should prob be an input but mehhh)
|
||||||
items.extend(quote! {
|
items.extend(quote! {
|
||||||
if AccessLevel::#access.has_access(access) {
|
Some((#arg.to_string(), EntryType::#t(self.#name.clone()))),
|
||||||
Some((#arg.to_string(), EntryType::#t(self.#name.clone())));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,9 +322,8 @@ fn impl_display(data: &syn::Data) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut vec = quote! { let mut v = Vec::with_capacity(#count); };
|
let mut vec = quote! { Vec::from };
|
||||||
vec.extend( items);
|
vec.append(Group::new(Delimiter::Parenthesis, Group::new(Delimiter::Bracket, items).to_token_stream()));
|
||||||
vec.extend(quote! { v });
|
|
||||||
output.append(Group::new(Delimiter::Brace, vec));
|
output.append(Group::new(Delimiter::Brace, vec));
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
Loading…
Reference in a new issue