Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
240a14da58 | ||
|
|
c441d75529 | ||
|
|
1bc89c1c89 | ||
|
|
43202e9917 | ||
|
|
05bc1a271d | ||
|
|
da1419d6b6 | ||
|
|
841fac38d3 | ||
|
|
2b8e23b32f | ||
|
|
5eae2bb488 | ||
|
|
6fa18c764b | ||
|
|
c9796a142d | ||
|
|
0718590f56 | ||
|
|
51f566ebf1 | ||
|
|
d2d904be7f | ||
|
|
088994f366 | ||
|
|
184b64a6af | ||
|
|
4aca035709 | ||
|
|
ebf3443e96 | ||
|
|
fd5372b35d | ||
|
|
f464558cd2 | ||
|
|
e7cd3f0549 | ||
|
|
545408a7e7 | ||
|
|
83156c30c7 | ||
|
|
636a8d061c | ||
|
|
2dbda99986 | ||
|
|
7d83552013 | ||
|
|
35bb12de6a | ||
|
|
1d1772e961 | ||
|
|
6787063ac7 | ||
|
|
9e09b8d87c | ||
|
|
2c77972073 | ||
|
|
31f4594928 | ||
|
|
eb9ac15de8 | ||
|
|
e922f3c5cc | ||
|
|
a8d08b93c5 | ||
|
|
64e118a2c8 | ||
|
|
6671541dcb | ||
|
|
962165dc8e | ||
|
|
f9b65dd892 | ||
|
|
979586d9d3 | ||
|
|
c522e60e28 | ||
|
|
f9cd38947d | ||
|
|
99b6cf2861 | ||
|
|
d925a17940 | ||
|
|
a2bbdf4645 | ||
|
|
93c98e16ac | ||
|
|
88e57b1200 | ||
|
|
1e96cf2d6c | ||
|
|
ccaf8e9842 | ||
|
|
e1f8282049 | ||
|
|
d873c4b7f1 | ||
|
|
3529bccf3a |
+7
-2
@@ -54,7 +54,7 @@ module.exports = (grunt)->
|
||||
mode: 'gzip'
|
||||
files: [
|
||||
{expand: true, cwd:'./build/static', src:'**/*.css', dest:'./dist/'}
|
||||
{expand: true, cwd:'./build/static', src:'**/*.html', dest:'./dist/'}
|
||||
{expand: true, cwd:'./build/static', src:['**/*.html', '!**/index.html'], dest:'./dist/'}
|
||||
{expand: true, cwd:'./build/static', src:'**/*.ugly.js', dest:'./dist/', ext: '.js'}
|
||||
{expand: true, cwd:'./build/static', src:'**/*.json', dest:'./dist/'}
|
||||
{expand: true, cwd:'./build/static', src:'**/*.ttf', dest:'./dist/'}
|
||||
@@ -77,7 +77,10 @@ module.exports = (grunt)->
|
||||
]
|
||||
build_to_dist:
|
||||
files: [
|
||||
{expand:true, cwd:'./build/static/', src:['**/*', '!**/*.map', '!**/*.js'], dest:'./dist'}
|
||||
expand: true
|
||||
cwd: './build/static/'
|
||||
src: ['**/*', '!**/*.map', '!**/*.js', '!index.html']
|
||||
dest: './dist'
|
||||
]
|
||||
common_source:
|
||||
files: [
|
||||
@@ -135,6 +138,8 @@ module.exports = (grunt)->
|
||||
|
||||
sass:
|
||||
all:
|
||||
options:
|
||||
sourcemap: 'none'
|
||||
files:
|
||||
'./build/static/main.css': [ './build/imports.scss' ]
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 267 B |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 300 B |
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "crafting-guide",
|
||||
"version": "3.2.2",
|
||||
"version": "3.2.4",
|
||||
"description": "A guide for building anything in Minecraft or its many mods",
|
||||
"main": "./dist/index.js",
|
||||
"repository": "http://github.com/andrewminer/crafting-guide",
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,353 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>ActiveLayerIndex</key>
|
||||
<integer>0</integer>
|
||||
<key>ApplicationVersion</key>
|
||||
<array>
|
||||
<string>com.omnigroup.OmniGraffle.MacAppStore</string>
|
||||
<string>139.18</string>
|
||||
</array>
|
||||
<key>AutoAdjust</key>
|
||||
<false/>
|
||||
<key>BackgroundGraphic</key>
|
||||
<dict>
|
||||
<key>Bounds</key>
|
||||
<string>{{0, 0}, {320, 320}}</string>
|
||||
<key>Class</key>
|
||||
<string>SolidGraphic</string>
|
||||
<key>ID</key>
|
||||
<integer>2</integer>
|
||||
<key>Style</key>
|
||||
<dict>
|
||||
<key>shadow</key>
|
||||
<dict>
|
||||
<key>Draws</key>
|
||||
<string>NO</string>
|
||||
</dict>
|
||||
<key>stroke</key>
|
||||
<dict>
|
||||
<key>Draws</key>
|
||||
<string>NO</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>BaseZoom</key>
|
||||
<integer>0</integer>
|
||||
<key>CanvasOrigin</key>
|
||||
<string>{0, 0}</string>
|
||||
<key>CanvasSize</key>
|
||||
<string>{320, 320}</string>
|
||||
<key>ColumnAlign</key>
|
||||
<integer>1</integer>
|
||||
<key>ColumnSpacing</key>
|
||||
<real>36</real>
|
||||
<key>CreationDate</key>
|
||||
<string>2016-04-23 05:39:56 +0000</string>
|
||||
<key>Creator</key>
|
||||
<string>Andrew Miner</string>
|
||||
<key>DisplayScale</key>
|
||||
<string>1 pt = 1 px</string>
|
||||
<key>GraphDocumentVersion</key>
|
||||
<integer>8</integer>
|
||||
<key>GraphicsList</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>AllowConnections</key>
|
||||
<string>NO</string>
|
||||
<key>AllowLabelDrop</key>
|
||||
<false/>
|
||||
<key>AllowToConnect</key>
|
||||
<false/>
|
||||
<key>Class</key>
|
||||
<string>LineGraphic</string>
|
||||
<key>ID</key>
|
||||
<integer>5</integer>
|
||||
<key>Points</key>
|
||||
<array>
|
||||
<string>{160, 480}</string>
|
||||
<string>{480, 160}</string>
|
||||
</array>
|
||||
<key>Style</key>
|
||||
<dict>
|
||||
<key>stroke</key>
|
||||
<dict>
|
||||
<key>Cap</key>
|
||||
<integer>0</integer>
|
||||
<key>Color</key>
|
||||
<dict>
|
||||
<key>a</key>
|
||||
<string>0.2</string>
|
||||
<key>b</key>
|
||||
<string>0</string>
|
||||
<key>g</key>
|
||||
<string>1</string>
|
||||
<key>r</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>HeadArrow</key>
|
||||
<string>0</string>
|
||||
<key>Legacy</key>
|
||||
<true/>
|
||||
<key>TailArrow</key>
|
||||
<string>0</string>
|
||||
<key>Width</key>
|
||||
<real>120</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>AllowConnections</key>
|
||||
<string>NO</string>
|
||||
<key>AllowLabelDrop</key>
|
||||
<false/>
|
||||
<key>AllowToConnect</key>
|
||||
<false/>
|
||||
<key>Class</key>
|
||||
<string>LineGraphic</string>
|
||||
<key>ID</key>
|
||||
<integer>4</integer>
|
||||
<key>Points</key>
|
||||
<array>
|
||||
<string>{-160, 160}</string>
|
||||
<string>{160, -160}</string>
|
||||
</array>
|
||||
<key>Style</key>
|
||||
<dict>
|
||||
<key>stroke</key>
|
||||
<dict>
|
||||
<key>Cap</key>
|
||||
<integer>0</integer>
|
||||
<key>Color</key>
|
||||
<dict>
|
||||
<key>a</key>
|
||||
<string>0.2</string>
|
||||
<key>b</key>
|
||||
<string>0</string>
|
||||
<key>g</key>
|
||||
<string>1</string>
|
||||
<key>r</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>HeadArrow</key>
|
||||
<string>0</string>
|
||||
<key>Legacy</key>
|
||||
<true/>
|
||||
<key>TailArrow</key>
|
||||
<string>0</string>
|
||||
<key>Width</key>
|
||||
<real>120</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>AllowConnections</key>
|
||||
<string>NO</string>
|
||||
<key>AllowLabelDrop</key>
|
||||
<false/>
|
||||
<key>AllowToConnect</key>
|
||||
<false/>
|
||||
<key>Class</key>
|
||||
<string>LineGraphic</string>
|
||||
<key>ID</key>
|
||||
<integer>3</integer>
|
||||
<key>Points</key>
|
||||
<array>
|
||||
<string>{0, 320}</string>
|
||||
<string>{320, 0}</string>
|
||||
</array>
|
||||
<key>Style</key>
|
||||
<dict>
|
||||
<key>stroke</key>
|
||||
<dict>
|
||||
<key>Cap</key>
|
||||
<integer>0</integer>
|
||||
<key>Color</key>
|
||||
<dict>
|
||||
<key>a</key>
|
||||
<string>0.2</string>
|
||||
<key>b</key>
|
||||
<string>0</string>
|
||||
<key>g</key>
|
||||
<string>1</string>
|
||||
<key>r</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>HeadArrow</key>
|
||||
<string>0</string>
|
||||
<key>Legacy</key>
|
||||
<true/>
|
||||
<key>TailArrow</key>
|
||||
<string>0</string>
|
||||
<key>Width</key>
|
||||
<real>120</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GridInfo</key>
|
||||
<dict>
|
||||
<key>GridSpacing</key>
|
||||
<real>10</real>
|
||||
<key>MajorGridSpacing</key>
|
||||
<integer>10</integer>
|
||||
<key>ShowsGrid</key>
|
||||
<string>YES</string>
|
||||
<key>SnapsToGrid</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
<key>GuidesLocked</key>
|
||||
<string>NO</string>
|
||||
<key>GuidesVisible</key>
|
||||
<string>YES</string>
|
||||
<key>HPages</key>
|
||||
<integer>1</integer>
|
||||
<key>ImageCounter</key>
|
||||
<integer>1</integer>
|
||||
<key>KeepToScale</key>
|
||||
<false/>
|
||||
<key>Layers</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>Lock</key>
|
||||
<string>NO</string>
|
||||
<key>Name</key>
|
||||
<string>Layer 1</string>
|
||||
<key>Print</key>
|
||||
<string>YES</string>
|
||||
<key>View</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LayoutInfo</key>
|
||||
<dict>
|
||||
<key>Animate</key>
|
||||
<string>NO</string>
|
||||
<key>circoMinDist</key>
|
||||
<real>18</real>
|
||||
<key>circoSeparation</key>
|
||||
<real>0.0</real>
|
||||
<key>layoutEngine</key>
|
||||
<string>dot</string>
|
||||
<key>neatoSeparation</key>
|
||||
<real>0.0</real>
|
||||
<key>twopiSeparation</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>LinksVisible</key>
|
||||
<string>NO</string>
|
||||
<key>MagnetsVisible</key>
|
||||
<string>NO</string>
|
||||
<key>MasterSheets</key>
|
||||
<array/>
|
||||
<key>ModificationDate</key>
|
||||
<string>2016-04-27 03:11:38 +0000</string>
|
||||
<key>Modifier</key>
|
||||
<string>Andrew Miner</string>
|
||||
<key>NotesVisible</key>
|
||||
<string>NO</string>
|
||||
<key>Orientation</key>
|
||||
<integer>2</integer>
|
||||
<key>OriginVisible</key>
|
||||
<string>NO</string>
|
||||
<key>PageBreaks</key>
|
||||
<string>NO</string>
|
||||
<key>PrintInfo</key>
|
||||
<dict>
|
||||
<key>NSBottomMargin</key>
|
||||
<array>
|
||||
<string>float</string>
|
||||
<string>41</string>
|
||||
</array>
|
||||
<key>NSHorizonalPagination</key>
|
||||
<array>
|
||||
<string>coded</string>
|
||||
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
|
||||
</array>
|
||||
<key>NSLeftMargin</key>
|
||||
<array>
|
||||
<string>float</string>
|
||||
<string>18</string>
|
||||
</array>
|
||||
<key>NSPaperSize</key>
|
||||
<array>
|
||||
<string>size</string>
|
||||
<string>{611.99998474121094, 792}</string>
|
||||
</array>
|
||||
<key>NSPrintReverseOrientation</key>
|
||||
<array>
|
||||
<string>int</string>
|
||||
<string>0</string>
|
||||
</array>
|
||||
<key>NSRightMargin</key>
|
||||
<array>
|
||||
<string>float</string>
|
||||
<string>18</string>
|
||||
</array>
|
||||
<key>NSTopMargin</key>
|
||||
<array>
|
||||
<string>float</string>
|
||||
<string>18</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>PrintOnePage</key>
|
||||
<false/>
|
||||
<key>ReadOnly</key>
|
||||
<string>NO</string>
|
||||
<key>RowAlign</key>
|
||||
<integer>1</integer>
|
||||
<key>RowSpacing</key>
|
||||
<real>36</real>
|
||||
<key>SheetTitle</key>
|
||||
<string>Canvas 1</string>
|
||||
<key>SmartAlignmentGuidesActive</key>
|
||||
<string>YES</string>
|
||||
<key>SmartDistanceGuidesActive</key>
|
||||
<string>YES</string>
|
||||
<key>UniqueID</key>
|
||||
<integer>1</integer>
|
||||
<key>UseEntirePage</key>
|
||||
<false/>
|
||||
<key>VPages</key>
|
||||
<integer>1</integer>
|
||||
<key>WindowInfo</key>
|
||||
<dict>
|
||||
<key>CurrentSheet</key>
|
||||
<integer>0</integer>
|
||||
<key>ExpandedCanvases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Canvas 1</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Frame</key>
|
||||
<string>{{215, 0}, {2134, 1417}}</string>
|
||||
<key>ListView</key>
|
||||
<true/>
|
||||
<key>OutlineWidth</key>
|
||||
<integer>142</integer>
|
||||
<key>RightSidebar</key>
|
||||
<false/>
|
||||
<key>ShowRuler</key>
|
||||
<true/>
|
||||
<key>Sidebar</key>
|
||||
<true/>
|
||||
<key>SidebarWidth</key>
|
||||
<integer>120</integer>
|
||||
<key>VisibleRegion</key>
|
||||
<string>{{-840, -477}, {1999, 1275}}</string>
|
||||
<key>Zoom</key>
|
||||
<real>1</real>
|
||||
<key>ZoomValues</key>
|
||||
<array>
|
||||
<array>
|
||||
<string>Canvas 1</string>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,18 @@
|
||||
//-
|
||||
//- Crafting Guide - _google_sitelinks.jade
|
||||
//-
|
||||
//- Copyright © 2014-2016 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
script(type="application/ld+json").
|
||||
{
|
||||
"@context": "http://schema.org",
|
||||
"@type": "WebSite",
|
||||
"url": "http://crafting-guide.com/",
|
||||
"potentialAction": {
|
||||
"@type": "SearchAction",
|
||||
"target": "http://crafting-guide.com?search={search_term}",
|
||||
"query-input": "required name=search_term"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
script.
|
||||
! function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0],
|
||||
p = /^http:/.test(d.location) ? 'http' : 'https';
|
||||
if (!d.getElementById(id)) {
|
||||
js = d.createElement(s);
|
||||
js.id = id;
|
||||
js.src = p + '://platform.twitter.com/widgets.js';
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}
|
||||
}(document, 'script', 'twitter-wjs');
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
module.exports = class BaseModel extends Backbone.Model
|
||||
|
||||
@_loadingQueue = []
|
||||
@_isDraining = false
|
||||
|
||||
constructor: (attributes={}, options={})->
|
||||
options.logEvents ?= true
|
||||
super attributes, options
|
||||
@@ -19,10 +22,10 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
continue if name is 'id'
|
||||
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
|
||||
|
||||
@fileCache = options.fileCache or null
|
||||
@loading = null
|
||||
@logEvents = options.logEvents or false
|
||||
@state = c.modelState.unloaded
|
||||
|
||||
@loading = null
|
||||
@state = c.modelState.unloaded
|
||||
|
||||
Object.defineProperties this,
|
||||
isUnloaded: { get:-> @state is c.modelState.unloaded }
|
||||
@@ -60,12 +63,23 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
|
||||
@state = c.modelState.loading
|
||||
@trigger c.event.request, this
|
||||
@loading = w.promise (resolve, reject)=>
|
||||
$.ajax
|
||||
url: url
|
||||
dataType: 'text'
|
||||
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
|
||||
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
|
||||
|
||||
loadFromServer = =>
|
||||
w.promise (resolve, reject)=>
|
||||
$.ajax
|
||||
url: url
|
||||
dataType: 'text'
|
||||
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
|
||||
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
|
||||
|
||||
if @fileCache?
|
||||
@loading = @fileCache.loading.then =>
|
||||
if @fileCache.hasFile url
|
||||
return @_addToLoadingQueue @fileCache.getFile(url), 'success', {url:url}
|
||||
else
|
||||
@loading = loadFromServer()
|
||||
else
|
||||
@loading = loadFromServer()
|
||||
|
||||
@loading.catch (e)-> # do nothing
|
||||
return @loading
|
||||
@@ -86,3 +100,30 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
|
||||
toString: ->
|
||||
return "#{@constructor.name}.#{@cid}"
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_addToLoadingQueue: (text, status, xhr)->
|
||||
deferred = w.defer()
|
||||
|
||||
BaseModel._loadingQueue.push resolve:deferred.resolve, func:(=> @onLoadSucceeded text, status, xhr)
|
||||
@_drainLoadingQueue()
|
||||
return deferred.promise
|
||||
|
||||
_drainLoadingQueue: ->
|
||||
return if @_isDraining
|
||||
@_isDraining = true
|
||||
|
||||
drainDelay = 50
|
||||
drain = =>
|
||||
toLoad = BaseModel._loadingQueue.shift()
|
||||
if not toLoad?
|
||||
@_isDraining = false
|
||||
else
|
||||
toLoad.func()
|
||||
toLoad.resolve(true)
|
||||
|
||||
_.delay drain, drainDelay
|
||||
|
||||
_.delay drain, drainDelay
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ module.exports = class CraftingPlan
|
||||
@_rawScores = {}
|
||||
@_scores = {}
|
||||
@_steps = steps
|
||||
@_tools = null
|
||||
@_want = want
|
||||
|
||||
@_numberSteps()
|
||||
@@ -37,19 +38,32 @@ module.exports = class CraftingPlan
|
||||
@_made = new SimpleInventory modPack:@_modPack
|
||||
@_made.addInventory @_have
|
||||
|
||||
@_tools = new SimpleInventory modPack:@_modPack
|
||||
|
||||
for i in [@_steps.length-1..0] by -1
|
||||
step = @_steps[i]
|
||||
step.multiplier = 0
|
||||
recipe = step.recipe
|
||||
|
||||
for stack in step.recipe.output
|
||||
if not stack?
|
||||
throw new Error 'stack should not be null here'
|
||||
|
||||
continue if recipe.isPassThroughFor stack.itemSlug
|
||||
qualifiedSlug = @_modPack.qualifySlug stack.itemSlug
|
||||
|
||||
while @_need.quantityOf(qualifiedSlug) > 0
|
||||
@_executeStep step
|
||||
|
||||
if step.multiplier > 0
|
||||
for stack in step.recipe.output
|
||||
qualifiedSlug = @_modPack.qualifySlug stack.itemSlug
|
||||
continue unless recipe.isPassThroughFor stack.itemSlug
|
||||
continue if @_made.hasAtLeast qualifiedSlug, 1
|
||||
continue if @_need.hasAtLeast qualifiedSlug, 1
|
||||
continue if @_tools.hasAtLeast qualifiedSlug, 1
|
||||
@_need.add qualifiedSlug, 1
|
||||
@_tools.add qualifiedSlug, 1
|
||||
|
||||
@_made.addInventory @_want
|
||||
@_made.addInventory @_tools
|
||||
@_pruneEmptySteps()
|
||||
@_numberSteps()
|
||||
|
||||
|
||||
@@ -63,6 +63,22 @@ describe 'crafting_plan.coffee', ->
|
||||
'1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot'
|
||||
]
|
||||
|
||||
it 'uses the correct amount of passthrough items', ->
|
||||
plans = fixtures.makePlans [10, 'test__split_oak_wood'], [10, 'test__split_spruce_wood']
|
||||
plan = plans[2]
|
||||
plan.computeRequired()
|
||||
|
||||
plan.need.unparse().should.equal 'coal:8.iron_ore:6.oak_wood:5.spruce_wood'
|
||||
plan.made.unparse().should.equal '4.iron_ingot:maul:2.oak_planks:10.split_oak_wood:10.split_spruce_wood:stick'
|
||||
(s.toString() for s in plan.steps).should.eql [
|
||||
'1x test__oak_wood>... .0. ...>>4 test__oak_planks'
|
||||
'1x test__oak_planks>.0. .0. ...>>4 test__stick'
|
||||
'1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot'
|
||||
'1x test__iron_ingot,test__stick>001 001 ..1>test__crafting_table>test__maul'
|
||||
'5x test__spruce_wood,test__maul>.1. .0. ...>>2 test__split_spruce_wood,test__maul'
|
||||
'5x test__oak_wood,test__maul>.1. .0. ...>>2 test__split_oak_wood,test__maul'
|
||||
]
|
||||
|
||||
it 'can compute multiple items with multiple plans', ->
|
||||
plans = fixtures.makePlans [1, 'test__copper_block'], [1, 'test__iron_sword']
|
||||
plans.length.should.equal 4
|
||||
|
||||
@@ -27,10 +27,11 @@ module.exports = class CraftingStep
|
||||
|
||||
addToolsTo: (targetInventory)->
|
||||
for stack in @_recipe.tools
|
||||
targetInventory.add stack.itemSlug, stack.quantity
|
||||
targetInventory.add stack.itemSlug, stack.quantity, insert:true
|
||||
|
||||
completeInto: (targetInventory)->
|
||||
for stack in @_recipe.output
|
||||
continue if @_recipe.isPassThroughFor stack.itemSlug
|
||||
quantity = @_recipe.getQuantityProduced stack.itemSlug
|
||||
targetInventory.add stack.itemSlug, quantity * @_multiplier
|
||||
|
||||
@@ -67,4 +68,6 @@ module.exports = class CraftingStep
|
||||
@_inventory = new SimpleInventory
|
||||
for stack in @_recipe.input
|
||||
qualifiedSlug = @_modPack.qualifySlug stack.itemSlug
|
||||
@_inventory.add qualifiedSlug, @multiplier * @_recipe.getQuantityRequired stack.itemSlug
|
||||
required = @_recipe.getQuantityRequired(stack.itemSlug) - @_recipe.getQuantityProduced(stack.itemSlug)
|
||||
required = if required > 0 then required * @multiplier else 1
|
||||
@_inventory.add qualifiedSlug, required
|
||||
|
||||
@@ -22,57 +22,43 @@ module.exports = class Craftsman extends BaseModel
|
||||
@::PLAN_STEP_INCREMENT = 39
|
||||
|
||||
@::STAGE =
|
||||
WAITING: 'waiting'
|
||||
EMPTY: 'empty'
|
||||
READY: 'ready'
|
||||
GRAPHING: 'examining recipes'
|
||||
PLANNING: 'computing plans'
|
||||
ANALYZING: 'analyzing plans'
|
||||
COMPLETE: 'complete'
|
||||
INVALID: 'invalid'
|
||||
OUTDATED: 'outdated'
|
||||
|
||||
constructor: (modPack)->
|
||||
if not modPack? then throw new Error 'modPack is required'
|
||||
attributes =
|
||||
paused: false
|
||||
stage: @STAGE.WAITING
|
||||
stage: @STAGE.READY
|
||||
stageCount: 0
|
||||
super attributes, {}
|
||||
|
||||
@_modPack = modPack
|
||||
|
||||
reset = _.debounce (=> @reset()), 100
|
||||
reevaluatePlans = _.debounce (=> @reevaluatePlans()), 100
|
||||
|
||||
@_have = new Inventory modPack:@_modPack
|
||||
@_have.on c.event.change, reevaluatePlans
|
||||
@_have.on c.event.change, => @_resetStage()
|
||||
|
||||
@_want = new Inventory modPack:@_modPack
|
||||
@_want.on c.event.change, reset
|
||||
@_want.on c.event.change, => @_resetStage()
|
||||
|
||||
@on c.event.change + ':paused', reset
|
||||
@on c.event.change + ':stage', => logger.info "Craftsman has started #{@stage}..."
|
||||
@on 'scheduleNextWork', => @_scheduleNextWork()
|
||||
@reset()
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
reevaluatePlans: ->
|
||||
@_plans = null
|
||||
@_planEvaluator = null
|
||||
@stage = @STAGE.WAITING
|
||||
@stageCount = 0
|
||||
|
||||
@_scheduleNextWork()
|
||||
|
||||
reset: ->
|
||||
@_graphBuilder = null
|
||||
@_planBuilder = null
|
||||
@_planEvaluator = null
|
||||
@_plans = null
|
||||
|
||||
@stage = @STAGE.WAITING
|
||||
@stageCount = 0
|
||||
|
||||
@_scheduleNextWork()
|
||||
@_resetStage()
|
||||
|
||||
work: ->
|
||||
return if @_want.isEmpty
|
||||
@@ -130,7 +116,7 @@ module.exports = class Craftsman extends BaseModel
|
||||
Object.defineProperties @prototype,
|
||||
|
||||
complete:
|
||||
get: -> @stage in [@STAGE.COMPLETE, @STAGE.INVALID]
|
||||
get: -> @stage in [@STAGE.COMPLETE, @STAGE.INVALID, @STAGE.OUTDATED]
|
||||
|
||||
have:
|
||||
get: -> @_have
|
||||
@@ -143,8 +129,19 @@ module.exports = class Craftsman extends BaseModel
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_resetStage: ->
|
||||
@stageCount = 0
|
||||
|
||||
if @want.isEmpty
|
||||
if @stage isnt @STAGE.EMPTY
|
||||
@stage = @STAGE.EMPTY
|
||||
@reset()
|
||||
else if not @_plans?
|
||||
@stage = @STAGE.READY
|
||||
else
|
||||
@stage = @STAGE.OUTDATED
|
||||
|
||||
_scheduleNextWork: ->
|
||||
return if @paused
|
||||
return if @want.isEmpty
|
||||
return if @complete
|
||||
|
||||
|
||||
@@ -98,6 +98,12 @@ MOD_VERSION_FILE =
|
||||
input: Stick, Cobblestone
|
||||
pattern: .0. .1. ...
|
||||
|
||||
item: Maul
|
||||
recipe:
|
||||
input: Iron Ingot, Stick
|
||||
pattern: 001 001 ..1
|
||||
tools: Crafting Table
|
||||
|
||||
item: Oak Planks
|
||||
recipe:
|
||||
input: Oak Wood
|
||||
@@ -107,12 +113,29 @@ MOD_VERSION_FILE =
|
||||
item: Oak Wood
|
||||
gatherable: yes
|
||||
|
||||
item: Spruce Wood
|
||||
gatherable: yes
|
||||
|
||||
item: Stick
|
||||
recipe:
|
||||
input: Oak Planks
|
||||
pattern: .0. .0. ...
|
||||
quantity: 4
|
||||
|
||||
item: Split Oak Wood
|
||||
recipe:
|
||||
extras: Maul
|
||||
input: Oak Wood, Maul
|
||||
pattern: .1. .0. ...
|
||||
quantity: 2
|
||||
|
||||
item: Split Spruce Wood
|
||||
recipe:
|
||||
extras: Maul
|
||||
input: Spruce Wood, Maul
|
||||
pattern: .1. .0. ...
|
||||
quantity: 2
|
||||
|
||||
item: String
|
||||
gatherable: yes
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ module.exports = class SimpleInventory
|
||||
@_itemSlugs = []
|
||||
|
||||
clone: ->
|
||||
inventory = new Inventory
|
||||
inventory = new SimpleInventory
|
||||
inventory.addInventory this
|
||||
return inventory
|
||||
|
||||
@@ -79,7 +79,7 @@ module.exports = class SimpleInventory
|
||||
|
||||
if qualifiedSlug?
|
||||
newSlugs.push qualifiedSlug
|
||||
newStacks.push new Stack itemSlug:qualifiedSlug, quantity:stack.quantity
|
||||
newStacks.push new SimpleStack itemSlug:qualifiedSlug, quantity:stack.quantity
|
||||
else
|
||||
newSlugs.push itemSlug
|
||||
newStacks.push stack
|
||||
@@ -130,9 +130,9 @@ module.exports = class SimpleInventory
|
||||
parse: (data)->
|
||||
return this if not data? or data.length is 0
|
||||
|
||||
stacks = data.split Inventory.Delimiters.Stack
|
||||
stacks = data.split SimpleInventory.Delimiters.Stack
|
||||
for stackText in stacks
|
||||
stackParts = stackText.split Inventory.Delimiters.Item
|
||||
stackParts = stackText.split SimpleInventory.Delimiters.Item
|
||||
if stackParts.length is 2
|
||||
quantity = parseInt stackParts[0], 10
|
||||
itemSlug = ItemSlug.slugify stackParts[1]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
###
|
||||
#
|
||||
# Crafting Guide - event_recorder.coffee
|
||||
#
|
||||
# Copyright (c) 2014-2015 by Redwood Labs
|
||||
# Copyright © 2014-2016 by Redwood Labs
|
||||
# All rights reserved.
|
||||
###
|
||||
#
|
||||
|
||||
util = require 'util'
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@ module.exports = class Inventory extends BaseModel
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
add: (itemSlug, quantity=1)->
|
||||
add: (itemSlug, quantity=1, options={})->
|
||||
return this unless quantity > 0
|
||||
|
||||
@_add itemSlug, quantity
|
||||
@_add itemSlug, quantity, options
|
||||
@trigger c.event.add, this, itemSlug, quantity
|
||||
@trigger c.event.change, this
|
||||
return this
|
||||
@@ -141,6 +141,18 @@ module.exports = class Inventory extends BaseModel
|
||||
@trigger c.event.change, this
|
||||
return this
|
||||
|
||||
toDescription: ->
|
||||
return null if @isEmpty
|
||||
return null unless @modPack?
|
||||
|
||||
item = @modPack.findItem @_itemSlugs[0]
|
||||
extras = @_itemSlugs.length - 1
|
||||
|
||||
result = "#{item.name}"
|
||||
if extras > 0 then result += " and #{extras} more..."
|
||||
|
||||
return result
|
||||
|
||||
# Parsing Methods ##############################################################################
|
||||
|
||||
parse: (data)->
|
||||
@@ -209,7 +221,8 @@ module.exports = class Inventory extends BaseModel
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_add: (itemSlug, quantity=1)->
|
||||
_add: (itemSlug, quantity=1, options={})->
|
||||
options.insert ?= false
|
||||
return unless itemSlug?
|
||||
return unless quantity > 0
|
||||
|
||||
@@ -218,7 +231,10 @@ module.exports = class Inventory extends BaseModel
|
||||
stack = new Stack itemSlug:itemSlug, quantity:quantity
|
||||
@listenTo stack, c.event.change, => @trigger c.event.change, this
|
||||
@_stacks[itemSlug] = stack
|
||||
@_itemSlugs.push itemSlug
|
||||
if options.insert
|
||||
@_itemSlugs.unshift itemSlug
|
||||
else
|
||||
@_itemSlugs.push itemSlug
|
||||
@_sort()
|
||||
else
|
||||
stack.quantity += quantity
|
||||
|
||||
@@ -29,8 +29,6 @@ module.exports = class Mod extends BaseModel
|
||||
@_modVersions = []
|
||||
@_tutorials = []
|
||||
|
||||
@once c.event.sync, => @_verifyActiveModVersion()
|
||||
|
||||
# Class Methods ##################################################################################
|
||||
|
||||
@Version: Version =
|
||||
@@ -95,6 +93,12 @@ module.exports = class Mod extends BaseModel
|
||||
|
||||
# Item Methods #################################################################################
|
||||
|
||||
chooseRandomItem: ->
|
||||
effectiveModVersion = @_activeModVersion or @getModVersion Mod.Version.Latest
|
||||
return null unless effectiveModVersion?
|
||||
|
||||
return effectiveModVersion.chooseRandomItem()
|
||||
|
||||
eachItem: (callback)->
|
||||
effectiveModVersion = @_activeModVersion or @getModVersion Mod.Version.Latest
|
||||
effectiveModVersion.eachItem callback
|
||||
@@ -129,6 +133,7 @@ module.exports = class Mod extends BaseModel
|
||||
|
||||
@_modVersions.push modVersion
|
||||
@listenTo modVersion, c.event.change, => @trigger c.event.change, this
|
||||
modVersion.fileCache = this.fileCache
|
||||
modVersion.mod = this
|
||||
|
||||
@trigger c.event.add + ':modVersion', modVersion, this
|
||||
@@ -143,6 +148,9 @@ module.exports = class Mod extends BaseModel
|
||||
for modVersion in @_modVersions
|
||||
callback modVersion
|
||||
|
||||
getAllModVersions: ->
|
||||
return @_modVersions[..]
|
||||
|
||||
getModVersion: (version)->
|
||||
return null if version is Mod.Version.None
|
||||
return @_modVersions[0] if version is Mod.Version.Latest
|
||||
@@ -201,6 +209,8 @@ module.exports = class Mod extends BaseModel
|
||||
@_parser ?= new ModParser model:this
|
||||
@_parser.parse text
|
||||
|
||||
@_verifyActiveModVersion()
|
||||
|
||||
return null # prevent calling `set`
|
||||
|
||||
url: ->
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#
|
||||
|
||||
BaseModel = require '../base_model'
|
||||
Inventory = require './inventory'
|
||||
Mod = require './mod'
|
||||
ModVersionParser = require '../parsing/mod_version_parser'
|
||||
Recipe = require './recipe'
|
||||
SimpleInventory = require '../crafting/simple_inventory'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -24,6 +25,12 @@ module.exports = class ModPack extends BaseModel
|
||||
|
||||
# Item Methods #################################################################################
|
||||
|
||||
chooseRandomItem: ->
|
||||
return null unless @_mods.length > 0
|
||||
|
||||
modIndex = Math.floor Math.random() * @_mods.length
|
||||
return @_mods[modIndex].chooseRandomItem()
|
||||
|
||||
findItem: (itemSlug, options={})->
|
||||
options.includeDisabled ?= false
|
||||
|
||||
@@ -75,7 +82,7 @@ module.exports = class ModPack extends BaseModel
|
||||
result.modSlug = @_mods[0].slug
|
||||
result.modVersion = @_mods[0].activeVersion
|
||||
|
||||
craftingUrlInventory = new Inventory modPack:this
|
||||
craftingUrlInventory = new SimpleInventory modPack:this
|
||||
if item?.multiblock?
|
||||
craftingUrlInventory.addInventory item.multiblock.inventory
|
||||
else
|
||||
@@ -165,12 +172,18 @@ module.exports = class ModPack extends BaseModel
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_onModVersionLoaded: (modVersion)->
|
||||
working = true
|
||||
@eachMod (mod)->
|
||||
mod.eachModVersion (modVersion)->
|
||||
working = working and (modVersion.isUnloaded or modVersion.isLoading)
|
||||
mods = @getAllMods()
|
||||
return true unless mods.length > 0
|
||||
|
||||
return if working
|
||||
for mod in mods
|
||||
modVersions = mod.getAllModVersions()
|
||||
return true unless modVersions.length > 0
|
||||
continue if mod.activeVersion is Mod.Version.None
|
||||
|
||||
activeModVersion = mod.activeModVersion
|
||||
return true unless activeModVersion?
|
||||
return true if activeModVersion.isUnloaded
|
||||
return true if activeModVersion.isLoading
|
||||
|
||||
@trigger c.event.change, this
|
||||
@trigger c.event.sync, this
|
||||
|
||||
@@ -59,6 +59,10 @@ module.exports = class ModVersion extends BaseModel
|
||||
return null if result.length is 0
|
||||
return result
|
||||
|
||||
chooseRandomItem: ->
|
||||
itemIndex = Math.floor Math.random() * @_slugs.length
|
||||
return @_slugs[itemIndex]
|
||||
|
||||
eachItem: (callback)->
|
||||
for slug in @_slugs
|
||||
item = @findItem slug
|
||||
|
||||
@@ -103,7 +103,7 @@ module.exports = class Recipe extends BaseModel
|
||||
if modPack?.findItemByName(@condition.noun)?
|
||||
result = true
|
||||
else if @condition.verb is 'mod'
|
||||
modPack.eachMod (mod)->
|
||||
modPack.eachMod (mod)=>
|
||||
if mod.name is @condition.noun
|
||||
result = true
|
||||
|
||||
@@ -111,16 +111,7 @@ module.exports = class Recipe extends BaseModel
|
||||
return result
|
||||
|
||||
isPassThroughFor: (itemSlug)->
|
||||
amountCreated = 0
|
||||
for stack in @output
|
||||
if stack.itemSlug.matches itemSlug
|
||||
amountCreated += stack.quantity
|
||||
|
||||
for stack in @input
|
||||
if stack.itemSlug.matches itemSlug
|
||||
amountCreated -= stack.quantity
|
||||
|
||||
return amountCreated <= 0
|
||||
return @getQuantityProduced(itemSlug) is @getQuantityRequired(itemSlug)
|
||||
|
||||
produces: (itemSlug)->
|
||||
if not @_produces?
|
||||
@@ -221,7 +212,11 @@ module.exports = class Recipe extends BaseModel
|
||||
_computeQuantities: (pattern)->
|
||||
quantityMap = {}
|
||||
|
||||
for c in pattern.split ''
|
||||
index = 0
|
||||
while index < pattern.length
|
||||
c = pattern[index]
|
||||
index += 1
|
||||
|
||||
continue if c is '.'
|
||||
continue if c is ' '
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ module.exports = class CraftPage extends BaseModel
|
||||
inventory.each (stack)=>
|
||||
item = @modPack.findItem stack.itemSlug, enableAsNeeded:true
|
||||
return unless item? and item.isCraftable
|
||||
|
||||
@craftsman.want.add stack.itemSlug, stack.quantity
|
||||
inventory.remove stack.itemSlug
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#
|
||||
# Crafting Guide - file_cache.coffee
|
||||
#
|
||||
# Copyright © 2014-2016 by Redwood Labs
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class FileCache extends Backbone.Events
|
||||
|
||||
@::FILE_TOKEN = '#file='
|
||||
|
||||
constructor: (url)->
|
||||
@_ajax = $.ajax
|
||||
@_files = {}
|
||||
@_loading = w.resolve(true)
|
||||
|
||||
if url? then @loadArchive(url).catch(->)
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
getFile: (file)->
|
||||
return null unless @hasFile file
|
||||
return @_files[file]
|
||||
|
||||
hasFile: (file)->
|
||||
return @_files[file]?
|
||||
|
||||
loadArchive: (url)->
|
||||
if not _.isFunction(@_ajax) then throw new Error '$.ajax is required'
|
||||
|
||||
newLoading = w.promise (resolve, reject)=>
|
||||
@_ajax
|
||||
url: url
|
||||
dataType: 'text'
|
||||
success: (text, status, xhr)=> resolve @_onLoadSuccess text, status, xhr
|
||||
error: (xhr, status, error)=> resolve @_onLoadError error, status, xhr
|
||||
|
||||
@_loading = w.join @_loading, newLoading
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
Object.defineProperties @prototype,
|
||||
|
||||
loading:
|
||||
get: -> return @_loading
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_onLoadError: (error, status, xhr)->
|
||||
console.error "Failed to load archive: #{xhr.responseText}"
|
||||
return false
|
||||
|
||||
_onLoadSuccess: (text, status, xhr)->
|
||||
return @_parseArchive text
|
||||
|
||||
_parseArchive: (text)->
|
||||
file = null
|
||||
tokenIndex = nameStartIndex = nameEndIndex = fileStartIndex = fileEndIndex = 0
|
||||
fileCount = 0
|
||||
|
||||
while true
|
||||
tokenIndex = text.indexOf @FILE_TOKEN, fileStartIndex
|
||||
if tokenIndex is -1
|
||||
if file?
|
||||
@_files[file] = text.substring fileStartIndex, text.length
|
||||
fileCount += 1
|
||||
break
|
||||
|
||||
if file?
|
||||
fileEndIndex = tokenIndex
|
||||
@_files[file] = text.substring fileStartIndex, fileEndIndex
|
||||
fileCount += 1
|
||||
|
||||
nameStartIndex = tokenIndex + @FILE_TOKEN.length
|
||||
nameEndIndex = text.indexOf '\n', nameStartIndex
|
||||
if nameEndIndex is -1
|
||||
file = text.substring nameStartIndex, text.length
|
||||
@_files[file] = ''
|
||||
break
|
||||
|
||||
file = text.substring nameStartIndex, nameEndIndex
|
||||
fileStartIndex = nameEndIndex + '\n'.length
|
||||
|
||||
return fileCount > 0
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
FileCache = require './file_cache'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
describe 'file_cache.coffee', ->
|
||||
|
||||
beforeEach ->
|
||||
@cache = new FileCache
|
||||
|
||||
makeTestAjax = (text)->
|
||||
return (options)->
|
||||
options.success text, 'success', {url:options.url}
|
||||
|
||||
it 'can load an archive with a single file', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie delta'
|
||||
@cache.loadArchive 'http://test'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie delta'
|
||||
|
||||
it 'can load an archive with multiple files', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
|
||||
@cache.loadArchive 'http://test'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie\n'
|
||||
@cache.hasFile('delta').should.equal true
|
||||
@cache.getFile('delta').should.equal 'echo foxtrot'
|
||||
|
||||
it 'can load an archive without newlines', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie#file=delta\necho foxtrot'
|
||||
@cache.loadArchive 'http://test'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie'
|
||||
@cache.hasFile('delta').should.equal true
|
||||
@cache.getFile('delta').should.equal 'echo foxtrot'
|
||||
|
||||
it 'can cope with an empty file in the middle of an archive', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\n#file=echo\nfoxtrot golf'
|
||||
@cache.loadArchive 'http://test'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie\n'
|
||||
@cache.hasFile('delta').should.equal true
|
||||
@cache.getFile('delta').should.equal ''
|
||||
@cache.hasFile('echo').should.equal true
|
||||
@cache.getFile('echo').should.equal 'foxtrot golf'
|
||||
|
||||
it 'can cope with an empty file at the end of an archive', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta'
|
||||
@cache.loadArchive 'http://test'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie\n'
|
||||
@cache.hasFile('delta').should.equal true
|
||||
@cache.getFile('delta').should.equal ''
|
||||
|
||||
it 'can load multiple, non-overlapping archives', ->
|
||||
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
|
||||
@cache.loadArchive 'http://test'
|
||||
|
||||
@cache._ajax = makeTestAjax '#file=golf\nhotel india'
|
||||
@cache.loadArchive 'http://test2'
|
||||
.then =>
|
||||
@cache.hasFile('alpha').should.equal true
|
||||
@cache.getFile('alpha').should.equal 'bravo charlie\n'
|
||||
@cache.hasFile('delta').should.equal true
|
||||
@cache.getFile('delta').should.equal 'echo foxtrot'
|
||||
@cache.hasFile('golf').should.equal true
|
||||
@cache.getFile('golf').should.equal 'hotel india'
|
||||
@@ -47,6 +47,7 @@ module.exports = class ItemPage extends BaseModel
|
||||
mod.eachRecipe (recipe)=>
|
||||
if isAcceptable recipe
|
||||
for outputStack in recipe.output
|
||||
continue if recipe.isPassThroughFor outputStack.itemSlug
|
||||
outputItem = @modPack.findItem outputStack.itemSlug, includeDisabled:true
|
||||
result[outputItem.slug] = outputItem
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
.content.view__browse_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
.tile_container
|
||||
@@ -10,14 +10,32 @@
|
||||
|
||||
.right {
|
||||
.tile_container {
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
justify-content : space-between;
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
|
||||
.view__mod_tile {
|
||||
max-width : calc(50% - 12px); // $size-margin-large / 2
|
||||
flex : 1 1 calc(50% - 12px); // $size-margin-large / 2
|
||||
margin-right : $size-margin-medium;
|
||||
margin-bottom : $size-margin-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(tablet) {
|
||||
.view__browse_page {
|
||||
.right {
|
||||
.tile_container {
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-items: stretch;
|
||||
|
||||
.view__mod_tile {
|
||||
flex: 0 0 auto;
|
||||
margin-right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
ModTileController = require './mod_tile/mod_tile_controller'
|
||||
PageController = require '../page_controller'
|
||||
|
||||
@@ -32,8 +31,6 @@ module.exports = class BrowsePageController extends PageController
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
|
||||
|
||||
@$tileContainer = @$('.tile_container')
|
||||
|
||||
refresh: ->
|
||||
|
||||
@@ -6,16 +6,14 @@
|
||||
//
|
||||
|
||||
.view__mod_tile {
|
||||
min-width : $size-minecraft-block * 9;
|
||||
min-width : $size-minecraft-block * 9;
|
||||
|
||||
display : flex;
|
||||
justify-content : stretch;
|
||||
align-items : stretch;
|
||||
display: flex;
|
||||
|
||||
a {
|
||||
max-width: 100%;
|
||||
|
||||
@include floating-panel;
|
||||
flex: 1 1 auto;
|
||||
|
||||
border : $size-border-medium solid $color-background-panel;
|
||||
color : $color-text;
|
||||
text-decoration : none;
|
||||
@@ -39,6 +37,7 @@
|
||||
overflow : hidden;
|
||||
|
||||
.title {
|
||||
max-width: 0;
|
||||
margin-bottom : $size-margin-medium;
|
||||
|
||||
font-family : $font-family-header;
|
||||
@@ -86,3 +85,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__mod_tile {
|
||||
min-width: 0;
|
||||
|
||||
a {
|
||||
& > .left {
|
||||
flex: 0 0 $size-minecraft-block * 2;
|
||||
|
||||
img {
|
||||
width: $size-minecraft-block * 2;
|
||||
max-height: $size-minecraft-block * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ BaseController = require '../../base_controller'
|
||||
module.exports = class ModTileController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
options.tagName = 'section'
|
||||
options.templateName = 'browse_page/mod_tile'
|
||||
super options
|
||||
|
||||
|
||||
@@ -6,20 +6,64 @@
|
||||
//
|
||||
|
||||
.view__adsense {
|
||||
.skyscraper {
|
||||
height : $size-skyscraper-height;
|
||||
width : $size-skyscraper-width;
|
||||
position : relative;
|
||||
left : 50%;
|
||||
margin : $size-margin-large 0;
|
||||
position : relative;
|
||||
transform : translate(-50%);
|
||||
|
||||
border : 0.1em solid $color-gray-faint;
|
||||
margin : $size-margin-large 0;
|
||||
ins {
|
||||
position: absolute; top: 0; right: 0; bottom: 0; left: 0;
|
||||
}
|
||||
|
||||
&.large-mobile-banner {
|
||||
height : $size-ad-large-mobile-banner-height;
|
||||
width : $size-ad-large-mobile-banner-width;
|
||||
|
||||
&.placeholder:before {
|
||||
font-size : $font-size-large;
|
||||
}
|
||||
}
|
||||
|
||||
&.leaderboard {
|
||||
height : $size-ad-leaderboard-height;
|
||||
width : $size-ad-leaderboard-width;
|
||||
|
||||
&.placeholder:before {
|
||||
font-size : $font-size-xxlarge;
|
||||
}
|
||||
}
|
||||
|
||||
&.skyscraper {
|
||||
height : $size-ad-skyscraper-height;
|
||||
width : $size-ad-skyscraper-width;
|
||||
|
||||
&.placeholder:before {
|
||||
transform : rotate(90deg);
|
||||
font-size : $font-size-xxlarge;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top : 0;
|
||||
}
|
||||
}
|
||||
|
||||
ins {
|
||||
position: absolute; top: 0; right: 0; bottom: 0; left: 0;
|
||||
&.placeholder {
|
||||
border : $size-border-small solid $color-gray-faint;
|
||||
|
||||
display : flex;
|
||||
align-items : center;
|
||||
justify-content : center;
|
||||
|
||||
&:before {
|
||||
color : $color-gray-faint;
|
||||
content : "GOOGLE ADSENSE";
|
||||
font-family : $font-family-control;
|
||||
letter-spacing : $size-margin-small;
|
||||
white-space : nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view__mod_tile + .view__adsense {
|
||||
margin-top : 0;
|
||||
}
|
||||
|
||||
@@ -5,63 +5,132 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
BaseController = require '../../base_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class AdsenseController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
options.templateName = 'common/adsense'
|
||||
super options
|
||||
module.exports = class AdsenseController
|
||||
|
||||
constructor: ->
|
||||
@_adsEnabled = global.env in c.productionEnvs
|
||||
@_adCount = 0
|
||||
@_adsPlaced = 0
|
||||
@_waiting = false
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
fillAdPositions: ->
|
||||
if @_adCount > 0
|
||||
return unless @$sidebar and @$mainBody
|
||||
return unless @_adCount < @_computeMaxAds()
|
||||
return unless @_adCount < c.adsense.slotIds.length
|
||||
adType = @_computeAdType()
|
||||
maxAds = c.adsense[adType].slotIds.length - @_adsPlaced
|
||||
return if maxAds is 0
|
||||
|
||||
$adContainer = $('<div class="skyscraper"></div>')
|
||||
@$el.append $adContainer
|
||||
logger.verbose => "Looking to place #{maxAds} more #{adType} ads..."
|
||||
|
||||
if @_adsEnabled
|
||||
$ad = $('<ins class="adsbygoogle"></ins>')
|
||||
$ad.attr 'data-ad-client', c.adsense.clientId
|
||||
$ad.attr 'data-ad-slot', c.adsense.slotIds[@_adCount]
|
||||
$adContainer.append $ad
|
||||
@_loadAds()
|
||||
if adType is 'skyscraper'
|
||||
placedNewAd = @_createSkyscraperPositions()
|
||||
else
|
||||
placedNewAd = @_createBannerPositions adType
|
||||
|
||||
@_adCount += 1
|
||||
_.defer => @fillAdPositions()
|
||||
if @_adsPlaced < c.adsense[adType].slotIds.length
|
||||
duration = if placedNewAd then 0 else c.adsense.readinessCheckInterval
|
||||
_.delay (=> @fillAdPositions()), duration
|
||||
else
|
||||
logger.verbose => "All #{adType} ad positions filled"
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$mainBody = $('.page > .content > .right')
|
||||
@$sidebar = $('.page > .content > .left')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
reset: ->
|
||||
@_adsPlaced = 0
|
||||
@_waitForPageReadiness()
|
||||
super
|
||||
|
||||
# Private Methods #############################################################################
|
||||
|
||||
_computeMaxAds: ->
|
||||
return null unless @$sidebar
|
||||
result = Math.floor @$sidebar.height() / (c.adsense.skyscraper.height + c.adsense.skyscraper.margin)
|
||||
_computeAdType: ->
|
||||
return c.adsense.adTypeMap[c.screen.type.compute()]
|
||||
|
||||
_computeAdCount: (adType)->
|
||||
result = c.adsense[adType].slotIds.length
|
||||
if c.screen.type.compute() is c.screen.type.desktop
|
||||
$sidebar = $('.page > .content > .left')
|
||||
return 0 unless $sidebar?.length
|
||||
|
||||
available = $sidebar.height() + c.adsense.skyscraper.margin
|
||||
available = Math.floor available / (c.adsense.skyscraper.height + c.adsense.skyscraper.margin)
|
||||
result = Math.min available, result
|
||||
|
||||
return result
|
||||
|
||||
_loadAds: ->
|
||||
_createSkyscraperPositions: ->
|
||||
$sidebar = $('.page > .content > .left')
|
||||
remaining = @_computeAdCount 'skyscraper'
|
||||
remaining -= @_adsPlaced
|
||||
placedNewAd = false
|
||||
|
||||
while remaining > 0
|
||||
$el = $('<div class="view__adsense"></div>')
|
||||
$el.addClass c.adsense.skyscraper.cssClass
|
||||
|
||||
if @_adsEnabled
|
||||
$ad = $('<ins class="adsbygoogle"></ins>')
|
||||
$ad.attr 'data-ad-client', c.adsense.clientId
|
||||
$ad.attr 'data-ad-slot', c.adsense.skyscraper.slotIds[@_adsPlaced]
|
||||
$el.append $ad
|
||||
else
|
||||
$el.addClass 'placeholder'
|
||||
|
||||
$sidebar.append $el
|
||||
placedNewAd = true
|
||||
@_adsPlaced += 1
|
||||
remaining -= 1
|
||||
logger.info => "Placed skyscraper ad ##{@_adsPlaced}"
|
||||
@_loadAd()
|
||||
|
||||
return placedNewAd
|
||||
|
||||
_createBannerPositions: (adType)->
|
||||
$pageContent = $('.page > .content > .right')
|
||||
remaining = @_computeAdCount adType
|
||||
remaining -= @_adsPlaced
|
||||
sectionIndex = 0
|
||||
placedNewAd = false
|
||||
|
||||
for sectionEl in $pageContent.find('section')
|
||||
break unless remaining > 0
|
||||
|
||||
$section = $(sectionEl)
|
||||
continue unless $section.is ':visible'
|
||||
|
||||
sectionIndex += 1
|
||||
continue if sectionIndex % 2 is 0
|
||||
continue if $section.next().hasClass 'view__adsense'
|
||||
|
||||
$el = $('<div class="view__adsense"></div>')
|
||||
$el.addClass c.adsense[adType].cssClass
|
||||
|
||||
if @_adsEnabled
|
||||
$ad = $('<ins class="adsbygoogle"></ins>')
|
||||
$ad.attr 'data-ad-client', c.adsense.clientId
|
||||
$ad.attr 'data-ad-slot', c.adsense[adType].slotIds[@_adsPlaced]
|
||||
$el.append $ad
|
||||
else
|
||||
$el.addClass 'placeholder'
|
||||
|
||||
$section.after $el
|
||||
placedNewAd = true
|
||||
@_adsPlaced += 1
|
||||
remaining -= 1
|
||||
logger.info => "Placed #{adType} ad ##{@_adsPlaced}"
|
||||
@_loadAd()
|
||||
|
||||
return placedNewAd
|
||||
|
||||
_isTooClose: ($priorEl, $el)->
|
||||
return false if c.screen.type.compute() is c.screen.type.desktop
|
||||
return false if not $priorEl?
|
||||
|
||||
priorBottom = $priorEl.position().top + $priorEl.height()
|
||||
currentTop = $el.position().top
|
||||
return priorBottom + c.adsense.minimumDistance > currentTop
|
||||
|
||||
_loadAd: ->
|
||||
return unless @_adsEnabled
|
||||
|
||||
logger.info "Loading #{@_adCount} Google AdSense ads"
|
||||
logger.info "Loading Google AdSense ads"
|
||||
try
|
||||
global.adsbygoogle ||= []
|
||||
global.adsbygoogle.push {}
|
||||
@@ -70,11 +139,12 @@ module.exports = class AdsenseController extends BaseController
|
||||
|
||||
_waitForPageReadiness: ->
|
||||
return if @_waiting
|
||||
adCount = @_computeAdCount @_computeAdType()
|
||||
|
||||
if @$sidebar.height() < c.adsense[@model].height / 2
|
||||
if adCount is 0
|
||||
logger.verbose "Adsense is waiting for room to insert ads"
|
||||
@_waiting = true
|
||||
_.delay (=> @_waiting = false; @_waitForPageReadiness()), c.duration.normal
|
||||
_.delay (=> @_waiting = false; @_waitForPageReadiness()), c.adsense.readinessCheckInterval
|
||||
else
|
||||
logger.verbose "Adsense is ready to fill ads"
|
||||
@fillAdPositions()
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
.item_container
|
||||
.empty_placeholder nothing
|
||||
.buttons
|
||||
.button.item-selector: .bezel: p add an item...
|
||||
.button.item-selector: .bezel: p add<span class="full"> an item</span>...
|
||||
.button.clear: .bezel: p clear
|
||||
|
||||
@@ -38,12 +38,24 @@
|
||||
margin-top: $size-margin-large;
|
||||
|
||||
.item-selector {
|
||||
flex : 85%;
|
||||
flex : 80%;
|
||||
margin-right : $size-margin-medium;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
flex: 50%;
|
||||
|
||||
.full {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clear {
|
||||
flex : 15%;
|
||||
flex : 20%;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
flex: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,8 +73,12 @@
|
||||
.quantity {
|
||||
padding-right : $size-margin-medium;
|
||||
input {
|
||||
width: 3em;
|
||||
font-size : $font-size-xlarge;
|
||||
width : 3em;
|
||||
font-size : $font-size-xlarge;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
width : 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,3 +17,23 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(tablet) {
|
||||
.view__item_group {
|
||||
.panel {
|
||||
.view__item_tile {
|
||||
width: calc(50% - 8px); // $size-margin-xsmall * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__item_group {
|
||||
.panel {
|
||||
.view__item_tile {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
overflow: visible;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
|
||||
img {
|
||||
height: $size-minecraft-block;
|
||||
@@ -22,9 +22,19 @@
|
||||
font-family: $font-family-text;
|
||||
font-size: $font-size-medium;
|
||||
line-height: $size-minecraft-block;
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__item_tile {
|
||||
a {
|
||||
p {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,6 @@
|
||||
}
|
||||
|
||||
&.selected {
|
||||
flex : 0 0 auto;
|
||||
background : $color-active-hover;
|
||||
|
||||
.name {
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
.view__item_selector_popup
|
||||
.search
|
||||
img(src='/images/search.png')
|
||||
input(placeholder='enter the name of an item')
|
||||
input(placeholder='enter an item name')
|
||||
img.close(src='/images/close.png')
|
||||
.results
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
}
|
||||
|
||||
.view__item_selector_popup {
|
||||
max-width: $size-minecraft-block * 20;
|
||||
height : 66%;
|
||||
|
||||
background : $color-background-panel;
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
input {
|
||||
flex: 1 1 100%;
|
||||
min-width: $font-size-large * 10;
|
||||
|
||||
background: none;
|
||||
border: 0;
|
||||
@@ -50,8 +52,15 @@
|
||||
|
||||
.results {
|
||||
flex: 1 1 100%;
|
||||
position: relative;
|
||||
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__item_selector_popup {
|
||||
position: fixed; top: 0; left: 0; height: 100%; width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
when c.key.enter
|
||||
@_chooseSelected()
|
||||
return false
|
||||
when c.key.down
|
||||
when c.key.downArrow
|
||||
@_selectNext()
|
||||
return false
|
||||
when c.key.up
|
||||
when c.key.upArrow
|
||||
@_selectPrevious()
|
||||
return false
|
||||
|
||||
@@ -82,6 +82,7 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
@model.hint = @$hintField.val()
|
||||
@tryRefresh()
|
||||
@onResultSelected @_elementControllers[0]
|
||||
return false
|
||||
|
||||
onPopupClicked: (event)->
|
||||
return false
|
||||
@@ -90,6 +91,7 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
@_session.resolve controller.model.slug
|
||||
@_session = null
|
||||
@_close()
|
||||
return false
|
||||
|
||||
onResultSelected: (controller)->
|
||||
for c in @_elementControllers
|
||||
@@ -98,6 +100,8 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
if controller?
|
||||
controller.selected = true
|
||||
|
||||
return false
|
||||
|
||||
onScreenClicked: (event)->
|
||||
@_close()
|
||||
return false
|
||||
@@ -169,6 +173,8 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
@_elementControllers.pop().remove()
|
||||
|
||||
_selectNext: ->
|
||||
return unless @_elementControllers.length > 0
|
||||
|
||||
for i in [0...(@_elementControllers.length - 1)] by 1
|
||||
controller = @_elementControllers[i]
|
||||
nextController = @_elementControllers[i + 1]
|
||||
@@ -179,7 +185,13 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
@_showElement nextController.$el
|
||||
return
|
||||
|
||||
controller = @_elementControllers[0]
|
||||
controller.selected = true
|
||||
@_showElement controller.$el
|
||||
|
||||
_selectPrevious: ->
|
||||
return unless @_elementControllers.length > 0
|
||||
|
||||
for i in [1...@_elementControllers.length] by 1
|
||||
previousController = @_elementControllers[i - 1]
|
||||
controller = @_elementControllers[i]
|
||||
@@ -190,6 +202,10 @@ module.exports = class ItemSelectorController extends BaseController
|
||||
@_showElement previousController.$el
|
||||
return
|
||||
|
||||
controller = @_elementControllers[@_elementControllers.length - 1]
|
||||
controller.selected = true
|
||||
@_showElement controller.$el
|
||||
|
||||
_showElement: ($el)->
|
||||
top = $el.position().top + @$resultsContainer.scrollTop()
|
||||
@$resultsContainer.css 'scrollTop', top
|
||||
@$resultsContainer.animate {scrollTop:top}, c.duration.snap
|
||||
|
||||
@@ -128,3 +128,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__markdown_section {
|
||||
.creating {
|
||||
padding-bottom: $size-margin-xlarge;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,16 +60,15 @@ module.exports = class MarkdownSectionController extends BaseController
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onCancelClicked: (event)->
|
||||
event.preventDefault()
|
||||
@model = @_originalModel
|
||||
@resetToDefaultState()
|
||||
|
||||
@_imageListController.reset()
|
||||
@_updatePreview()
|
||||
return false
|
||||
|
||||
onEditClicked: (event)->
|
||||
event.preventDefault()
|
||||
return unless @editable
|
||||
return false unless @editable
|
||||
|
||||
@_originalModel = @model
|
||||
@state = @State.waiting
|
||||
@@ -81,22 +80,22 @@ module.exports = class MarkdownSectionController extends BaseController
|
||||
@state = @State.appologizing
|
||||
w(true).delay(@_confirmDuration).then => @resetToDefaultState()
|
||||
|
||||
return false
|
||||
|
||||
onQuestionClicked: (event)->
|
||||
event.preventDefault()
|
||||
@_enterFeedback ''
|
||||
return false
|
||||
|
||||
onPreviewClicked: (event)->
|
||||
event.preventDefault()
|
||||
@_updatePreview()
|
||||
@state = @State.previewing
|
||||
return false
|
||||
|
||||
onReturnClicked: (event)->
|
||||
event.preventDefault()
|
||||
@state = @State.editing
|
||||
return false
|
||||
|
||||
onSaveClicked: (event)->
|
||||
event.preventDefault()
|
||||
|
||||
@state = @State.waiting
|
||||
@_endEditing()
|
||||
.then =>
|
||||
@@ -109,9 +108,11 @@ module.exports = class MarkdownSectionController extends BaseController
|
||||
.then =>
|
||||
@state = @State.viewing
|
||||
|
||||
return false
|
||||
|
||||
onTextChanged: (event)->
|
||||
event.preventDefault()
|
||||
@model = @$textarea.val()
|
||||
return false
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
|
||||
@@ -9,12 +9,16 @@
|
||||
display: flex;
|
||||
|
||||
.input {
|
||||
flex: 1 1 50%;
|
||||
flex: 0 0 auto;
|
||||
|
||||
align-items : center;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
|
||||
.view__crafting_grid {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.tool {
|
||||
margin-top : $size-margin-small;
|
||||
|
||||
@@ -24,7 +28,7 @@
|
||||
}
|
||||
|
||||
.output {
|
||||
flex: 1 1 50%;
|
||||
flex: 1 1 100%;
|
||||
margin-left: $size-margin-medium;
|
||||
|
||||
display : flex;
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
//-
|
||||
|
||||
.view__stack
|
||||
.quantity: input
|
||||
.quantity
|
||||
input
|
||||
.hover
|
||||
.icon: img(src='')
|
||||
.name: a
|
||||
.action.first(style="display: none")
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
.quantity {
|
||||
padding-right : $size-margin-medium;
|
||||
position : relative;
|
||||
text-align : right;
|
||||
|
||||
input {
|
||||
@@ -32,6 +33,38 @@
|
||||
font-size : $font-size-large;
|
||||
text-align : right;
|
||||
}
|
||||
|
||||
.hover {
|
||||
$backgroundColor: fade-out($color-black, 0.25);
|
||||
|
||||
display: none;
|
||||
position: absolute; left: 50%; top: -($font-size-large * 2);
|
||||
transform: translateX(-50%);
|
||||
|
||||
background: $backgroundColor;
|
||||
color: $color-white;
|
||||
font-family: $font-family-control;
|
||||
font-size: $font-size-medium;
|
||||
padding: $size-margin-small;
|
||||
z-index: $layer-dialog;
|
||||
|
||||
&:after {
|
||||
position: absolute; top: 100%; left: calc(50% - 9px); // $font-size-large / 2
|
||||
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
border-width: $size-margin-medium $size-margin-medium 0 $size-margin-medium;
|
||||
border-color: $backgroundColor transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.hover.enabled {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
@@ -84,3 +117,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__stack.editable {
|
||||
.quantity {
|
||||
input {
|
||||
width : 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ Events:
|
||||
module.exports = class StackController extends BaseController
|
||||
|
||||
@::MAX_QUANTITY = 9999
|
||||
@::STACK_SIZE = 64
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
@@ -107,6 +108,7 @@ module.exports = class StackController extends BaseController
|
||||
@$image = @$('.icon img')
|
||||
@$nameLink = @$('.name a')
|
||||
@$quantityField = @$('.quantity input')
|
||||
@$quantityHover = @$('.quantity .hover')
|
||||
@$secondAction = @$('.action.second')
|
||||
@$secondButton = @$('.action.second .button')
|
||||
super
|
||||
@@ -124,6 +126,7 @@ module.exports = class StackController extends BaseController
|
||||
@$quantityField.val quantityText
|
||||
|
||||
@_refreshButtons()
|
||||
@_refreshHover()
|
||||
|
||||
if @_editable
|
||||
@$el.addClass 'editable'
|
||||
@@ -169,6 +172,20 @@ module.exports = class StackController extends BaseController
|
||||
when 'remove' then $label.text '-'
|
||||
when 'up' then $label.text '⬆︎'
|
||||
|
||||
_refreshHover: ->
|
||||
if @model.quantity > @STACK_SIZE
|
||||
remainder = @model.quantity % @STACK_SIZE
|
||||
stacks = (@model.quantity - remainder) / @STACK_SIZE
|
||||
|
||||
text = "#{stacks}x#{@STACK_SIZE}"
|
||||
text += "+#{remainder}" if remainder > 0
|
||||
|
||||
@$quantityHover.text text
|
||||
@$quantityHover.addClass 'enabled'
|
||||
else
|
||||
@$quantityHover.text ''
|
||||
@$quantityHover.removeClass 'enabled'
|
||||
|
||||
_updateButtonType: ($button, type)->
|
||||
for currentType in ['check', 'down', 'remove', 'up']
|
||||
$button.removeClass currentType
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//-
|
||||
//- Crafting Guide - twitter.jade
|
||||
//-
|
||||
//- Copyright © 2014-2016 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.view__twitter
|
||||
.left
|
||||
img(src="/images/twitter.png")
|
||||
.right
|
||||
.instructions Follow us for updates!
|
||||
a(
|
||||
href="https://twitter.com/Crafting_Guide"
|
||||
class="twitter-follow-button"
|
||||
data-show-count="false"
|
||||
data-size="large"
|
||||
) Follow @Crafting_Guide
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Crafting Guide - news_page.scss
|
||||
//
|
||||
// Copyright © 2014-2016 by Redwood Labs
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
.view__twitter {
|
||||
display: flex;
|
||||
|
||||
& > .left {
|
||||
flex: 1 1 50%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
height: $size-minecraft-block * 4;
|
||||
width: $size-minecraft-block * 4;
|
||||
}
|
||||
}
|
||||
|
||||
& > .right {
|
||||
flex: 1 1 50%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.instructions {
|
||||
flex: 1 1 50%;
|
||||
margin-bottom: $size-margin-medium;
|
||||
margin-top: $size-margin-medium;
|
||||
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-xlarge;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
iframe {
|
||||
flex: 1 1 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__twitter {
|
||||
& > .left {
|
||||
img {
|
||||
height: $size-minecraft-block * 3;
|
||||
width: $size-minecraft-block * 3;
|
||||
}
|
||||
}
|
||||
|
||||
& > .right {
|
||||
.instructions {
|
||||
font-size: $font-size-xlarge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,5 @@
|
||||
//-
|
||||
|
||||
.view__video
|
||||
iframe(width="356", height="267", src="", frameborder="0", allowfullscreen="true")
|
||||
iframe(src="", frameborder="0", allowfullscreen="true")
|
||||
.caption: p
|
||||
@@ -11,6 +11,10 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
iframe {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.caption {
|
||||
margin-top: $size-margin-small;
|
||||
|
||||
|
||||
@@ -5,16 +5,8 @@
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
- var quarryHref = '/craft/quarry'
|
||||
- var quarry
|
||||
- var quantumSuitHref = '/craft/quantumsuit_bodyarmor:quantumsuit_boots:quantumsuit_helmet:quantumsuit_leggings'
|
||||
- var ic2Href = '/browse/industrial_craft_2'
|
||||
- var solarPanelHref = '/craft/solar_panel_vi'
|
||||
- var solarFluxHref = '/browse/solar_flux'
|
||||
|
||||
.content.view__craft_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
section.instructions
|
||||
@@ -26,19 +18,19 @@
|
||||
p.
|
||||
Not sure what you'd like to make? Try one of these:
|
||||
.items
|
||||
a(href="/craft/potion_of_strength_ii_1_30")
|
||||
a(href="/" data-slug="potion_of_strength_ii_1_30")
|
||||
img(src="/data/minecraft/items/potion_of_strength_ii_1_30/icon.png")
|
||||
a(href="/craft/quarry")
|
||||
a(href="/" data-slug="quarry")
|
||||
img(src="/data/buildcraft/items/quarry/icon.png")
|
||||
a(href="/craft/quantumsuit_bodyarmor:quantumsuit_boots:quantumsuit_helmet:quantumsuit_leggings")
|
||||
a(href="/" data-slug="quantumsuit_bodyarmor:quantumsuit_boots:quantumsuit_helmet:quantumsuit_leggings")
|
||||
img(src="/data/ic2_classic/items/quantumsuit_helmet/icon.png")
|
||||
a(href="/craft/solar_panel_vi")
|
||||
a(href="/" data-slug="solar_panel_vi")
|
||||
img(src="/data/solar_flux/items/solar_panel_vi/icon.png")
|
||||
a(href="/craft/crystal_chest")
|
||||
a(href="/" data-slug="crystal_chest")
|
||||
img(src="/data/iron_chests/items/crystal_chest/icon.png")
|
||||
a(href="/craft/digital_miner")
|
||||
a(href="/" data-slug="digital_miner")
|
||||
img(src="/data/mekanism/items/digital_miner/icon.png")
|
||||
a(href="/craft/2.tesseract")
|
||||
a(href="/" data-slug="2.tesseract")
|
||||
img(src="/data/thermal_expansion/items/tesseract/icon.png")
|
||||
|
||||
section.want
|
||||
@@ -51,8 +43,6 @@
|
||||
.panel
|
||||
.view__inventory.large.editable
|
||||
|
||||
section.view__craftsman_working
|
||||
|
||||
section.need
|
||||
h2 Need to Gather
|
||||
.panel
|
||||
@@ -61,3 +51,5 @@
|
||||
section.steps
|
||||
h2 Steps
|
||||
.panel
|
||||
|
||||
section.view__craftsman_working
|
||||
|
||||
@@ -49,4 +49,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.outdated {
|
||||
section.need .panel {
|
||||
background: $color-white url('/images/panel-background-outdated.png') repeat;
|
||||
}
|
||||
|
||||
section.steps .panel {
|
||||
background: $color-white url('/images/panel-background-outdated.png') repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,19 +5,21 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
BaseController = require '../base_controller'
|
||||
CraftPage = require '../../models/site/craft_page'
|
||||
Craftsman = require '../../models/crafting/craftsman'
|
||||
CraftsmanWorkingController = require './craftsman_working/craftsman_working_controller'
|
||||
InventoryController = require '../common/inventory/inventory_controller'
|
||||
PageController = require '../page_controller'
|
||||
SimpleInventory = require '../../models/crafting/simple_inventory'
|
||||
StepController = require './step/step_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class CraftPageController extends PageController
|
||||
|
||||
@::SCROLL_BUFFER = 8 # px
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
@@ -33,10 +35,9 @@ module.exports = class CraftPageController extends PageController
|
||||
@_router = options.router
|
||||
@_storage = options.storage
|
||||
|
||||
# c.event Methods ################################################################################
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onHaveInventoryChanged: ->
|
||||
logger.warning => "storing have: #{@model.craftsman.have.unparse()}"
|
||||
@_storage.store 'crafting-plan:have', @model.craftsman.have.unparse()
|
||||
|
||||
onMoveNeedToHave: (itemSlug)->
|
||||
@@ -50,27 +51,39 @@ module.exports = class CraftPageController extends PageController
|
||||
@model.craftsman.want.remove itemSlug
|
||||
@onWantInventoryChanged()
|
||||
|
||||
onSampleClicked: (event)->
|
||||
$el = $(event.target)
|
||||
while $el.length > 0
|
||||
inventoryText = $el.attr 'data-slug'
|
||||
break if inventoryText
|
||||
$el = $el.parent()
|
||||
|
||||
if inventoryText?
|
||||
sampleInventory = new SimpleInventory
|
||||
sampleInventory.parse inventoryText
|
||||
@model.craftsman.want.addInventory sampleInventory
|
||||
@_scrollTo @$workingSection
|
||||
|
||||
return false
|
||||
|
||||
onWantInventoryChanged: ->
|
||||
text = @model.craftsman.want.unparse()
|
||||
url = c.url.crafting inventoryText:text
|
||||
@router.navigate url
|
||||
|
||||
if @model.craftsman.want.isEmpty
|
||||
@model.craftsman.have.clear()
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getMetaDescription: ->
|
||||
return c.text.craftDescription()
|
||||
|
||||
getTitle: ->
|
||||
return 'Craft'
|
||||
description = @model.craftsman.want.toDescription()
|
||||
return null unless description?
|
||||
return "Crafting Plan for #{description}"
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
|
||||
|
||||
@_wantInventoryController = @addChild InventoryController, '.want .view__inventory',
|
||||
firstButtonType: 'remove'
|
||||
imageLoader: @_imageLoader
|
||||
@@ -89,7 +102,6 @@ module.exports = class CraftPageController extends PageController
|
||||
router: @_router
|
||||
@_haveInventoryController.on c.event.button.first, (controller, itemSlug)=>
|
||||
@onRemoveFromHaveInventory itemSlug
|
||||
@_haveInventoryController.on c.event.change, (c)=> @onHaveInventoryChanged()
|
||||
|
||||
@_needInventoryController = @addChild InventoryController, '.need .view__inventory',
|
||||
editable: false
|
||||
@@ -102,6 +114,7 @@ module.exports = class CraftPageController extends PageController
|
||||
|
||||
@_workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working',
|
||||
model: @model.craftsman
|
||||
@_workingSectionController.on c.event.click, => @_scrollTo @$workingSection
|
||||
|
||||
@$haveSection = @$('section.have')
|
||||
@$instructionsSection = @$('section.instructions')
|
||||
@@ -112,25 +125,37 @@ module.exports = class CraftPageController extends PageController
|
||||
@$toolsSection = @$('section.tools')
|
||||
@$workingSection = @$('.view__craftsman_working')
|
||||
|
||||
if c.screen.type.compute() is c.screen.type.mobile
|
||||
@$('.view__inventory.large').removeClass 'large'
|
||||
|
||||
super
|
||||
|
||||
onWillRender: ->
|
||||
@model.craftsman.have.clear()
|
||||
@model.craftsman.have.parse @_storage.load('crafting-plan:have')
|
||||
@model.craftsman.have.on c.event.change, => @onHaveInventoryChanged()
|
||||
|
||||
@model.craftsman.want.on c.event.change, => @refresh()
|
||||
|
||||
@model.craftsman.on c.event.change + ":stage", =>
|
||||
return unless @model.craftsman.stage is Craftsman::STAGE.COMPLETE
|
||||
@_scrollTo @$needSection
|
||||
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@_needInventoryController.model = @model.craftsman.plan?.need
|
||||
@_refreshOutdated()
|
||||
@_refreshSectionVisibility()
|
||||
@_refreshSteps()
|
||||
@_adsenseController.fillAdPositions()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ########################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .instructions a': 'routeLinkClick'
|
||||
'click .instructions a': 'onSampleClicked'
|
||||
|
||||
# Private Methods ################################################################################
|
||||
|
||||
@@ -138,7 +163,7 @@ module.exports = class CraftPageController extends PageController
|
||||
controller.model.addToolsTo @model.craftsman.want
|
||||
|
||||
_completeStep: (controller)->
|
||||
controller.model.completeInto @model.craftsman.have
|
||||
controller.markComplete @model.craftsman.have
|
||||
|
||||
_isAddingToolsPossible: (controller)->
|
||||
tools = controller.model.recipe.tools
|
||||
@@ -160,6 +185,12 @@ module.exports = class CraftPageController extends PageController
|
||||
|
||||
return true
|
||||
|
||||
_refreshOutdated: ->
|
||||
if @model.craftsman.stage is Craftsman::STAGE.OUTDATED
|
||||
@$el.addClass 'outdated'
|
||||
else
|
||||
@$el.removeClass 'outdated'
|
||||
|
||||
_refreshSectionVisibility: ->
|
||||
return unless @_rendered
|
||||
|
||||
@@ -172,11 +203,13 @@ module.exports = class CraftPageController extends PageController
|
||||
if @model.craftsman.want.isEmpty
|
||||
visibleSections.push el for el in [@$instructionsSection, @$wantSection]
|
||||
else if @model.craftsman.stage is Craftsman::STAGE.INVALID
|
||||
visibleSections.push el for el in [@$wantSection, @$workingSection]
|
||||
visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
|
||||
else if not @model.craftsman.complete
|
||||
visibleSections.push el for el in [@$wantSection, @$workingSection]
|
||||
visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
|
||||
else
|
||||
visibleSections.push el for el in [@$haveSection, @$needSection, @$stepsSection, @$wantSection]
|
||||
visibleSections.push el for el in [@$haveSection, @$wantSection, @$workingSection]
|
||||
if @model.craftsman.plan?
|
||||
visibleSections.push el for el in [@$needSection, @$stepsSection]
|
||||
|
||||
@hide $el for $el in allSections
|
||||
@show $el for $el in visibleSections
|
||||
@@ -209,3 +242,28 @@ module.exports = class CraftPageController extends PageController
|
||||
|
||||
while @_stepControllers.length > index
|
||||
@_stepControllers.pop().remove()
|
||||
|
||||
_scrollTo: ($targetEl)->
|
||||
@_$scrollTarget = $targetEl
|
||||
|
||||
if @_scrollTimer?
|
||||
clearTimeout @_scrollTimer
|
||||
|
||||
@_scrollTimer = setTimeout(=>
|
||||
$el = @_$scrollTarget
|
||||
@_scrollTimer = null
|
||||
|
||||
minScrollPosition = $el.offset().top + $el.height() - $(window).height() - @SCROLL_BUFFER
|
||||
maxScrollPosition = $el.offset().top + @SCROLL_BUFFER
|
||||
scrollPosition = $(window).scrollTop()
|
||||
|
||||
scrollTarget = scrollPosition
|
||||
if scrollPosition > maxScrollPosition
|
||||
scrollTarget = maxScrollPosition
|
||||
else if scrollPosition < minScrollPosition
|
||||
scrollTarget = minScrollPosition
|
||||
else
|
||||
return
|
||||
|
||||
$('html, body').animate {scrollTop:scrollTarget}, c.duration.normal
|
||||
, c.duration.slow)
|
||||
|
||||
@@ -5,11 +5,16 @@
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.view__item_group.section
|
||||
.content
|
||||
.view__craftsman_working
|
||||
.panel
|
||||
.waiting
|
||||
img(src='/images/wait.gif')
|
||||
.message
|
||||
p
|
||||
.count
|
||||
p
|
||||
.button: .bezel: p Calculate
|
||||
|
||||
.outdated
|
||||
.message Your crafting plan is out of date!
|
||||
.button: .bezel: p Recalculate
|
||||
@@ -6,32 +6,78 @@ All rights reserved.
|
||||
*/
|
||||
|
||||
.view__craftsman_working {
|
||||
.content {
|
||||
background: $color-white;
|
||||
box-shadow: none;
|
||||
|
||||
.panel {
|
||||
align-items : center;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
padding : $size-margin-xlarge;
|
||||
|
||||
.waiting {
|
||||
margin-bottom: $size-margin-xlarge;
|
||||
margin-bottom : $size-margin-xlarge;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-bottom: $size-margin-medium;
|
||||
margin-bottom : $size-margin-medium;
|
||||
|
||||
p {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-large;
|
||||
font-family : $font-family-header;
|
||||
font-size : $font-size-large;
|
||||
text-align : center;
|
||||
}
|
||||
}
|
||||
|
||||
.count {
|
||||
p {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-medium;
|
||||
font-family : $font-family-header;
|
||||
font-size : $font-size-medium;
|
||||
text-align : center;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-top : $size-margin-large;
|
||||
min-width: $size-minecraft-block * 6;
|
||||
}
|
||||
}
|
||||
|
||||
.outdated {
|
||||
position: fixed; top: 0; left: 0; right: 0;
|
||||
|
||||
|
||||
background : fade-out($color-white, 0.15) url('/images/panel-background-outdated.png');
|
||||
border-bottom : $size-border-medium solid $color-black;
|
||||
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
align-items : center;
|
||||
|
||||
.message {
|
||||
margin-top : $size-margin-medium;
|
||||
|
||||
font-family : $font-family-header;
|
||||
font-size : $font-size-xlarge;
|
||||
text-align : center;
|
||||
}
|
||||
|
||||
.button {
|
||||
width : $size-minecraft-block * 6;
|
||||
margin : $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(not-mobile) {
|
||||
.view__craftsman_working {
|
||||
.panel {
|
||||
.button {
|
||||
margin-top : $size-margin-large;
|
||||
height : $size-minecraft-block * 2;
|
||||
width : $size-minecraft-block * 10;
|
||||
|
||||
p {
|
||||
font-size : $font-size-xxlarge;
|
||||
transform : translateY(-25%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,48 +12,94 @@ Craftsman = require '../../../models/crafting/craftsman'
|
||||
|
||||
module.exports = class CraftsmanWorkingController extends BaseController
|
||||
|
||||
@::HIDE_TIMER_DURATION = 2000
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model then throw new Error 'options.model is required'
|
||||
options.templateName = 'craft_page/craftsman_working'
|
||||
super options
|
||||
|
||||
@model.on c.event.change, => @_refreshStatusText()
|
||||
@_hideTimer = null
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onButtonClicked: ->
|
||||
@trigger c.event.click
|
||||
@model.reset()
|
||||
@model.work()
|
||||
return false
|
||||
|
||||
# BaseController Methods #######################################################################
|
||||
|
||||
onDidModelChange: ->
|
||||
@refresh()
|
||||
|
||||
onDidRender: ->
|
||||
@$message = @$('.message p')
|
||||
@$count = @$('.count p')
|
||||
@$waiting = @$('.waiting')
|
||||
@$button = @$('.button')
|
||||
@$count = @$('.count p')
|
||||
@$message = @$('.message p')
|
||||
@$outdated = @$('.outdated')
|
||||
@$waiting = @$('.waiting')
|
||||
|
||||
@_controls = [@$button, @$count, @$message, @$outdated, @$waiting]
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@_refreshStatusText()
|
||||
super
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshStatusText: ->
|
||||
return unless @$message? and @$count?
|
||||
|
||||
@show @$waiting
|
||||
button = count = message = outdated = waiting = null
|
||||
|
||||
switch @model.stage
|
||||
when Craftsman::STAGE.WAITING
|
||||
@$message.html 'Preparing crafting calculation...'
|
||||
@$count.html ''
|
||||
when Craftsman::STAGE.READY
|
||||
message = 'Ready to compute crafting plan!'
|
||||
count = 'Click "Calculate" to continue.'
|
||||
button = true
|
||||
when Craftsman::STAGE.GRAPHING
|
||||
@$message.html 'Researching recipes...'
|
||||
@$count.html "Found #{@model.stageCount} recipes so far..."
|
||||
message = 'Researching recipes...'
|
||||
count = "Found #{@model.stageCount} recipes so far..."
|
||||
watiing = true
|
||||
when Craftsman::STAGE.PLANNING
|
||||
@$message.html 'Figuring out possible crafting plans...'
|
||||
@$count.html "Found #{@model.stageCount} possibilities so far..."
|
||||
message = 'Figuring out possible crafting plans...'
|
||||
count = "Found #{@model.stageCount} possibilities so far..."
|
||||
watiing = true
|
||||
when Craftsman::STAGE.ANALYZING
|
||||
@$message.html 'Looking for the best plan...'
|
||||
@$count.html "Finished checking #{@model.stageCount} so far..."
|
||||
message = 'Looking for the best plan...'
|
||||
count = "Finished checking #{@model.stageCount} so far..."
|
||||
watiing = true
|
||||
when Craftsman::STAGE.COMPLETE
|
||||
@$message.html 'All done!'
|
||||
@$count.html ''
|
||||
message = 'Crafting plan is complete.'
|
||||
when Craftsman::STAGE.INVALID
|
||||
@$message.html 'Couldn\'t make a crafting plan'
|
||||
@$count.html ''
|
||||
@hide @waiting
|
||||
message = 'Couldn\'t make a crafting plan!'
|
||||
count = 'Please report this problem using the Feedback box.'
|
||||
when Craftsman::STAGE.OUTDATED
|
||||
message = 'Your crafting plan is out of date!'
|
||||
count = 'Click "Calculate" to re-compute.'
|
||||
button = true
|
||||
outdated = true
|
||||
|
||||
@hide(control) for control in @_controls
|
||||
|
||||
if button?
|
||||
@show @$button
|
||||
|
||||
if count?
|
||||
@show @$count
|
||||
@$count.html count
|
||||
|
||||
if message?
|
||||
@show @$message
|
||||
@$message.html message
|
||||
|
||||
if outdated?
|
||||
@show @$outdated
|
||||
|
||||
if waiting?
|
||||
@show @$waiting
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .button': 'onButtonClicked'
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
.view__inventory
|
||||
.view__recipe
|
||||
.buttons
|
||||
.button.complete: .bezel: p complete step
|
||||
.button.tool: .bezel: p make this tool
|
||||
a.button.tool: .bezel: p <span class="full">show plan for </span>tools
|
||||
.button.complete: .bezel: p complete<span class="full"> step</span>
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
.view__inventory {
|
||||
flex: 50%;
|
||||
margin-left: $size-margin-large;
|
||||
|
||||
.buttons {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.view__recipe {
|
||||
@@ -52,5 +56,51 @@
|
||||
margin-left: $size-margin-medium;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
border: 0;
|
||||
|
||||
.bezel {
|
||||
border-top : 3px solid $color-button-highlight;
|
||||
border-left : 3px solid $color-button-highlight;
|
||||
border-bottom : 6px solid $color-button-shadow;
|
||||
border-right : 3px solid $color-button-shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.complete {
|
||||
opacity: 0.25;
|
||||
|
||||
h3 {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__step {
|
||||
.main_content {
|
||||
flex-direction: column-reverse;
|
||||
|
||||
.view__inventory {
|
||||
flex: 0 0 auto;
|
||||
margin: $size-margin-large $size-margin-large 0 $size-margin-large;
|
||||
}
|
||||
|
||||
.view__recipe {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
opacity: 1.0;
|
||||
|
||||
.button {
|
||||
.full {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
BaseController = require '../../base_controller'
|
||||
InventoryController = require '../../common/inventory/inventory_controller'
|
||||
RecipeController = require '../../common/recipe/recipe_controller'
|
||||
SimpleInventory = require '../../../models/crafting/simple_inventory'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -29,16 +30,19 @@ module.exports = class StepController extends BaseController
|
||||
@onComplete = options.onComplete or (controller)-> # do nothing
|
||||
@onAddTools = options.onAddTools or (controller)-> # do nothing
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
markComplete: (targetInventory)->
|
||||
@$el.addClass 'complete'
|
||||
@$completeButton.addClass 'disabled'
|
||||
@model.completeInto targetInventory
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onCompleteButtonClicked: (event)->
|
||||
return if @$completeButton.hasClass 'disabled'
|
||||
@onComplete this
|
||||
|
||||
onToolButtonClicked: (event)->
|
||||
return if @$toolButton.hasClass 'disabled'
|
||||
@onAddTools this
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@@ -63,6 +67,9 @@ module.exports = class StepController extends BaseController
|
||||
|
||||
onWillChangeModel: (oldModel, newModel)->
|
||||
if not newModel? then throw new Error 'model cannot be null'
|
||||
if @rendered
|
||||
@$el.removeClass 'complete'
|
||||
@$completeButton.removeClass 'disabled'
|
||||
return super
|
||||
|
||||
refresh: ->
|
||||
@@ -83,11 +90,19 @@ module.exports = class StepController extends BaseController
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .button.complete': 'onCompleteButtonClicked'
|
||||
'click .button.tool': 'onToolButtonClicked'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshToolButton: ->
|
||||
inventory = new SimpleInventory {}, modPack:@_modPack
|
||||
for toolStack in @model.recipe.tools
|
||||
inventory.add toolStack.itemSlug, toolStack.quantity
|
||||
inventory.localize()
|
||||
|
||||
inventoryText = inventory.unparse()
|
||||
@$toolButton.attr 'href', "/craft/#{inventoryText}"
|
||||
@$toolButton.attr 'target', inventoryText
|
||||
|
||||
if @canAddTools this
|
||||
@$toolButton.removeClass 'disabled'
|
||||
else
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
display: flex;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
flex: 1 1 100%;
|
||||
|
||||
@@ -73,13 +77,11 @@
|
||||
background: $color-gray-light;
|
||||
border: $size-border-medium solid $color-black;
|
||||
border-left: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
p {
|
||||
transform: rotate(-90deg);
|
||||
position: absolute; top: 50%; left: 50%;
|
||||
transform: translateX(-50%) rotate(-90deg) translateX(10%);
|
||||
|
||||
font-family: $font-family-header;
|
||||
font-size: $label-size;
|
||||
|
||||
@@ -19,12 +19,20 @@
|
||||
> .content {
|
||||
display: flex;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
color: $color-text-light;
|
||||
|
||||
.left, .center, .right {
|
||||
flex: 1 1 33%;
|
||||
margin: $size-margin-large $size-margin-large $size-margin-large 0;
|
||||
|
||||
@include screen-size(mobile) {
|
||||
margin-left: $size-margin-large;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -38,6 +46,7 @@
|
||||
.action {
|
||||
flex: 1 1 auto;
|
||||
align-self: center;
|
||||
margin-top: $size-margin-large;
|
||||
margin-bottom: $size-margin-large;
|
||||
|
||||
display: flex;
|
||||
@@ -55,3 +64,13 @@
|
||||
height: $size-minecraft-block;
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__footer {
|
||||
> .content {
|
||||
.left, .center, .right {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,6 @@
|
||||
.button.search: .bezel: p Search
|
||||
.button.login: .bezel: p Login
|
||||
|
||||
.breadcrumbs
|
||||
.breadcrumb-bar
|
||||
.breadcrumbs
|
||||
.extra-nav
|
||||
|
||||
@@ -23,24 +23,22 @@
|
||||
|
||||
img {
|
||||
position : relative;
|
||||
top : -$size-minecraft-block * 0.5;
|
||||
left : -$size-minecraft-block * 0.5;
|
||||
height : $size-minecraft-block * 2.0;
|
||||
width : $size-minecraft-block * 2.0;
|
||||
height : $size-minecraft-block * 1.5;
|
||||
width : $size-minecraft-block * 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
flex: 1 1 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.addthis_sharing_toolbox {
|
||||
flex : 0 0 auto;
|
||||
min-height : 37px;
|
||||
min-height : 37px; // actual size of addthis component
|
||||
min-width : 144px;
|
||||
margin-right : $size-margin-small;
|
||||
|
||||
|
||||
&.placeholder {
|
||||
border : 1px solid orange;
|
||||
text-align : center;
|
||||
@@ -62,36 +60,103 @@
|
||||
align-items : center;
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
justify-content : space-around;
|
||||
justify-content : center;
|
||||
padding : $size-margin-medium $size-margin-medium;
|
||||
padding-top : 0;
|
||||
|
||||
.button {
|
||||
flex : 1 1 20%;
|
||||
min-width : 4 * $size-minecraft-block;
|
||||
max-width : 5 * $size-minecraft-block;
|
||||
margin-top: $size-margin-medium;
|
||||
flex-grow : 1;
|
||||
flex-shrink : 1;
|
||||
min-width : 3 * $size-minecraft-block;
|
||||
max-width : 5 * $size-minecraft-block;
|
||||
margin-top : $size-margin-medium;
|
||||
margin-right : $size-margin-small;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
.breadcrumb-bar {
|
||||
background: $color-screen;
|
||||
padding: 0 ($size-margin-medium + $size-margin-large);
|
||||
|
||||
font-family: $font-family-control;
|
||||
font-size: $font-size-medium;
|
||||
line-height: $font-size-medium + 2 * $size-margin-small;
|
||||
|
||||
padding: $size-margin-small $size-margin-medium;
|
||||
display: flex;
|
||||
|
||||
&:before {
|
||||
content: "⟩";
|
||||
margin-right: $size-margin-medium;
|
||||
.breadcrumbs {
|
||||
flex: 1 1 75%;
|
||||
|
||||
text-indent: -$size-margin-large;
|
||||
|
||||
&:before {
|
||||
content: "⟩";
|
||||
margin-right: $size-margin-medium;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span {
|
||||
margin: 0 $size-margin-medium;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.extra-nav {
|
||||
flex: 1 1 25%;
|
||||
align-self: flex-end;
|
||||
|
||||
span {
|
||||
margin: 0 $size-margin-medium;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(desktop) {
|
||||
.view__header {
|
||||
.top-row {
|
||||
a {
|
||||
img {
|
||||
top : -$size-minecraft-block * 0.5;
|
||||
left : -$size-minecraft-block * 0.5;
|
||||
height : $size-minecraft-block * 2.0;
|
||||
width : $size-minecraft-block * 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(tablet) {
|
||||
.view__header {
|
||||
.top-row {
|
||||
h1 {
|
||||
font-size : $font-size-xlarge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__header {
|
||||
.top-row {
|
||||
display : none;
|
||||
}
|
||||
|
||||
.divider {
|
||||
.button.login {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-bar {
|
||||
.extra-nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
BaseController = require '../base_controller'
|
||||
ItemSelectorController = require '../common/item_selector/item_selector_controller'
|
||||
UrlParams = require '../url_params'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -43,9 +44,11 @@ module.exports = class HeaderController extends BaseController
|
||||
@router.navigate '/news', trigger:true
|
||||
return false
|
||||
|
||||
onSearch: ->
|
||||
@_selector.launch()
|
||||
onSearch: (event, hint='')->
|
||||
@_selector.launch hint
|
||||
.then (itemSlug)=>
|
||||
return unless itemSlug?
|
||||
|
||||
itemDisplay = @_modPack.findItemDisplay itemSlug
|
||||
@router.navigate itemDisplay.itemUrl, trigger:true
|
||||
return false
|
||||
@@ -62,8 +65,11 @@ module.exports = class HeaderController extends BaseController
|
||||
@$('.addthis_sharing_toolbox').addClass 'placeholder'
|
||||
|
||||
@$breadcrumbs = @$('.breadcrumbs')
|
||||
@$extraNav = @$('.extra-nav')
|
||||
@$loginButtonLabel = @$('.button.login p')
|
||||
@$title = $('title')
|
||||
|
||||
@_checkForSearchRequest()
|
||||
super
|
||||
|
||||
onWillChangeModel: (oldModel, newModel)->
|
||||
@@ -75,6 +81,8 @@ module.exports = class HeaderController extends BaseController
|
||||
@$loginButtonLabel.text if global.site.user? then "Logout" else "Login"
|
||||
|
||||
@_refreshBreadcrumbs()
|
||||
@_refreshExtraNav()
|
||||
@_refreshSelectedNavButton()
|
||||
@_refreshTitle()
|
||||
super
|
||||
|
||||
@@ -82,15 +90,21 @@ module.exports = class HeaderController extends BaseController
|
||||
|
||||
events: ->
|
||||
_.extend super,
|
||||
'click .craft': 'onCraft'
|
||||
'click .browse': 'onBrowse'
|
||||
'click .login': 'onLogin'
|
||||
'click .news': 'onNews'
|
||||
'click .search': 'onSearch'
|
||||
'click .breadcrumbs a': 'routeLinkClick'
|
||||
'click .craft': 'onCraft'
|
||||
'click .browse': 'onBrowse'
|
||||
'click .login': 'onLogin'
|
||||
'click .news': 'onNews'
|
||||
'click .search': 'onSearch'
|
||||
'click .breadcrumb-bar a': 'routeLinkClick'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_checkForSearchRequest: ->
|
||||
params = new UrlParams search:{type:'string'}
|
||||
return unless params.search?
|
||||
|
||||
_.delay (=> @onSearch {}, params.search), c.duration.slow
|
||||
|
||||
_refreshBreadcrumbs: ->
|
||||
breadcrumbs = @model?.controller?.getBreadcrumbs()
|
||||
breadcrumbs ?= []
|
||||
@@ -106,6 +120,23 @@ module.exports = class HeaderController extends BaseController
|
||||
else
|
||||
@hide @$breadcrumbs
|
||||
|
||||
_refreshExtraNav: ->
|
||||
extraNavContent = @model?.controller?.getExtraNav()
|
||||
|
||||
if extraNavContent?
|
||||
@$extraNav.empty()
|
||||
@$extraNav.append extraNavContent
|
||||
@show @$extraNav
|
||||
else
|
||||
@hide @$extraNav
|
||||
|
||||
|
||||
_refreshSelectedNavButton: ->
|
||||
return unless @model?.page?
|
||||
|
||||
@$('.button').removeClass 'active'
|
||||
@$(".button.#{@model.page}").addClass 'active'
|
||||
|
||||
_refreshTitle: ->
|
||||
title = @model?.controller?.getTitle()
|
||||
if title
|
||||
|
||||
@@ -12,7 +12,7 @@ html
|
||||
link(href="/images/favicon.png" rel="icon" type="image/png")
|
||||
link(href="/main.css" rel="stylesheet" type="text/css" )
|
||||
meta(charset="UTF-8")
|
||||
meta(name="viewport" content="width=480")
|
||||
meta(name="viewport" content="user-scalable=no, width=device-width")
|
||||
|
||||
body
|
||||
.view__feedback
|
||||
@@ -21,7 +21,7 @@ html
|
||||
.page
|
||||
.view__header
|
||||
|
||||
.content(style="display: none")
|
||||
.content.hidden
|
||||
.content-loading
|
||||
img(src="/images/wait.gif")
|
||||
|
||||
@@ -32,4 +32,6 @@ html
|
||||
|
||||
include ../includes/_google_adsense.jade
|
||||
include ../includes/_google_analytics.jade
|
||||
include ../includes/_google_sitelinks.jade
|
||||
include ../includes/_twitter_follow.jade
|
||||
|
||||
|
||||
@@ -36,19 +36,22 @@ html {
|
||||
}
|
||||
|
||||
& > *:first-child {
|
||||
flex: 0 0 50%;
|
||||
flex: 1 1 100%;
|
||||
|
||||
box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
.page {
|
||||
margin : $size-margin-large 0;
|
||||
max-width : $size-page-width;
|
||||
width : 100%;
|
||||
|
||||
@include screen-size(desktop) {
|
||||
margin : $size-margin-large 0;
|
||||
box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow;
|
||||
}
|
||||
|
||||
background : $color-background-page;
|
||||
box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow;
|
||||
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
.content.view__item_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
.about
|
||||
@@ -17,7 +16,7 @@
|
||||
.title
|
||||
a.sourceMod
|
||||
.button-row
|
||||
.button.craftingPlan: .bezel: p View Crafting Plan
|
||||
.button.craftingPlan: .bezel: p View <span class="full">Crafting </span>Plan
|
||||
.right
|
||||
p Official Link:
|
||||
a.officialLink project page
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
.button {
|
||||
flex: 1 1 100%;
|
||||
max-width: 66%;
|
||||
max-width: $size-minecraft-block * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,3 +58,50 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__item_page {
|
||||
.about {
|
||||
flex-direction: column;
|
||||
|
||||
& > .left {
|
||||
margin: 0 $size-margin-medium;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
}
|
||||
}
|
||||
|
||||
& > .center {
|
||||
flex: 0 0 auto;
|
||||
margin: 0 $size-margin-medium;
|
||||
|
||||
.sourceMod, .title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.sourceMod {
|
||||
}
|
||||
|
||||
.button-row {
|
||||
flex: 0 0 auto;
|
||||
margin: $size-margin-large 0;
|
||||
|
||||
.button {
|
||||
max-width: $size-minecraft-block * 8;
|
||||
.full {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .right {
|
||||
margin: 0 $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
EditableFile = require '../../models/site/editable_file'
|
||||
Item = require '../../models/game/item'
|
||||
ItemGroupController = require '../common/item_group/item_group_controller'
|
||||
@@ -42,6 +41,7 @@ module.exports = class ItemPageController extends PageController
|
||||
@_itemSlug = options.itemSlug
|
||||
@_modPack = options.modPack
|
||||
@_router = options.router
|
||||
@_triggerEditing = options.login
|
||||
|
||||
@_modPack.on c.event.change, =>
|
||||
@tryRefresh()
|
||||
@@ -68,6 +68,13 @@ module.exports = class ItemPageController extends PageController
|
||||
$("<b>#{display.itemName}</b>")
|
||||
]
|
||||
|
||||
getExtraNav: ->
|
||||
itemSlug = @_modPack.chooseRandomItem()
|
||||
return null unless itemSlug?
|
||||
|
||||
itemDisplay = @_modPack.findItemDisplay itemSlug
|
||||
return $("<a href='#{itemDisplay.itemUrl}'>Random Item</a>")
|
||||
|
||||
getMetaDescription: ->
|
||||
return null unless @_itemSlug?
|
||||
display = @_modPack.findItemDisplay @_itemSlug
|
||||
@@ -83,9 +90,11 @@ module.exports = class ItemPageController extends PageController
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper', router: @_router
|
||||
onDidModelChange: ->
|
||||
@trigger c.event.change
|
||||
super
|
||||
|
||||
onDidRender: ->
|
||||
options = imageLoader:@_imageLoader, modPack:@_modPack, router:@_router, show:false
|
||||
@_multiblockController = @addChild MultiblockViewerController, '.view__multiblock_viewer', options
|
||||
@_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options
|
||||
@@ -101,11 +110,12 @@ module.exports = class ItemPageController extends PageController
|
||||
endEditing: => @_endEditingDescription()
|
||||
enterFeedback: @_enterFeedback
|
||||
|
||||
@$aboutImage = @$('.about img')
|
||||
@$name = @$('.about .title')
|
||||
@$officialLink = @$('.about a.officialLink')
|
||||
@$sourceModLink = @$('.about a.sourceMod')
|
||||
@$aboutLinks = @$('.about .right')
|
||||
@$aboutImage = @$('.about img')
|
||||
@$craftingPlanButton = @$('.button.craftingPlan')
|
||||
@$name = @$('.about .title')
|
||||
@$officialLink = @$('.about a.officialLink')
|
||||
@$sourceModLink = @$('.about a.sourceMod')
|
||||
@$aboutLinks = @$('.about .right')
|
||||
|
||||
@$multiblockSection = @$('section.multiblock')
|
||||
@$recipeContainer = @$('section.recipes .panel')
|
||||
@@ -135,6 +145,15 @@ module.exports = class ItemPageController extends PageController
|
||||
else
|
||||
@hide @$aboutLinks
|
||||
|
||||
if @model.item.isCraftable
|
||||
@show @$craftingPlanButton
|
||||
else
|
||||
@hide @$craftingPlanButton
|
||||
|
||||
if @_triggerEditing
|
||||
@_triggerEditing = false
|
||||
@_descriptionController.onEditClicked {}
|
||||
|
||||
@show()
|
||||
else
|
||||
@hide()
|
||||
@@ -317,7 +336,7 @@ module.exports = class ItemPageController extends PageController
|
||||
item = @_modPack.findItem @_itemSlug, includeDisabled:true
|
||||
if item?
|
||||
if not ItemSlug.equal item.slug, @_itemSlug
|
||||
router.navigate c.url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
|
||||
@_router.navigate c.url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
|
||||
return
|
||||
|
||||
@model.item = item
|
||||
|
||||
@@ -75,3 +75,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__multiblock_viewer {
|
||||
flex-direction: column-reverse;
|
||||
|
||||
.left {
|
||||
flex: 0 0 auto;
|
||||
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: $size-margin-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
.view__recipe_detail {
|
||||
display : flex;
|
||||
|
||||
.input, .output{
|
||||
.input, .output {
|
||||
flex : 0 1 33%;
|
||||
|
||||
h3 {
|
||||
@@ -20,8 +20,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
order: 10;
|
||||
}
|
||||
|
||||
.pattern {
|
||||
flex : 0 1 33%;
|
||||
order: 20;
|
||||
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
@@ -36,9 +41,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
.output {
|
||||
order: 30;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top : 1px solid $color-gray-light;
|
||||
margin-top : $size-margin-medium;
|
||||
padding-top : $size-margin-large;
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__recipe_detail {
|
||||
flex-direction: column;
|
||||
|
||||
> :not(:last-child) {
|
||||
margin-bottom: $size-margin-large;
|
||||
}
|
||||
|
||||
.input, .output {
|
||||
flex: 0 0 auto;
|
||||
|
||||
|
||||
h3 {
|
||||
}
|
||||
|
||||
.view__inventory {
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
order: 21;
|
||||
}
|
||||
|
||||
.pattern {
|
||||
flex: 0 0 auto;
|
||||
|
||||
.tool {
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
//-
|
||||
//- Crafting Guide - mod_editor_page.jade
|
||||
//-
|
||||
//- Copyright © 2014-2016 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.content.view__mod_editor_page
|
||||
.left
|
||||
|
||||
.right
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Crafting Guide - mod_editor_page.scss
|
||||
//
|
||||
// Copyright © 2014-2016 by Redwood Labs
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
.view__mod_editor_page {
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Crafting Guide - mod_page_controller.coffee
|
||||
#
|
||||
# Copyright © 2014-2016 by Redwood Labs
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
PageController = require '../page_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ModPageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'mod_editor_page'
|
||||
super options
|
||||
|
||||
@_imageLoader = options.imageLoader
|
||||
@_modPack = options.modPack
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getBreadcrumbs: ->
|
||||
|
||||
getTitle: ->
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
@@ -1,5 +1,5 @@
|
||||
//-
|
||||
//- Crafting Guide - item_page.jade
|
||||
//- Crafting Guide - mod_page.jade
|
||||
//-
|
||||
//- Copyright © 2014-2016 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
.content.view__mod_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
.about
|
||||
@@ -17,8 +16,11 @@
|
||||
.title
|
||||
.author
|
||||
.description
|
||||
.modpack
|
||||
span.checkbox
|
||||
span.label I have this mod in my modpack
|
||||
.version
|
||||
span in my mod pack
|
||||
span I'm using version:
|
||||
select
|
||||
.warning.
|
||||
<b>PLEASE NOTE:</b> By selecting "no", crafting plans, search, and other features will ignore items
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Crafting Guide - item_page.scss
|
||||
// Crafting Guide - mod_page.scss
|
||||
//
|
||||
// Copyright © 2014-2016 by Redwood Labs
|
||||
// All rights reserved.
|
||||
@@ -49,8 +49,44 @@
|
||||
line-height: $font-size-medium * 1.25;
|
||||
}
|
||||
|
||||
.modpack {
|
||||
margin-top : $size-margin-large;
|
||||
|
||||
cursor : pointer;
|
||||
font-family : $font-family-control;
|
||||
font-size : $font-size-medium;
|
||||
|
||||
display : flex;
|
||||
|
||||
.checkbox {
|
||||
display : inline-block;
|
||||
height : $font-size-medium;
|
||||
margin-right : $size-margin-small;
|
||||
position : relative;
|
||||
width : $font-size-medium;
|
||||
|
||||
background : $color-white;
|
||||
border : $size-border-small solid $color-black;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: $color-gray-medium;
|
||||
}
|
||||
|
||||
&.enabled {
|
||||
.checkbox:before {
|
||||
position: absolute; top: 0; left: 1.5px; // adjust for glyph position
|
||||
content: "✕";
|
||||
}
|
||||
|
||||
.label {
|
||||
color: $color-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.version {
|
||||
margin-top: $size-margin-large;
|
||||
margin-top: $size-margin-medium;
|
||||
|
||||
font-family: $font-family-control;
|
||||
font-size: $font-size-medium;
|
||||
@@ -92,3 +128,42 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__mod_page {
|
||||
.about {
|
||||
flex-direction: column;
|
||||
|
||||
& > * {
|
||||
margin-left: $size-margin-medium;
|
||||
margin-right: $size-margin-medium;
|
||||
}
|
||||
|
||||
.left {
|
||||
margin-bottom: $size-margin-large;
|
||||
margin-left: $size-margin-medium;
|
||||
margin-right: $size-margin-medium;
|
||||
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
align-items : center;
|
||||
}
|
||||
|
||||
.center {
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: $size-margin-xlarge;
|
||||
margin-left: $size-margin-medium;
|
||||
margin-right: $size-margin-medium;
|
||||
|
||||
.author, .title {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: $size-margin-medium;
|
||||
margin-right: $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
BaseController = require '../base_controller'
|
||||
Item = require '../../models/game/item'
|
||||
ItemGroupController = require '../common/item_group/item_group_controller'
|
||||
@@ -29,6 +28,14 @@ module.exports = class ModPageController extends BaseController
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onToggleEnabled: ->
|
||||
if @model.activeVersion is Mod.Version.None
|
||||
@model.activeVersion = Mod.Version.Latest
|
||||
else
|
||||
@model.activeVersion = Mod.Version.None
|
||||
|
||||
return false
|
||||
|
||||
onVersionChanged: ->
|
||||
@model.activeVersion = @$versionSelector.val()
|
||||
return false
|
||||
@@ -58,8 +65,6 @@ module.exports = class ModPageController extends BaseController
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model: 'skyscraper'
|
||||
|
||||
@$author = @$('.about .author')
|
||||
@$description = @$('.about .description')
|
||||
@$documentationLink = @$('.about .documentation')
|
||||
@@ -67,15 +72,18 @@ module.exports = class ModPageController extends BaseController
|
||||
@$homePageLink = @$('.about .homePage')
|
||||
@$itemGroups = @$(".itemGroups")
|
||||
@$logo = @$('.about img')
|
||||
@$modpackSection = @$('.modpack')
|
||||
@$title = @$('.about .title')
|
||||
@$tutorialsContainer = @$('section.tutorials .panel')
|
||||
@$tutorialsSection = @$('section.tutorials')
|
||||
@$versionSection = @$('.version')
|
||||
@$versionSelector = @$('.version select')
|
||||
@$warning = @$('.warning')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@_refreshAboutBlock()
|
||||
@_refreshEnabled()
|
||||
@_refreshItemGroups()
|
||||
@_refreshTutorials()
|
||||
@_refreshVersionSelector()
|
||||
@@ -86,6 +94,7 @@ module.exports = class ModPageController extends BaseController
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'change .version select': 'onVersionChanged'
|
||||
'click .modpack': 'onToggleEnabled'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
@@ -107,6 +116,19 @@ module.exports = class ModPageController extends BaseController
|
||||
@$logo.attr 'src', ''
|
||||
@$title.text ''
|
||||
|
||||
_refreshEnabled: ->
|
||||
if @model.slug in c.requiredMods
|
||||
@hide @$modpackSection
|
||||
else
|
||||
@show @$modpackSection
|
||||
|
||||
if @model.activeVersion is Mod.Version.None
|
||||
@$modpackSection.removeClass 'enabled'
|
||||
@show @$warning
|
||||
else
|
||||
@$modpackSection.addClass 'enabled'
|
||||
@hide @$warning
|
||||
|
||||
_refreshItemGroups: ->
|
||||
@_groupControllers ?= []
|
||||
groupIndex = 0
|
||||
@@ -124,9 +146,10 @@ module.exports = class ModPageController extends BaseController
|
||||
router: @_router
|
||||
title: if group is Item.Group.Other then 'Items' else group
|
||||
|
||||
@_groupControllers.push controller
|
||||
@$itemGroups.append controller.$el
|
||||
controller.render()
|
||||
_.defer =>
|
||||
@_groupControllers.push controller
|
||||
@$itemGroups.append controller.$el
|
||||
controller.render()
|
||||
else
|
||||
controller.modVersion = modVersion
|
||||
controller.model = items
|
||||
@@ -163,19 +186,16 @@ module.exports = class ModPageController extends BaseController
|
||||
|
||||
_refreshVersionSelector: ->
|
||||
modVersions = @model.modVersions
|
||||
|
||||
if (@model.activeVersion is Mod.Version.None) or modVersions.length < 2
|
||||
@hide @$versionSection
|
||||
else
|
||||
@show @$versionSection
|
||||
|
||||
selectedModVersion = @effectiveModVersion
|
||||
|
||||
@$versionSelector.empty()
|
||||
|
||||
$option = $("<option value=\"none\">no</option>")
|
||||
if not @model.enabled
|
||||
@$warning.css display:''
|
||||
selectedModVersion = null
|
||||
$option.attr 'selected', true
|
||||
else
|
||||
@$warning.css display:'none'
|
||||
@$versionSelector.append $option
|
||||
|
||||
for modVersion in @model.modVersions
|
||||
$option = $("<option value=\"#{modVersion.version}\">#{modVersion.version}</option>")
|
||||
if modVersion is selectedModVersion
|
||||
|
||||
@@ -7,9 +7,86 @@
|
||||
|
||||
.content.view__news_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
include ../common/twitter/twitter.jade
|
||||
|
||||
section
|
||||
h3 2016-04-30
|
||||
.panel
|
||||
p.
|
||||
Big news... no, huge news... no, tiny news! Crafting Guide is now fully functional on any size
|
||||
screen from a 30" desktop monitor all the way down to a 4" phone. Just grab your favorite mobile
|
||||
device and give it a try!
|
||||
|
||||
section
|
||||
h3 2016-04-24
|
||||
.panel
|
||||
p.
|
||||
I've been knocking off a few more feature requests over the weekend. First, I've made the entire
|
||||
site respond to being on a smaller screen (tablet-sized for now, phone-sized will be next).
|
||||
Hopefully, it should just feel pretty natural on whatever screen size, and you won't notice any big
|
||||
differences from one to the other.
|
||||
p.
|
||||
The second small change is that whenever you're looking at a recipe which calls for a <i>lot</i> of
|
||||
some item, you can hover over the quantity to see what it would be in stacks + the remainder. For
|
||||
example, 127 translates to: 1x64+63. That should make it easier to think about large builds.
|
||||
|
||||
section
|
||||
h3 2016-04-23
|
||||
.panel
|
||||
p.
|
||||
I've spent some time working on the crafting page today, and I think you'll find it a lot easier to
|
||||
adjust your plans now. The big difference is that the site no longer automatically calculate.
|
||||
Instead, you have to deliberately press a button when you're ready for a new plan. This allows you
|
||||
to check out an existing plan, mark certain steps complete, adjust your inventory, and only when
|
||||
you're ready, click the button for a new plan. Not a huge change, but I think you'll find yourself
|
||||
adjusting a not-quite-right plan a lot more often now!
|
||||
|
||||
section
|
||||
h3 2016-04-21
|
||||
.panel
|
||||
p.
|
||||
The most highly-requested mod currently on my list is <a href="/browse/tinkers_construct">Tinker's
|
||||
Construct</a>, and I'm pleased to announce that it is now available on Crafting Guide! In case you
|
||||
aren't familiar with it, it adds the ability to create tools by crafting together individual parts
|
||||
made from different materials, and adds a complex smelting mechanic which allows you to create a
|
||||
variety of useful metal alloys. This smelting has the side-effect of producing two ingots for every
|
||||
block of ore as well, so you can very rapidly get to ore-doubling without having to have already got
|
||||
a complex power system up and running.
|
||||
p.
|
||||
There is <i>one</i> thing missing. I didn't include any recipes for the actual tools themselves.
|
||||
The problem, of course, is that you can mix and match parts made from any of the supported
|
||||
materials, and that leads to thousands upon thousands of possible tools: way more than would ever be
|
||||
practical to include in Crafting Guide in the obvious way other items are included.
|
||||
p.
|
||||
The plan, then, is to create a feature just for Tinker's Construct which allows you to select a tool
|
||||
to create, and then pick and choose the material types for each part. You'll then be able to make a
|
||||
crafting plan for those parts. If that sounds like something you'd use, head over to <a
|
||||
href="https://github.com/andrewminer/crafting-guide/issues/214">GitHub</a> and add your vote!
|
||||
|
||||
section
|
||||
h3 2016-04-16
|
||||
.panel
|
||||
p.
|
||||
I've been working on adding a new mod, and I ran across a bug which has been in the system for a
|
||||
while now, but which will cause serious problems with a lot of the recipes in the new mod. So, I put
|
||||
the mod aside for a bit to fix it.
|
||||
p.
|
||||
The bug was that when you are making something like an <a
|
||||
href="/browse/forge_multipart/oak_wood_cover">Oak Wood Cover</a> the <a
|
||||
href="/browse/forge_multipart/stone_saw">saw</a> wouldn't be part of the crafting plan. This isn't
|
||||
such a big deal for most things, but for this new mod, it would have been a major problem.
|
||||
|
||||
section
|
||||
h3 2016-04-14
|
||||
.panel
|
||||
p.
|
||||
In between adding new features to the website, I've taken a little break to add support for
|
||||
<a href="/browse/projectred">ProjectRed</a>. It takes up the mantle of the retired RedPower mod
|
||||
and adds a lot of what that one used to provide: logic gates, cables, pneumatic tubes, and lots and
|
||||
lots of new lights and lamps.
|
||||
|
||||
section
|
||||
h3 2016-04-05
|
||||
.panel
|
||||
@@ -79,54 +156,3 @@
|
||||
p.
|
||||
With many thanks to <a href="https://github.com/pkmnfrk">Mike Caron</a>, I'm pleased to announce
|
||||
support for <a href="/browse/storage_drawers">Storage Drawers</a>!
|
||||
|
||||
section
|
||||
h3 2015-12-13
|
||||
.panel
|
||||
p.
|
||||
I'm super excited to announce that I've added full multi-block support for Crafting Guide! For
|
||||
example, check out a <a href="/browse/big_reactors/5_core_passive_reactor">5-Core Reactor</a>
|
||||
from Big Reactors, or the <a href="/browse/railcraft/steel_tank_5x5x5">5x5x5 Steel Tank</a> from
|
||||
Railcraft. I'm really pleased with how it turned out!
|
||||
|
||||
section
|
||||
h3 2015-11-17
|
||||
.panel
|
||||
p.
|
||||
And today, it's <a href="/browse/extra_cells">Extra Cells</a>!
|
||||
|
||||
section
|
||||
h3 2015-11-16
|
||||
.panel
|
||||
p.
|
||||
It's a small one, but also highly requested... Here's <a
|
||||
href="/browse/computercraft">ComputerCraft</a>!
|
||||
|
||||
section
|
||||
h3 2015-11-14
|
||||
.panel
|
||||
p.
|
||||
One more small one over the weekend... <a href="/browse/advanced_solar_panels">Advanced Solar
|
||||
Panels</a> has been added to crafting guide!
|
||||
|
||||
section
|
||||
h3 2015-11-14
|
||||
.panel
|
||||
p.
|
||||
For a long while now, <a href="/browse/galacticraft">Galacticraft</a> has been the most
|
||||
requested mod, and it's finally here! Enjoy!
|
||||
|
||||
section
|
||||
h3 2015-11-10
|
||||
.panel
|
||||
p.
|
||||
Remember me? They guy who runs the site. Yeah, I'm back, and with big news! The site now has
|
||||
a completely new crafting algorithm. Instead of just taking the first crafting plan it comes up
|
||||
with, it tries to compute every possible plan, rates them, and then picks the best one. This
|
||||
also clears up a lot of bugs related to the old algorithm. The one drawback is that some items
|
||||
can take a bit longer to compute than with the old way, but I think you'll find it's worth it!
|
||||
p.
|
||||
On a personal note, I think it's clear that I don't have nearly as much time to dedicate to the
|
||||
site as I used to. That's mostly because I started a new job which keeps me away from working
|
||||
on the site so much. I hope to be able to get into a more regular pace now things my personal
|
||||
life has settled down again.
|
||||
|
||||
@@ -8,22 +8,32 @@
|
||||
.view__news_page {
|
||||
@include layout-body-with-sidebar;
|
||||
|
||||
section {
|
||||
&:not(:first-child) {
|
||||
margin-top : $size-margin-large;
|
||||
& > .right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
.view__twitter {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom : $size-margin-small;
|
||||
}
|
||||
section {
|
||||
&:not(:first-child) {
|
||||
margin-top : $size-margin-large;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family : $font-family-text;
|
||||
font-size : $font-size-medium;
|
||||
line-height : $font-size-medium * 1.5;
|
||||
h3 {
|
||||
margin-bottom : $size-margin-small;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom : $size-margin-medium;
|
||||
p {
|
||||
font-family : $font-family-text;
|
||||
font-size : $font-size-medium;
|
||||
line-height : $font-size-medium * 1.5;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom : $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
PageController = require '../page_controller'
|
||||
PageController = require '../page_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -24,11 +23,6 @@ module.exports = class NewsPageController extends PageController
|
||||
getTitle: ->
|
||||
return "News"
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
|
||||
@@ -19,6 +19,10 @@ module.exports = class PageController extends BaseController
|
||||
getBreadcrumbs: ->
|
||||
return []
|
||||
|
||||
getExtraNav: ->
|
||||
# subclasses may override this to provide extra content in the right-hand side of the breadcrumb bar
|
||||
return null
|
||||
|
||||
getMetaDescription: ->
|
||||
# subclasses should override this to return the page-specific text for the meta description tag
|
||||
return null
|
||||
|
||||
@@ -11,6 +11,7 @@ ItemPageController = require './item_page/item_page_controller'
|
||||
ItemSlug = require '../models/game/item_slug'
|
||||
LoginPageController = require './login_page/login_page_controller'
|
||||
ModPageController = require './mod_page/mod_page_controller'
|
||||
ModEditorPageController = require './mod_editor_page/mod_editor_page_controller'
|
||||
NewsPageController = require './news_page/news_page_controller'
|
||||
TutorialPageController = require './tutorial_page/tutorial_page_controller'
|
||||
UrlParams = require './url_params'
|
||||
@@ -66,6 +67,10 @@ module.exports = class Router extends Backbone.Router
|
||||
'craft/:text/': 'route__craft'
|
||||
'craft/:text/index.html': 'route__craft'
|
||||
|
||||
'edit/:modSlug': 'route__editMod'
|
||||
'edit/:modSlug/': 'route__editMod'
|
||||
'edit/:modSlug/index.html': 'route__editMod'
|
||||
|
||||
'login': 'route__login'
|
||||
'login/': 'route__login'
|
||||
'login/index.html': 'route__login'
|
||||
@@ -98,17 +103,25 @@ module.exports = class Router extends Backbone.Router
|
||||
@_siteController.setPage 'browseMod', controller
|
||||
|
||||
route__browseModItem: (modSlug, itemSlug)->
|
||||
params = new UrlParams login:{type:'boolean', default:false}
|
||||
slug = new ItemSlug modSlug, itemSlug
|
||||
controller = new ItemPageController @_makeOptions {itemSlug:slug}
|
||||
controller = new ItemPageController @_makeOptions {itemSlug:slug, login:params.login}
|
||||
@_siteController.setPage 'browseModItem', controller
|
||||
|
||||
route__browseTutorial: (modSlug, tutorialSlug)->
|
||||
controller = new TutorialPageController @_makeOptions {modSlug:modSlug, tutorialSlug:tutorialSlug}
|
||||
params = new UrlParams login:{type:'boolean', default:false}
|
||||
controller = new TutorialPageController @_makeOptions
|
||||
login:params.login, modSlug:modSlug, tutorialSlug:tutorialSlug
|
||||
@_siteController.setPage 'browseTutorial', controller
|
||||
|
||||
route__configure: ->
|
||||
@route__craft()
|
||||
|
||||
route__editMod: (modSlug)->
|
||||
controller = new ModEditorPageController @_makeOptions()
|
||||
controller.model = @_siteController.modPack.getMod modSlug
|
||||
@_siteController.setPage 'editMod', controller
|
||||
|
||||
route__craft: (text)->
|
||||
controller = new CraftPageController @_makeOptions {}
|
||||
controller.model.params = inventoryText:text
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require './common/adsense/adsense_controller'
|
||||
BaseController = require './base_controller'
|
||||
FeedbackController = require './feedback/feedback_controller'
|
||||
FileCache = require '../models/site/file_cache'
|
||||
FooterController = require './footer/footer_controller'
|
||||
GitHubUser = require '../models/site/github_user'
|
||||
HeaderController = require './header/header_controller'
|
||||
@@ -26,11 +28,13 @@ module.exports = class SiteController extends BaseController
|
||||
super options
|
||||
|
||||
@client = options.client
|
||||
@fileCache = new FileCache c.url.modpackArchive()
|
||||
@imageLoader = new ImageLoader defaultUrl:'/images/unknown.png'
|
||||
@modPack = new ModPack
|
||||
@modPack = new ModPack {}, fileCache:@fileCache
|
||||
@router = new Router this
|
||||
@storage = options.storage
|
||||
|
||||
@_adsenseController = new AdsenseController
|
||||
@_currentPage = null
|
||||
@_currentPageController = null
|
||||
@_user = null
|
||||
@@ -42,7 +46,7 @@ module.exports = class SiteController extends BaseController
|
||||
m.activeModVersion.fetch() if m.activeModVersion?
|
||||
|
||||
for modSlug, modData of c.defaultMods
|
||||
mod = new Mod slug:modSlug
|
||||
mod = new Mod {slug:modSlug}, {fileCache:@fileCache}
|
||||
mod.on c.event.change + ':activeModVersion', makeResponder mod
|
||||
@storage.register "mod:#{mod.slug}", mod, 'activeVersion', modData.defaultVersion
|
||||
mod.fetch()
|
||||
@@ -51,8 +55,8 @@ module.exports = class SiteController extends BaseController
|
||||
|
||||
if global.env isnt 'prerender'
|
||||
@modPack.once c.event.sync, =>
|
||||
@$pageContent.css 'display', ''
|
||||
@$pageContentLoading.css 'display', 'none'
|
||||
@$pageContent.removeClass 'hidden'
|
||||
@$pageContentLoading.addClass 'hidden'
|
||||
|
||||
loadCurrentUser: ->
|
||||
@client.fetchCurrentUser()
|
||||
@@ -80,7 +84,7 @@ module.exports = class SiteController extends BaseController
|
||||
|
||||
resumeAfterLogin: ->
|
||||
url = @storage.load 'post-login-url'
|
||||
url = if (not url? or url is 'null') then null else url
|
||||
url = if (not url? or url is 'null') then null else url + '?login=true'
|
||||
if url? then @router.navigate url, trigger:true
|
||||
@storage.store 'post-login-url', null
|
||||
|
||||
@@ -142,16 +146,21 @@ module.exports = class SiteController extends BaseController
|
||||
$pageContent = $('.page > .content')
|
||||
$pageContent.removeClass()
|
||||
$pageContent.addClass 'content'
|
||||
$pageContent.css display:''
|
||||
if not @$pageContentLoading.hasClass 'hidden'
|
||||
$pageContent.addClass 'hidden'
|
||||
|
||||
window.scrollTo 0, 0
|
||||
|
||||
@_headerController.model = controller: controller
|
||||
@_headerController.model = controller: controller, page: page
|
||||
|
||||
@_currentPageController.user = @user
|
||||
@_currentPageController.onWillShow()
|
||||
@_currentPageController.$el = $pageContent
|
||||
@_currentPageController.render()
|
||||
|
||||
@_adsenseController.reset()
|
||||
|
||||
_resetGlobals: ->
|
||||
if global.env in c.productionEnvs
|
||||
for key, value of global
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
.view__tutorial_page
|
||||
.left
|
||||
.view__adsense
|
||||
|
||||
.right
|
||||
.about
|
||||
|
||||
@@ -51,12 +51,28 @@
|
||||
margin-top : -$size-margin-medium;
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
padding-right : -$size-margin-medium;
|
||||
|
||||
& > * {
|
||||
flex : 1 1 100%;
|
||||
margin-right : $size-margin-medium;
|
||||
margin-top : $size-margin-medium;
|
||||
max-width : calc(50% - 12px); // $size-margin-medium
|
||||
width : calc(50% - 12px); // $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include screen-size(mobile) {
|
||||
.view__tutorial_page {
|
||||
.video-container {
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: stretch;
|
||||
|
||||
& > * {
|
||||
width: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
AdsenseController = require '../common/adsense/adsense_controller'
|
||||
PageController = require '../page_controller'
|
||||
MarkdownSectionController = require '../common/markdown_section/markdown_section_controller'
|
||||
VideoController = require '../common/video/video_controller'
|
||||
@@ -60,8 +59,6 @@ module.exports = class TutorialPageController extends PageController
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
|
||||
|
||||
@$sourceModLink = @$('.sourceMod a')
|
||||
@$officialLink = @$('.officialLink a')
|
||||
@$officialLinkPanel = @$('.officialLink')
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
background : url('/images/button-background-hover.png') repeat;
|
||||
}
|
||||
|
||||
&:active {
|
||||
&:active, &.active {
|
||||
background : url('/images/button-background-active.png') repeat;
|
||||
|
||||
.bezel {
|
||||
@@ -69,15 +69,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.page > .content {
|
||||
min-height: $size-skyscraper-height;
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.skyscraper {
|
||||
height : $size-skyscraper-height - 2px;
|
||||
width : $size-skyscraper-width - 2px;
|
||||
|
||||
border : 1px solid $color-gray-medium;
|
||||
.page > .content {
|
||||
min-height: $size-ad-skyscraper-height;
|
||||
}
|
||||
|
||||
.scrollDisabled {
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
// normalize all values
|
||||
@import './reset';
|
||||
|
||||
// define media breakpoints
|
||||
@import './media';
|
||||
|
||||
// define variables
|
||||
@import './colors';
|
||||
@import './fonts';
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Crafting Guide - fonts.scss
|
||||
//
|
||||
// Copyright © 2014-2016 by Redwood Labs
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
$tablet : 960px;
|
||||
$mobile : 568px;
|
||||
|
||||
@mixin screen-size($screenType) {
|
||||
@if $screenType == desktop {
|
||||
@media (min-width: $tablet + 1) { @content; }
|
||||
} @else if $screenType == tablet {
|
||||
@media (max-width: $tablet) { @content; }
|
||||
} @else if $screenType == mobile {
|
||||
@media (max-width: $mobile) { @content; }
|
||||
} @else if $screenType == not-mobile {
|
||||
@media (min-width: $mobile + 1) { @content }
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,11 @@
|
||||
filter : blur($radius);
|
||||
}
|
||||
|
||||
@mixin floating-panel {
|
||||
background: $color-background-panel;
|
||||
box-shadow: $size-margin-xxsmall $size-margin-xxsmall $size-margin-xsmall $color-shadow;
|
||||
}
|
||||
|
||||
@mixin grayscale {
|
||||
-webkit-filter : grayscale(100%);
|
||||
-moz-filter : grayscale(100%);
|
||||
@@ -18,6 +23,66 @@
|
||||
filter : gray;
|
||||
}
|
||||
|
||||
@mixin layout-body-with-sidebar {
|
||||
display: flex;
|
||||
|
||||
& > .left {
|
||||
flex : 0 0 $size-ad-skyscraper-width + $size-margin-medium;
|
||||
min-height : $size-ad-skyscraper-height;
|
||||
|
||||
padding-right : $size-margin-medium;
|
||||
|
||||
@include screen-size(tablet) {
|
||||
display : none;
|
||||
}
|
||||
@include screen-size(mobile) {
|
||||
display : none;
|
||||
}
|
||||
}
|
||||
|
||||
& > .right {
|
||||
flex : 1 1 100%;
|
||||
|
||||
@include screen-size(tablet) {
|
||||
margin : 0 $size-margin-xlarge;
|
||||
max-width: calc(100% - 2 * 48px); // 2 * $size-margin-xlarge
|
||||
}
|
||||
@include screen-size(mobile) {
|
||||
margin : 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom : $size-margin-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin layout-link-list {
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
justify-content : center;
|
||||
|
||||
p {
|
||||
margin-bottom : $size-margin-small;
|
||||
|
||||
font-family : $font-family-text;
|
||||
font-size : $font-size-large;
|
||||
}
|
||||
|
||||
a {
|
||||
margin-left : $size-margin-medium;
|
||||
|
||||
font-family : $font-family-text;
|
||||
font-size : $font-size-medium;
|
||||
text-decoration : underline;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom : $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin no-select {
|
||||
-webkit-touch-callout : none; /* iOS Safari */
|
||||
-webkit-user-select : none; /* Chrome/Safari/Opera */
|
||||
@@ -26,36 +91,6 @@
|
||||
user-select : none; /* non-prefixed version, currently not supported by any browser */
|
||||
}
|
||||
|
||||
@mixin floating-panel {
|
||||
background: $color-background-panel;
|
||||
box-shadow: $size-margin-xxsmall $size-margin-xxsmall $size-margin-xsmall $color-shadow;
|
||||
}
|
||||
|
||||
@mixin layout-link-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
p {
|
||||
margin-bottom: $size-margin-small;
|
||||
|
||||
font-family: $font-family-text;
|
||||
font-size: $font-size-large;
|
||||
}
|
||||
|
||||
a {
|
||||
margin-left: $size-margin-medium;
|
||||
|
||||
font-family: $font-family-text;
|
||||
font-size: $font-size-medium;
|
||||
text-decoration: underline;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: $size-margin-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin pixel-image {
|
||||
image-rendering : -moz-crisp-edges; /* Firefox */
|
||||
image-rendering : -o-crisp-edges; /* Opera */
|
||||
@@ -63,20 +98,3 @@
|
||||
image-rendering : crisp-edges;
|
||||
-ms-interpolation-mode : nearest-neighbor; /* IE (non-standard property) */
|
||||
}
|
||||
|
||||
@mixin layout-body-with-sidebar {
|
||||
display: flex;
|
||||
|
||||
& > .left {
|
||||
flex: 0 0 $size-skyscraper-width + $size-margin-medium;
|
||||
padding-right: $size-margin-medium;
|
||||
}
|
||||
|
||||
& > .right {
|
||||
flex: 1 1 auto;
|
||||
|
||||
section {
|
||||
margin-bottom: $size-margin-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,9 @@ $size-minecraft-block : 32px;
|
||||
|
||||
$size-page-width : $size-rem * 80;
|
||||
|
||||
$size-skyscraper-height : 600px;
|
||||
$size-skyscraper-width : 160px;
|
||||
$size-ad-large-mobile-banner-height : 100px;
|
||||
$size-ad-large-mobile-banner-width : 320px;
|
||||
$size-ad-leaderboard-height : 90px;
|
||||
$size-ad-leaderboard-width : 728px;
|
||||
$size-ad-skyscraper-height : 600px;
|
||||
$size-ad-skyscraper-width : 160px;
|
||||
|
||||
@@ -7,24 +7,39 @@
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
exports.adsense = adsense = {}
|
||||
adsense.clientId = 'ca-pub-6593013914878730'
|
||||
adsense.skyscraper = {}
|
||||
adsense.skyscraper.height = 600
|
||||
adsense.skyscraper.width = 160
|
||||
adsense.skyscraper.margin = 24
|
||||
adsense.slotIds = ['7613920409', '9574673605', '3388539204']
|
||||
exports.adsense = adsense = {}
|
||||
adsense.adTypeMap = desktop:'skyscraper', tablet:'leaderboard', mobile:'largeMobileBanner'
|
||||
adsense.clientId = 'ca-pub-6593013914878730'
|
||||
adsense.largeMobileBanner = {}
|
||||
adsense.largeMobileBanner.cssClass = 'large-mobile-banner'
|
||||
adsense.largeMobileBanner.height = 100 # px
|
||||
adsense.largeMobileBanner.slotIds = ['6651071600', '2081271209', '3558004401']
|
||||
adsense.largeMobileBanner.width = 320 # px
|
||||
adsense.leaderboard = {}
|
||||
adsense.leaderboard.cssClass = 'leaderboard'
|
||||
adsense.leaderboard.height = 90 # px
|
||||
adsense.leaderboard.slotIds = ['6790672401', '8267405609', '5174338406']
|
||||
adsense.leaderboard.width = 728 # px
|
||||
adsense.minimumDistance = 100 # px
|
||||
adsense.readinessCheckInterval = 1000 # ms
|
||||
adsense.skyscraper = {}
|
||||
adsense.skyscraper.cssClass = 'skyscraper'
|
||||
adsense.skyscraper.height = 600 # px
|
||||
adsense.skyscraper.margin = 24 # px
|
||||
adsense.skyscraper.slotIds = ['7613920409', '9574673605', '3388539204']
|
||||
adsense.skyscraper.width = 160 # px
|
||||
|
||||
exports.defaultMods = defaultMods = {}
|
||||
defaultMods.minecraft = { defaultVersion: '1.7.10' } # Minecraft must be first
|
||||
|
||||
defaultMods.advanced_solar_panels = { defaultVersion: '3.5.1' }
|
||||
defaultMods.agricraft = { defaultVersion: '1.4.6' }
|
||||
defaultMods.applied_energistics_2 = { defaultVersion: 'rv1-stable-1' }
|
||||
defaultMods.big_reactors = { defaultVersion: '0.4.2A2' }
|
||||
defaultMods.buildcraft = { defaultVersion: '6.4.6' }
|
||||
defaultMods.computercraft = { defaultVersion: '1.74' }
|
||||
defaultMods.enderio = { defaultVersion: '2.2.7.325' }
|
||||
defaultMods.ender_storage = { defaultVersion: '1.4.5.29' }
|
||||
defaultMods.enderio = { defaultVersion: '2.2.7.325' }
|
||||
defaultMods.extra_cells = { defaultVersion: '2.2.73b129' }
|
||||
defaultMods.extra_utilities = { defaultVersion: '1.2.2' }
|
||||
defaultMods.forestry = { defaultVersion: '3.4.0.7' }
|
||||
@@ -35,16 +50,20 @@ defaultMods.ic2_classic = { defaultVersion: 'none' }
|
||||
defaultMods.industrial_craft_2 = { defaultVersion: '2.2.663' }
|
||||
defaultMods.iron_chests = { defaultVersion: '6.0.62.742' }
|
||||
defaultMods.jabba = { defaultVersion: '1.2.1a' }
|
||||
defaultMods.logistics_pipes = { defaultVersion: '0.9.3.100' }
|
||||
defaultMods.mekanism = { defaultVersion: '7.1.1.127' }
|
||||
defaultMods.minefactory_reloaded = { defaultVersion: '2.8.0RC8-86' }
|
||||
defaultMods.modular_powersuits = { defaultVersion: '0.11.0-300-thermal-expansion' }
|
||||
defaultMods.opencomputers = { defaultVersion: '1.5.22' }
|
||||
defaultMods.quantum_flux = { defaultVersion: '1.3.4' }
|
||||
defaultMods.project_red = { defaultVersion: '4.5.16.77' }
|
||||
defaultMods.railcraft = { defaultVersion: '9.5.0' }
|
||||
defaultMods.simply_jetpacks = { defaultVersion: '1.4.1' }
|
||||
defaultMods.solar_flux = { defaultVersion: '0.5b' }
|
||||
defaultMods.storage_drawers = { defaultVersion: '1.7.10-1.6.2' }
|
||||
defaultMods.thermal_dynamics = { defaultVersion: '1.0.0RC7-98' }
|
||||
defaultMods.thermal_expansion = { defaultVersion: '4.0.0B8-23' }
|
||||
defaultMods.tinkers_construct = { defaultVersion: '1.7.10-1.8.8' }
|
||||
|
||||
exports.duration = duration = {}
|
||||
duration.snap = 100
|
||||
@@ -109,6 +128,20 @@ exports.productionEnvs = [ 'staging', 'production' ]
|
||||
|
||||
exports.requiredMods = [ 'minecraft' ]
|
||||
|
||||
exports.screen = screen = {}
|
||||
screen.mobileMaxWidth = 568 # px
|
||||
screen.tabletMaxWidth = 960 # px
|
||||
screen.type = {}
|
||||
screen.type.desktop = 'desktop'
|
||||
screen.type.mobile = 'mobile'
|
||||
screen.type.tablet = 'tablet'
|
||||
|
||||
screen.type.compute = ->
|
||||
width = $(document).width()
|
||||
return screen.type.mobile if width <= screen.mobileMaxWidth
|
||||
return screen.type.tablet if width <= screen.tabletMaxWidth
|
||||
return screen.type.desktop
|
||||
|
||||
exports.server = {}
|
||||
exports.server.defaultPort = 8080
|
||||
|
||||
@@ -133,6 +166,7 @@ url.login = _.template "/login"
|
||||
url.mod = _.template "/browse/<%= modSlug %>/"
|
||||
url.modData = _.template "/data/<%= modSlug %>/mod.cg"
|
||||
url.modIcon = _.template "/data/<%= modSlug %>/icon.png"
|
||||
url.modpackArchive = _.template "/data/modpack.cg"
|
||||
url.modVersionData = _.template "/data/<%= modSlug %>/versions/<%= modVersion %>/mod-version.cg"
|
||||
url.root = _.template "/"
|
||||
url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/"
|
||||
|
||||
@@ -16,5 +16,6 @@ sendIndex = (request, response)->
|
||||
|
||||
router.get '/browse*', sendIndex
|
||||
router.get '/craft*', sendIndex
|
||||
router.get '/edit*', sendIndex
|
||||
router.get '/login*', sendIndex
|
||||
router.get '/news*', sendIndex
|
||||
|
||||
Reference in New Issue
Block a user