summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornsensfel <SpamShield0@noot-noot.org>2018-07-11 17:54:14 +0200
committernsensfel <SpamShield0@noot-noot.org>2018-07-11 17:54:14 +0200
commitfde827cba1ff3d889135c74ee1978098465fd200 (patch)
treed6022f800aa8226bf79a26a19189965c8cbfb2fe /src/battle/query
parentdf59024199c387903e3d4a901171939a358489d3 (diff)
"Battlemap" -> "Battle".
Diffstat (limited to 'src/battle/query')
-rw-r--r--src/battle/query/btl_character_turn.erl282
-rw-r--r--src/battle/query/btl_load_state.erl159
2 files changed, 441 insertions, 0 deletions
diff --git a/src/battle/query/btl_character_turn.erl b/src/battle/query/btl_character_turn.erl
new file mode 100644
index 0000000..c232ab0
--- /dev/null
+++ b/src/battle/query/btl_character_turn.erl
@@ -0,0 +1,282 @@
+-module(btl_character_turn).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-include("../../../include/yaws_api.hrl").
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export([out/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%-spec send_to_database (list(database_diff:type()), character_turn_request:type()) -> 'ok'.
+
+
+%%%% REQUEST DECODING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec decode_request (binary()) -> btl_character_turn_request:type().
+decode_request (BinaryRequest) ->
+ JSONMap = jiffy:decode(BinaryRequest, [return_maps]),
+
+ btl_character_turn_request:decode(JSONMap).
+
+%%%% USER AUTHENTICATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec authenticate_user (btl_character_turn_request:type()) -> 'ok'.
+authenticate_user (Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ SessionToken = btl_character_turn_request:get_session_token(Request),
+
+ btl_security:assert_identity(PlayerID, SessionToken),
+ btl_security:lock_queries(PlayerID),
+
+ ok.
+
+%%%% MAIN LOGIC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec fetch_data
+ (
+ btl_character_turn_request:type()
+ )
+ -> btl_character_turn_data:type().
+fetch_data (Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ BattleID = btl_character_turn_request:get_battle_id(Request),
+ CharacterIX = btl_character_turn_request:get_character_ix(Request),
+ Battle = sh_timed_cache:fetch(battle_db, PlayerID, BattleID),
+
+ btl_character_turn_data:new(Battle, CharacterIX).
+
+%%%% ASSERTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec assert_user_is_current_player
+ (
+ btl_character_turn_data:type(),
+ btl_character_turn_request:type()
+ ) -> 'ok'.
+assert_user_is_current_player (Data, Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ Battle = btl_character_turn_data:get_battle(Data),
+ CurrentPlayerTurn = btl_battle:get_current_player_turn(Battle),
+ CurrentPlayerIX = btl_player_turn:get_player_ix(CurrentPlayerTurn),
+ CurrentPlayer = btl_battle:get_player(CurrentPlayerIX, Battle),
+
+ true = (PlayerID == btl_player:get_id(CurrentPlayer)),
+
+ ok.
+
+-spec assert_user_owns_played_character
+ (
+ btl_character_turn_data:type(),
+ btl_character_turn_request:type()
+ ) -> 'ok'.
+assert_user_owns_played_character (Data, Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ Battle = btl_character_turn_data:get_battle(Data),
+ Players = btl_battle:get_players(Battle),
+ Character = btl_character_turn_data:get_character(Data),
+ CharacterPlayerIX = btl_character:get_player_index(Character),
+ CharacterPlayer = array:get(CharacterPlayerIX, Players),
+ CharacterPlayerID = btl_player:get_id(CharacterPlayer),
+
+ true = (PlayerID == CharacterPlayerID),
+
+ ok.
+
+-spec assert_character_can_be_played (btl_character_turn_data:type()) -> 'ok'.
+assert_character_can_be_played (Data) ->
+ Character = btl_character_turn_data:get_character(Data),
+
+ true = btl_character:get_is_active(Character),
+
+ ok.
+
+-spec assert_user_permissions
+ (
+ btl_character_turn_data:type(),
+ btl_character_turn_request:type()
+ ) -> 'ok'.
+assert_user_permissions (Data, Request) ->
+ assert_user_is_current_player(Data, Request),
+ assert_user_owns_played_character(Data, Request),
+ assert_character_can_be_played(Data),
+
+ ok.
+
+%%%% QUERY LOGIC HANDLING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec finalize_character
+ (
+ btl_character_turn_update:type()
+ )
+ -> btl_character_turn_update:type().
+finalize_character (Update) ->
+ Data = btl_character_turn_update:get_data(Update),
+ Character = btl_character_turn_data:get_character(Data),
+
+ DisabledCharacter = btl_character:set_is_active(false, Character),
+ UpdatedData = btl_character_turn_data:set_character(DisabledCharacter, Data),
+ FinalizedData = btl_character_turn_data:clean_battle(UpdatedData),
+
+ DBQuery =
+ sh_db_query:update_indexed
+ (
+ btl_battle:get_characters_field(),
+ btl_character_turn_data:get_character_ix(Data),
+ [ sh_db_query:set_field(btl_character:get_is_active_field(), false) ]
+ ),
+
+ S0Update = btl_character_turn_update:set_data(FinalizedData, Update),
+ S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update),
+
+ S1Update.
+
+-spec handle_actions
+ (
+ btl_character_turn_data:type(),
+ btl_character_turn_request:type()
+ )
+ -> btl_character_turn_update:type().
+handle_actions (Data, Request) ->
+ Actions = btl_character_turn_request:get_actions(Request),
+
+ EmptyUpdate = btl_character_turn_update:new(Data),
+ PostActionsUpdate =
+ lists:foldl(fun btl_turn_actions:handle/2, EmptyUpdate, Actions),
+
+ finalize_character(PostActionsUpdate).
+
+-spec update_timeline
+ (
+ btl_character_turn_update:type()
+ )
+ -> btl_character_turn_update:type().
+update_timeline (Update) ->
+ NewTimelineElements = btl_character_turn_update:get_timeline(Update),
+ Data = btl_character_turn_update:get_data(Update),
+ Battle = btl_character_turn_data:get_battle(Data),
+ PlayerTurn = btl_battle:get_current_player_turn(Battle),
+ PlayerIX = btl_player_turn:get_player_ix(PlayerTurn),
+ Player = btl_battle:get_player(PlayerIX, Battle),
+
+ UpdatedPlayer = btl_player:add_to_timeline(NewTimelineElements, Player),
+ UpdatedBattle = btl_battle:set_player(PlayerIX, UpdatedPlayer, Battle),
+ UpdatedData = btl_character_turn_data:set_battle(UpdatedBattle, Data),
+
+ DBQuery =
+ sh_db_query:update_indexed
+ (
+ btl_battle:get_players_field(),
+ PlayerIX,
+ [
+ sh_db_query:add_to_field
+ (
+ btl_player:get_timeline_field(),
+ NewTimelineElements,
+ true % We add those to the start of the list
+ )
+ ]
+ ),
+
+ S0Update = btl_character_turn_update:set_data(UpdatedData, Update),
+ S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update),
+
+ S1Update.
+
+
+-spec update_data
+ (
+ btl_character_turn_data:type(),
+ btl_character_turn_request:type()
+ )
+ -> btl_character_turn_update:type().
+update_data (Data, Request) ->
+ PostActionsUpdate = handle_actions(Data, Request),
+ PostCharacterTurnUpdate = update_timeline(PostActionsUpdate),
+
+ btl_next_turn:update_if_needed(PostCharacterTurnUpdate).
+
+%%%% DATABASE UPDATES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec send_to_database
+ (
+ btl_character_turn_update:type(),
+ btl_character_turn_request:type()
+ )
+ -> 'ok'.
+send_to_database (Update, Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ BattleID = btl_character_turn_request:get_battle_id(Request),
+ Ops = btl_character_turn_update:get_db(Update),
+ Query = sh_db_query:new(battle_db, BattleID, {user, PlayerID}, Ops),
+
+ sh_database:commit(Query),
+
+ ok.
+
+-spec send_to_cache
+ (
+ btl_character_turn_update:type(),
+ btl_character_turn_request:type()
+ )
+ -> 'ok'.
+send_to_cache (Update, Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+ BattleID = btl_character_turn_request:get_battle_id(Request),
+ Data = btl_character_turn_update:get_data(Update),
+ Battle = btl_character_turn_data:get_battle(Data),
+
+ sh_timed_cache:update(battle_db, PlayerID, BattleID, Battle),
+
+ ok.
+
+-spec commit_update
+ (
+ btl_character_turn_update:type(),
+ btl_character_turn_request:type()
+ )
+ -> 'ok'.
+commit_update (Update, Request) ->
+ send_to_database(Update, Request),
+ send_to_cache(Update, Request),
+
+ ok.
+
+%%%% USER DISCONNECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec disconnect_user (btl_character_turn_request:type()) -> 'ok'.
+disconnect_user (Request) ->
+ PlayerID = btl_character_turn_request:get_player_id(Request),
+
+ btl_security:unlock_queries(PlayerID),
+
+ ok.
+
+%%%% REPLY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec generate_reply (btl_character_turn_update:type()) -> binary().
+generate_reply (Update) ->
+ NewTimelineItems = btl_character_turn_update:get_timeline(Update),
+
+ TurnResultReply = btl_turn_results:generate(NewTimelineItems),
+
+ jiffy:encode([TurnResultReply]).
+
+%%%% MAIN LOGIC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec handle (binary()) -> binary().
+handle (EncodedRequest) ->
+ Request = decode_request(EncodedRequest),
+ authenticate_user(Request),
+ Data = fetch_data(Request),
+ assert_user_permissions(Data, Request),
+ Update = update_data(Data, Request),
+ commit_update(Update, Request),
+ disconnect_user(Request),
+ generate_reply(Update).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+out(A) ->
+ {
+ content,
+ "application/json; charset=UTF-8",
+ handle(A#arg.clidata)
+ }.
diff --git a/src/battle/query/btl_load_state.erl b/src/battle/query/btl_load_state.erl
new file mode 100644
index 0000000..f79e24e
--- /dev/null
+++ b/src/battle/query/btl_load_state.erl
@@ -0,0 +1,159 @@
+-module(btl_load_state).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-include("../../../include/yaws_api.hrl").
+
+-record
+(
+ input,
+ {
+ player_id :: btl_player:id(),
+ session_token :: binary(),
+ battle_id :: binary()
+ }
+).
+
+-record
+(
+ query_state,
+ {
+ battle :: btl_battle:type()
+ }
+).
+
+-type input() :: #input{}.
+-type query_state() :: #query_state{}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export([out/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec parse_input (binary()) -> input().
+parse_input (Req) ->
+ JSONReqMap = jiffy:decode(Req, [return_maps]),
+ PlayerID = maps:get(<<"pid">>, JSONReqMap),
+ SessionToken = maps:get(<<"stk">>, JSONReqMap),
+ BattleID = maps:get(<<"bid">>, JSONReqMap),
+
+ #input
+ {
+ player_id = PlayerID,
+ session_token = SessionToken,
+ battle_id = BattleID
+ }.
+
+-spec fetch_data (input()) -> query_state().
+fetch_data (Input) ->
+ PlayerID = Input#input.player_id,
+ BattleID = Input#input.battle_id,
+
+ Battle = sh_timed_cache:fetch(battle_db, PlayerID, BattleID),
+
+ #query_state
+ {
+ battle = Battle
+ }.
+
+-spec generate_reply(query_state(), input()) -> binary().
+generate_reply (QueryState, Input) ->
+ PlayerID = Input#input.player_id,
+ Battle = QueryState#query_state.battle,
+ Players = btl_battle:get_players(Battle),
+
+ PlayerIX =
+ sh_array_util:first
+ (
+ fun (Player) ->
+ (btl_player:get_id(Player) == PlayerID)
+ end,
+ Players
+ ),
+
+ true = (PlayerIX >= 0),
+
+ SetTimeline =
+ btl_set_timeline:generate
+ (
+ btl_battle:get_encoded_last_turns_effects(Battle)
+ ),
+
+ SetMap = btl_set_map:generate(btl_battle:get_battlemap(Battle)),
+
+ AddCharList =
+ array:sparse_to_list
+ (
+ array:map
+ (
+ fun (IX, Character) ->
+ btl_add_char:generate(IX, Character, PlayerIX)
+ end,
+ btl_battle:get_characters(Battle)
+ )
+ ),
+
+ AddWeaponList =
+ lists:map
+ (
+ fun (WeaponID) ->
+ btl_add_weapon:generate(sh_weapon:from_id(WeaponID))
+ end,
+ btl_battle:get_used_weapon_ids(Battle)
+ ),
+
+ AddArmorList =
+ lists:map
+ (
+ fun (ArmorID) ->
+ btl_add_armor:generate(sh_armor:from_id(ArmorID))
+ end,
+ btl_battle:get_used_armor_ids(Battle)
+ ),
+
+ AddTileList =
+ lists:map
+ (
+ fun (TileID) ->
+ btl_add_tile:generate(btl_tile:from_id(TileID))
+ end,
+ btl_battle:get_used_tile_ids(Battle)
+ ),
+
+ OutputList =
+ (
+ AddTileList
+ ++ [SetTimeline, SetMap | AddWeaponList]
+ ++ AddArmorList
+ ++ AddCharList
+ ),
+ Output = jiffy:encode(OutputList),
+
+ Output.
+
+-spec handle (binary()) -> binary().
+handle (Req) ->
+ Input = parse_input(Req),
+ btl_security:assert_identity
+ (
+ Input#input.player_id,
+ Input#input.session_token
+ ),
+ btl_security:lock_queries(Input#input.player_id),
+ QueryState = fetch_data(Input),
+ btl_security:unlock_queries(Input#input.player_id),
+ generate_reply(QueryState, Input).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+out(A) ->
+ {
+ content,
+ "application/json; charset=UTF-8",
+ handle(A#arg.clidata)
+ }.