2012-09-24 20:45:37 +00:00
derby = require ' derby '
2013-03-23 20:03:12 +00:00
2013-04-26 21:27:20 +00:00
# Include library components
2013-03-17 04:48:00 +00:00
derby . use require ( ' derby-ui-boot ' ) , { styles: [ ] }
2013-02-12 00:27:35 +00:00
derby . use require ' ../../ui '
derby . use require ' derby-auth/components '
2012-07-27 23:38:28 +00:00
2013-04-26 21:27:20 +00:00
# Init app & reference its functions
app = derby . createApp module
{ get , view , ready } = app
2013-03-23 20:03:12 +00:00
# Translations
i18n = require ' ./i18n '
i18n . localize app ,
2013-05-12 17:58:50 +00:00
availableLocales: [ ' en ' , ' he ' , ' bg ' , ' nl ' ]
2013-03-23 20:03:12 +00:00
defaultLocale: ' en '
2013-05-09 17:07:54 +00:00
urlScheme: false
checkHeader: true
2013-03-23 20:03:12 +00:00
2013-05-22 10:07:56 +00:00
misc = require ( ' ./misc ' )
misc . viewHelpers view
2013-02-08 07:01:48 +00:00
2013-05-19 23:53:18 +00:00
_ = require ( ' lodash ' )
algos = require ' habitrpg-shared/script/algos '
helpers = require ' habitrpg-shared/script/helpers '
2012-06-20 21:30:10 +00:00
2013-04-10 22:32:38 +00:00
# ##
Cleanup task - corruption ( null tasks , rogue / invisible tasks , etc )
Obviously none of this should be happening , but we ' ll stop-gap until we can find & fix
2013-04-11 15:39:54 +00:00
Gotta love refLists ! see https : / / github . com / lefnire / habitrpg / issues / 803 & https : / / github . com / lefnire / habitrpg / issues / 6343
2013-04-10 22:32:38 +00:00
# ##
cleanupCorruptTasks = (model) ->
user = model . at ( ' _user ' )
tasks = user . get ( ' tasks ' )
## Remove corrupted tasks
_ . each tasks , (task, key) ->
2013-04-10 23:24:27 +00:00
unless task ? . id ? and task ? . type ?
2013-04-10 22:32:38 +00:00
user . del ( " tasks. #{ key } " )
delete tasks [ key ]
2013-05-22 10:29:24 +00:00
true
2013-04-10 22:32:38 +00:00
2013-04-18 23:14:05 +00:00
batch = null
2013-04-10 22:32:38 +00:00
## Task List Cleanup
2013-05-22 10:29:24 +00:00
[ ' habit ' , ' daily ' , ' todo ' , ' reward ' ] . forEach (type) ->
2013-04-10 22:32:38 +00:00
# 1. remove duplicates
# 2. restore missing zombie tasks back into list
2013-04-10 23:24:27 +00:00
idList = user . get ( " #{ type } Ids " )
2013-04-18 23:14:05 +00:00
taskIds = _ . pluck ( _ . where ( tasks , { type : type } ) , ' id ' )
2013-04-10 22:32:38 +00:00
union = _ . union idList , taskIds
# 2. remove empty (grey) tasks
2013-04-10 23:24:27 +00:00
preened = _ . filter union , (id) -> id and _ . contains ( taskIds , id )
2013-04-10 22:32:38 +00:00
# There were indeed issues found, set the new list
2013-04-11 15:49:55 +00:00
if ! _ . isEqual ( idList , preened )
2013-04-18 23:14:05 +00:00
unless batch ?
batch = new require ( ' ./character ' ) . BatchUpdate ( model )
batch . startTransaction ( )
batch . set ( " #{ type } Ids " , preened )
console . error user . get ( ' id ' ) + " ' s #{ type } s were corrupt. "
2013-05-19 23:53:18 +00:00
true
2013-04-10 22:32:38 +00:00
2013-04-18 23:14:05 +00:00
batch . commit ( ) if batch ?
2013-04-11 15:33:50 +00:00
2013-05-08 14:04:10 +00:00
# ##
Subscribe to the user , the users ' s party (meta info like party name, member ids, etc), and the party ' s members . 3 subscriptions .
# ##
setupSubscriptions = (page, model, params, next, cb) ->
uuid = model . get ( ' _userId ' ) or model . session . userId # see http://goo.gl/TPYIt
selfQ = model . query ( ' users ' ) . withId ( uuid ) #keep this for later
partyQ = model . query ( ' parties ' ) . withMember ( uuid )
2013-05-11 12:08:09 +00:00
partyQ . fetch (err, party) ->
2013-05-08 14:04:10 +00:00
return next ( err ) if err
finished = (descriptors, paths) ->
model . subscribe . apply model , descriptors . concat ->
[ err , refs ] = [ arguments [ 0 ] , arguments ]
return next ( err ) if err
2013-05-19 23:53:18 +00:00
_ . each paths , (path, idx) -> model . ref path , refs [ idx + 1 ] ; true
2013-05-08 14:04:10 +00:00
unless model . get ( ' _user ' )
console . error " User not found - this shouldn ' t be happening! "
return page . redirect ( ' /logout ' ) #delete model.session.userId
return cb ( )
# (1) Solo player
2013-05-11 12:08:09 +00:00
return finished ( [ selfQ , ' tavern ' ] , [ ' _user ' , ' _tavern ' ] ) unless party . get ( )
2013-05-08 14:04:10 +00:00
## (2) Party has members, subscribe to those users too
2013-05-11 11:13:48 +00:00
membersQ = model . query ( ' users ' ) . party ( party . get ( ' members ' ) )
# Fetch instead of subscribe. There's nothing dynamic we need from members just yet, they'll update _party instead.
# This may change in the future.
membersQ . fetch (err, members) ->
return next ( err ) if err
model . ref ' _partyMembers ' , members
2013-05-11 23:56:02 +00:00
# Note - selfQ *must* come after membersQ in subscribe, otherwise _user will only get the fields restricted by party-members in store.coffee. Strang bug, but easy to get around
return finished ( [ partyQ , selfQ , ' tavern ' ] , [ ' _party ' , ' _user ' , ' _tavern ' ] )
2013-05-08 14:04:10 +00:00
# ========== ROUTES ==========
2013-02-25 23:59:14 +00:00
get ' / ' , (page, model, params, next) ->
2013-02-21 18:40:03 +00:00
return page . redirect ' / ' if page . params ? . query ? . play ?
2013-04-18 20:53:59 +00:00
# removed force-ssl (handled in nginx), see git for code
2013-05-08 14:04:10 +00:00
setupSubscriptions page , model , params , next , ->
2013-04-18 23:14:05 +00:00
cleanupCorruptTasks ( model ) # https://github.com/lefnire/habitrpg/issues/634
2013-04-11 15:39:54 +00:00
require ( ' ./items ' ) . server ( model )
2013-04-04 19:36:52 +00:00
#refLists
_ . each [ ' habit ' , ' daily ' , ' todo ' , ' reward ' ] , (type) ->
model . refList " _ #{ type } List " , " _user.tasks " , " _user. #{ type } Ids "
2013-05-19 23:53:18 +00:00
true
2013-02-18 17:49:53 +00:00
page . render ( )
2012-04-27 02:19:31 +00:00
2013-05-08 14:04:10 +00:00
2012-07-28 01:11:53 +00:00
# ========== CONTROLLER FUNCTIONS ==========
2012-04-27 02:19:31 +00:00
ready (model) ->
2013-01-21 17:06:12 +00:00
user = model . at ( ' _user ' )
2013-05-20 09:56:38 +00:00
browser = require ' ./browser '
2013-01-29 05:02:30 +00:00
2013-04-04 20:44:54 +00:00
require ( ' ./character ' ) . app ( exports , model )
require ( ' ./tasks ' ) . app ( exports , model )
require ( ' ./items ' ) . app ( exports , model )
2013-05-02 19:16:09 +00:00
require ( ' ./party ' ) . app ( exports , model , app )
2013-04-04 20:44:54 +00:00
require ( ' ./profile ' ) . app ( exports , model )
require ( ' ./pets ' ) . app ( exports , model )
2013-01-15 19:35:10 +00:00
require ( ' ../server/private ' ) . app ( exports , model )
2013-04-08 15:24:45 +00:00
require ( ' ./debug ' ) . app ( exports , model ) if model . flags . nodeEnv != ' production '
2013-05-20 09:56:38 +00:00
browser . app ( exports , model , app )
2013-04-16 17:46:44 +00:00
require ( ' ./unlock ' ) . app ( exports , model )
2013-05-06 13:01:43 +00:00
require ( ' ./filters ' ) . app ( exports , model )
2013-05-19 23:53:18 +00:00
2013-05-21 23:40:46 +00:00
cron = ->
#return setTimeout(cron, 1) if model._txnQueue.length > 0
2013-05-22 10:07:56 +00:00
uObj = misc . hydrate ( user . get ( ) ) # need to clone, else derby won't catch model.set()'s after obj property sets
2013-05-20 09:56:38 +00:00
# habitrpg-shared/algos requires uObj.habits, uObj.dailys etc instead of uObj.tasks
_ . each [ ' habit ' , ' daily ' , ' todo ' , ' reward ' ] , (type) ->
uObj [ " #{ type } s " ] = _ . where ( uObj . tasks , { type : type } ) ; true
paths = { }
algos . cron ( uObj , paths )
lostHp = delete paths [ ' stats.hp ' ] # we'll set this manually so we can get a cool animation
_ . each paths , (v,k) -> user . pass ( { cron : true } ) . set ( k , helpers . dotGet ( k , uObj ) ) ; true
if lostHp
browser . resetDom ( model )
2013-05-21 23:40:46 +00:00
setTimeout ( -> user . set ( ' stats.hp ' , uObj . stats . hp ) ) , 750
cron ( ) if algos . shouldCron { lastCron: user . get ( ' lastCron ' ) , preferences: user . get ( ' preferences ' ) }