Author SHA1 Message Date
Andrew Miner 240a14da58 wip 2016-05-10 21:12:38 -07:00
Andrew Miner c441d75529 Fix layout issues on News Page 2016-05-07 14:50:06 -07:00
Andrew Miner 1bc89c1c89 Fix layout issues for News page 2016-05-07 14:47:07 -07:00
Andrew Miner 43202e9917 Add link to Twitter account
fixes #226
2016-05-07 14:41:47 -07:00
Andrew Miner 05bc1a271d Add support for Google Sitelinks
fixes #187
2016-05-07 13:36:49 -07:00
Andrew Miner da1419d6b6 Add a "Random Item" link to the breadcrumb bar
fixes #216
2016-05-07 12:25:21 -07:00
Andrew Miner 841fac38d3 Correct errors on mobile search feature
fixes #235, #233
2016-05-07 09:49:51 -07:00
Andrew Miner 2b8e23b32f Fix layout of video sections on mobile 2016-05-07 09:39:11 -07:00
Andrew Miner 5eae2bb488 Start editing after login needed for editing
When a user isn't logged in, click the "Edit" button on an item
description will initiate the login process.  After it is complete,
the user is placed back on the page where they started.  However,
the edit box remains closed.  So, after all the activity which
resulted in trying to edit, they user still has to click the edit
button one more time to actually start editing.

This change makes it so that the user returning from the login
process is placed directly into edit mode without having to click the
button a second time.

fixes #237
2016-05-07 08:12:39 -07:00
Andrew Miner 6fa18c764b Correct keyboard handling errors in item selector
fixes #227, #218
2016-05-06 21:30:41 -07:00
Andrew Miner c9796a142d Improve scrolling behavior on mobile
fixes #221
2016-05-05 21:20:41 -07:00
Andrew Miner 0718590f56 Don't use large inventory on mobile crafting page
fixes #219
2016-05-04 21:50:48 -07:00
Andrew Miner 51f566ebf1 Mark button for current page as active
fixes #232
2016-05-04 21:27:23 -07:00
Andrew Miner d2d904be7f Don't override index.html from prerendered pages 2016-05-04 20:20:44 -07:00
Andrew Miner 088994f366 Correct bug where prerendered pages don't display 2016-05-03 22:22:03 -07:00
Andrew Miner 184b64a6af No sourcemaps for CSS 2016-05-03 22:06:36 -07:00
Andrew Miner 4aca035709 Correct sizing problem with mod tiles 2016-05-03 20:42:36 -07:00
Andrew Miner ebf3443e96 Update Adsense to place ads on all devices
The current adsense implementation only places ads on desktop-sized
screens.  This change allows ads of the appropriate size to be
displayed on any device.

fixes #224
2016-05-03 20:25:56 -07:00
Andrew Miner fd5372b35d Add announcement of mobile site 2016-04-30 13:02:41 -07:00
Andrew Miner f464558cd2 Don't show "login" button on mobile 2016-04-30 13:00:14 -07:00
Andrew Miner e7cd3f0549 Complete mobile reactiveness in CSS layer 2016-04-30 11:31:49 -07:00
Andrew Miner 545408a7e7 Fixes for reactivity in Safari 2016-04-29 23:08:08 -07:00
Andrew Miner 83156c30c7 Initial progress towards responsive for mobile 2016-04-29 22:30:37 -07:00
Andrew Miner 636a8d061c Don't show page until fully loaded 2016-04-28 22:38:04 -07:00
Andrew Miner 2dbda99986 Allow FileCache to operate on file markers midline 2016-04-28 20:22:54 -07:00
Andrew Miner 7d83552013 Load all data files from a single archive 2016-04-27 22:47:44 -07:00
Andrew Miner 35bb12de6a Show crafting plan button only when craftable 2016-04-26 21:53:39 -07:00
Andrew Miner 1d1772e961 Make the mod version selector more clear
This change the single select box into a checkbox which toggles the
mod on/off.  If the mod is "on" and it has multiple versions, then
a selection list will be shown with the various possible versions.
If there is only a single available version, then the selector is
not shown.
2016-04-26 21:40:52 -07:00
Andrew Miner 6787063ac7 Prevent border around tool buttons on craft page 2016-04-26 20:31:51 -07:00
Andrew Miner 9e09b8d87c Make "outdated" background more pronounced 2016-04-26 20:25:20 -07:00
Andrew Miner 2c77972073 Correct several small bugs found in user testing
* The "Show Plan for Tools" link should open a new window each time
    it is clicked (i.e., don't re-use the same window)
  * Further customize the title of the crafting page to give some
    indication of what is being crafted
2016-04-25 21:54:28 -07:00
Andrew Miner 31f4594928 Don't show border on a pretending to be buttons 2016-04-24 15:21:12 -07:00
Andrew Miner eb9ac15de8 Show stack quantity tooltip for large quantities
When hovering over a quantity in an inventory display, if the
quantity is larger than one stack (i.e., 64 items), display a
tooltip showing the quantity in stacks (plus the remainder).
2016-04-24 15:17:46 -07:00
Andrew Miner e922f3c5cc Fix iOS viewport meta tag 2016-04-23 20:22:05 -07:00
Andrew Miner a8d08b93c5 Add reactive styles for Tablets 2016-04-23 20:10:09 -07:00
Andrew Miner 64e118a2c8 Open crafting plan for tools in a new window 2016-04-23 16:54:50 -07:00
Andrew Miner 6671541dcb Announce changes to crafting page 2016-04-23 11:58:48 -07:00
Andrew Miner 962165dc8e Don't automatically recalculate crafting plans
Instead, any time a change is made which invalidates a crafting plan,
update the visual display to show that the plan is out of date, and
add some extra affordances to recalculate.
2016-04-23 11:46:35 -07:00
Andrew Miner f9b65dd892 3.2.4 2016-04-21 22:59:37 -07:00
Andrew Miner 979586d9d3 Add Tinker's Construct 2016-04-21 22:59:00 -07:00
Andrew Miner c522e60e28 Fix router error on item page 2016-04-20 22:58:58 -07:00
Andrew Miner f9cd38947d Create item group controllers off main event loop 2016-04-20 22:30:55 -07:00
Andrew Miner 99b6cf2861 Don't clear user inventory between crafting plans 2016-04-20 22:30:14 -07:00
Andrew Miner d925a17940 Do not show pass-through items in derived items
For the various derived item groups on the item detail page, do not
show pass through items as being related (e.g., "Used to Make").
2016-04-20 22:28:42 -07:00
Andrew Miner a2bbdf4645 Improve perf. looking up item display data 2016-04-20 22:27:22 -07:00
Andrew Miner 93c98e16ac Further fixes of how passthrough items are handled
* When evaluating a plan, only give the pass-through treatment to
  items if the step they're part of was actually executed
* When marking a step "complete", ignore passthrough items
2016-04-16 20:33:05 -07:00
Andrew Miner 88e57b1200 Improve handling of pass-through items in recipes 2016-04-16 12:20:29 -07:00
Andrew Miner 1e96cf2d6c 3.2.3 2016-04-14 20:59:20 -07:00
Andrew Miner ccaf8e9842 Add ProjectRed 2016-04-14 20:54:44 -07:00
Andrew Miner e1f8282049 Fix bug with evaluating mod conditions 2016-04-10 14:10:23 -07:00
Andrew Miner d873c4b7f1 Fix layout bug on browse page in Safari 2016-04-10 14:09:56 -07:00
Andrew Miner 3529bccf3a Add back mods lost in website upgrade 2016-04-10 14:08:38 -07:00
95 changed files with 2301 additions and 462 deletions
+7 -2
View File
@@ -54,7 +54,7 @@ module.exports = (grunt)->
mode: 'gzip' mode: 'gzip'
files: [ files: [
{expand: true, cwd:'./build/static', src:'**/*.css', dest:'./dist/'} {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:'**/*.ugly.js', dest:'./dist/', ext: '.js'}
{expand: true, cwd:'./build/static', src:'**/*.json', dest:'./dist/'} {expand: true, cwd:'./build/static', src:'**/*.json', dest:'./dist/'}
{expand: true, cwd:'./build/static', src:'**/*.ttf', dest:'./dist/'} {expand: true, cwd:'./build/static', src:'**/*.ttf', dest:'./dist/'}
@@ -77,7 +77,10 @@ module.exports = (grunt)->
] ]
build_to_dist: build_to_dist:
files: [ 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: common_source:
files: [ files: [
@@ -135,6 +138,8 @@ module.exports = (grunt)->
sass: sass:
all: all:
options:
sourcemap: 'none'
files: files:
'./build/static/main.css': [ './build/imports.scss' ] './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
View File
@@ -1,6 +1,6 @@
{ {
"name": "crafting-guide", "name": "crafting-guide",
"version": "3.2.2", "version": "3.2.4",
"description": "A guide for building anything in Minecraft or its many mods", "description": "A guide for building anything in Minecraft or its many mods",
"main": "./dist/index.js", "main": "./dist/index.js",
"repository": "http://github.com/andrewminer/crafting-guide", "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"
}
}
+11
View File
@@ -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');
+44 -3
View File
@@ -9,6 +9,9 @@
module.exports = class BaseModel extends Backbone.Model module.exports = class BaseModel extends Backbone.Model
@_loadingQueue = []
@_isDraining = false
constructor: (attributes={}, options={})-> constructor: (attributes={}, options={})->
options.logEvents ?= true options.logEvents ?= true
super attributes, options super attributes, options
@@ -19,11 +22,11 @@ module.exports = class BaseModel extends Backbone.Model
continue if name is 'id' continue if name is 'id'
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name) Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
@fileCache = options.fileCache or null
@loading = null
@logEvents = options.logEvents or false @logEvents = options.logEvents or false
@state = c.modelState.unloaded @state = c.modelState.unloaded
@loading = null
Object.defineProperties this, Object.defineProperties this,
isUnloaded: { get:-> @state is c.modelState.unloaded } isUnloaded: { get:-> @state is c.modelState.unloaded }
isLoading: { get:-> @state is c.modelState.loading } isLoading: { get:-> @state is c.modelState.loading }
@@ -60,13 +63,24 @@ module.exports = class BaseModel extends Backbone.Model
@state = c.modelState.loading @state = c.modelState.loading
@trigger c.event.request, this @trigger c.event.request, this
@loading = w.promise (resolve, reject)=>
loadFromServer = =>
w.promise (resolve, reject)=>
$.ajax $.ajax
url: url url: url
dataType: 'text' dataType: 'text'
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
error: (xhr, status, error)=> reject @onLoadFailed error, 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 @loading.catch (e)-> # do nothing
return @loading return @loading
@@ -86,3 +100,30 @@ module.exports = class BaseModel extends Backbone.Model
toString: -> toString: ->
return "#{@constructor.name}.#{@cid}" 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 = {} @_rawScores = {}
@_scores = {} @_scores = {}
@_steps = steps @_steps = steps
@_tools = null
@_want = want @_want = want
@_numberSteps() @_numberSteps()
@@ -37,19 +38,32 @@ module.exports = class CraftingPlan
@_made = new SimpleInventory modPack:@_modPack @_made = new SimpleInventory modPack:@_modPack
@_made.addInventory @_have @_made.addInventory @_have
@_tools = new SimpleInventory modPack:@_modPack
for i in [@_steps.length-1..0] by -1 for i in [@_steps.length-1..0] by -1
step = @_steps[i] step = @_steps[i]
step.multiplier = 0 step.multiplier = 0
recipe = step.recipe
for stack in step.recipe.output for stack in step.recipe.output
if not stack? continue if recipe.isPassThroughFor stack.itemSlug
throw new Error 'stack should not be null here'
qualifiedSlug = @_modPack.qualifySlug stack.itemSlug qualifiedSlug = @_modPack.qualifySlug stack.itemSlug
while @_need.quantityOf(qualifiedSlug) > 0 while @_need.quantityOf(qualifiedSlug) > 0
@_executeStep step @_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 @_want
@_made.addInventory @_tools
@_pruneEmptySteps() @_pruneEmptySteps()
@_numberSteps() @_numberSteps()
@@ -63,6 +63,22 @@ describe 'crafting_plan.coffee', ->
'1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot' '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', -> it 'can compute multiple items with multiple plans', ->
plans = fixtures.makePlans [1, 'test__copper_block'], [1, 'test__iron_sword'] plans = fixtures.makePlans [1, 'test__copper_block'], [1, 'test__iron_sword']
plans.length.should.equal 4 plans.length.should.equal 4
@@ -27,10 +27,11 @@ module.exports = class CraftingStep
addToolsTo: (targetInventory)-> addToolsTo: (targetInventory)->
for stack in @_recipe.tools for stack in @_recipe.tools
targetInventory.add stack.itemSlug, stack.quantity targetInventory.add stack.itemSlug, stack.quantity, insert:true
completeInto: (targetInventory)-> completeInto: (targetInventory)->
for stack in @_recipe.output for stack in @_recipe.output
continue if @_recipe.isPassThroughFor stack.itemSlug
quantity = @_recipe.getQuantityProduced stack.itemSlug quantity = @_recipe.getQuantityProduced stack.itemSlug
targetInventory.add stack.itemSlug, quantity * @_multiplier targetInventory.add stack.itemSlug, quantity * @_multiplier
@@ -67,4 +68,6 @@ module.exports = class CraftingStep
@_inventory = new SimpleInventory @_inventory = new SimpleInventory
for stack in @_recipe.input for stack in @_recipe.input
qualifiedSlug = @_modPack.qualifySlug stack.itemSlug 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
+20 -23
View File
@@ -22,57 +22,43 @@ module.exports = class Craftsman extends BaseModel
@::PLAN_STEP_INCREMENT = 39 @::PLAN_STEP_INCREMENT = 39
@::STAGE = @::STAGE =
WAITING: 'waiting' EMPTY: 'empty'
READY: 'ready'
GRAPHING: 'examining recipes' GRAPHING: 'examining recipes'
PLANNING: 'computing plans' PLANNING: 'computing plans'
ANALYZING: 'analyzing plans' ANALYZING: 'analyzing plans'
COMPLETE: 'complete' COMPLETE: 'complete'
INVALID: 'invalid' INVALID: 'invalid'
OUTDATED: 'outdated'
constructor: (modPack)-> constructor: (modPack)->
if not modPack? then throw new Error 'modPack is required' if not modPack? then throw new Error 'modPack is required'
attributes = attributes =
paused: false stage: @STAGE.READY
stage: @STAGE.WAITING
stageCount: 0 stageCount: 0
super attributes, {} super attributes, {}
@_modPack = modPack @_modPack = modPack
reset = _.debounce (=> @reset()), 100
reevaluatePlans = _.debounce (=> @reevaluatePlans()), 100
@_have = new Inventory modPack:@_modPack @_have = new Inventory modPack:@_modPack
@_have.on c.event.change, reevaluatePlans @_have.on c.event.change, => @_resetStage()
@_want = new Inventory modPack:@_modPack @_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 c.event.change + ':stage', => logger.info "Craftsman has started #{@stage}..."
@on 'scheduleNextWork', => @_scheduleNextWork() @on 'scheduleNextWork', => @_scheduleNextWork()
@reset() @reset()
# Public Methods ############################################################################### # Public Methods ###############################################################################
reevaluatePlans: ->
@_plans = null
@_planEvaluator = null
@stage = @STAGE.WAITING
@stageCount = 0
@_scheduleNextWork()
reset: -> reset: ->
@_graphBuilder = null @_graphBuilder = null
@_planBuilder = null @_planBuilder = null
@_planEvaluator = null @_planEvaluator = null
@_plans = null @_plans = null
@stage = @STAGE.WAITING @_resetStage()
@stageCount = 0
@_scheduleNextWork()
work: -> work: ->
return if @_want.isEmpty return if @_want.isEmpty
@@ -130,7 +116,7 @@ module.exports = class Craftsman extends BaseModel
Object.defineProperties @prototype, Object.defineProperties @prototype,
complete: complete:
get: -> @stage in [@STAGE.COMPLETE, @STAGE.INVALID] get: -> @stage in [@STAGE.COMPLETE, @STAGE.INVALID, @STAGE.OUTDATED]
have: have:
get: -> @_have get: -> @_have
@@ -143,8 +129,19 @@ module.exports = class Craftsman extends BaseModel
# Private Methods ############################################################################## # 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: -> _scheduleNextWork: ->
return if @paused
return if @want.isEmpty return if @want.isEmpty
return if @complete return if @complete
@@ -98,6 +98,12 @@ MOD_VERSION_FILE =
input: Stick, Cobblestone input: Stick, Cobblestone
pattern: .0. .1. ... pattern: .0. .1. ...
item: Maul
recipe:
input: Iron Ingot, Stick
pattern: 001 001 ..1
tools: Crafting Table
item: Oak Planks item: Oak Planks
recipe: recipe:
input: Oak Wood input: Oak Wood
@@ -107,12 +113,29 @@ MOD_VERSION_FILE =
item: Oak Wood item: Oak Wood
gatherable: yes gatherable: yes
item: Spruce Wood
gatherable: yes
item: Stick item: Stick
recipe: recipe:
input: Oak Planks input: Oak Planks
pattern: .0. .0. ... pattern: .0. .0. ...
quantity: 4 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 item: String
gatherable: yes gatherable: yes
@@ -44,7 +44,7 @@ module.exports = class SimpleInventory
@_itemSlugs = [] @_itemSlugs = []
clone: -> clone: ->
inventory = new Inventory inventory = new SimpleInventory
inventory.addInventory this inventory.addInventory this
return inventory return inventory
@@ -79,7 +79,7 @@ module.exports = class SimpleInventory
if qualifiedSlug? if qualifiedSlug?
newSlugs.push qualifiedSlug newSlugs.push qualifiedSlug
newStacks.push new Stack itemSlug:qualifiedSlug, quantity:stack.quantity newStacks.push new SimpleStack itemSlug:qualifiedSlug, quantity:stack.quantity
else else
newSlugs.push itemSlug newSlugs.push itemSlug
newStacks.push stack newStacks.push stack
@@ -130,9 +130,9 @@ module.exports = class SimpleInventory
parse: (data)-> parse: (data)->
return this if not data? or data.length is 0 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 for stackText in stacks
stackParts = stackText.split Inventory.Delimiters.Item stackParts = stackText.split SimpleInventory.Delimiters.Item
if stackParts.length is 2 if stackParts.length is 2
quantity = parseInt stackParts[0], 10 quantity = parseInt stackParts[0], 10
itemSlug = ItemSlug.slugify stackParts[1] itemSlug = ItemSlug.slugify stackParts[1]
+3 -3
View File
@@ -1,9 +1,9 @@
### #
# Crafting Guide - event_recorder.coffee # Crafting Guide - event_recorder.coffee
# #
# Copyright (c) 2014-2015 by Redwood Labs # Copyright © 2014-2016 by Redwood Labs
# All rights reserved. # All rights reserved.
### #
util = require 'util' util = require 'util'
+19 -3
View File
@@ -29,10 +29,10 @@ module.exports = class Inventory extends BaseModel
# Public Methods ############################################################################### # Public Methods ###############################################################################
add: (itemSlug, quantity=1)-> add: (itemSlug, quantity=1, options={})->
return this unless quantity > 0 return this unless quantity > 0
@_add itemSlug, quantity @_add itemSlug, quantity, options
@trigger c.event.add, this, itemSlug, quantity @trigger c.event.add, this, itemSlug, quantity
@trigger c.event.change, this @trigger c.event.change, this
return this return this
@@ -141,6 +141,18 @@ module.exports = class Inventory extends BaseModel
@trigger c.event.change, this @trigger c.event.change, this
return 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 ############################################################################## # Parsing Methods ##############################################################################
parse: (data)-> parse: (data)->
@@ -209,7 +221,8 @@ module.exports = class Inventory extends BaseModel
# Private Methods ############################################################################## # Private Methods ##############################################################################
_add: (itemSlug, quantity=1)-> _add: (itemSlug, quantity=1, options={})->
options.insert ?= false
return unless itemSlug? return unless itemSlug?
return unless quantity > 0 return unless quantity > 0
@@ -218,6 +231,9 @@ module.exports = class Inventory extends BaseModel
stack = new Stack itemSlug:itemSlug, quantity:quantity stack = new Stack itemSlug:itemSlug, quantity:quantity
@listenTo stack, c.event.change, => @trigger c.event.change, this @listenTo stack, c.event.change, => @trigger c.event.change, this
@_stacks[itemSlug] = stack @_stacks[itemSlug] = stack
if options.insert
@_itemSlugs.unshift itemSlug
else
@_itemSlugs.push itemSlug @_itemSlugs.push itemSlug
@_sort() @_sort()
else else
+12 -2
View File
@@ -29,8 +29,6 @@ module.exports = class Mod extends BaseModel
@_modVersions = [] @_modVersions = []
@_tutorials = [] @_tutorials = []
@once c.event.sync, => @_verifyActiveModVersion()
# Class Methods ################################################################################## # Class Methods ##################################################################################
@Version: Version = @Version: Version =
@@ -95,6 +93,12 @@ module.exports = class Mod extends BaseModel
# Item Methods ################################################################################# # Item Methods #################################################################################
chooseRandomItem: ->
effectiveModVersion = @_activeModVersion or @getModVersion Mod.Version.Latest
return null unless effectiveModVersion?
return effectiveModVersion.chooseRandomItem()
eachItem: (callback)-> eachItem: (callback)->
effectiveModVersion = @_activeModVersion or @getModVersion Mod.Version.Latest effectiveModVersion = @_activeModVersion or @getModVersion Mod.Version.Latest
effectiveModVersion.eachItem callback effectiveModVersion.eachItem callback
@@ -129,6 +133,7 @@ module.exports = class Mod extends BaseModel
@_modVersions.push modVersion @_modVersions.push modVersion
@listenTo modVersion, c.event.change, => @trigger c.event.change, this @listenTo modVersion, c.event.change, => @trigger c.event.change, this
modVersion.fileCache = this.fileCache
modVersion.mod = this modVersion.mod = this
@trigger c.event.add + ':modVersion', modVersion, this @trigger c.event.add + ':modVersion', modVersion, this
@@ -143,6 +148,9 @@ module.exports = class Mod extends BaseModel
for modVersion in @_modVersions for modVersion in @_modVersions
callback modVersion callback modVersion
getAllModVersions: ->
return @_modVersions[..]
getModVersion: (version)-> getModVersion: (version)->
return null if version is Mod.Version.None return null if version is Mod.Version.None
return @_modVersions[0] if version is Mod.Version.Latest 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 ?= new ModParser model:this
@_parser.parse text @_parser.parse text
@_verifyActiveModVersion()
return null # prevent calling `set` return null # prevent calling `set`
url: -> url: ->
+20 -7
View File
@@ -6,9 +6,10 @@
# #
BaseModel = require '../base_model' BaseModel = require '../base_model'
Inventory = require './inventory' Mod = require './mod'
ModVersionParser = require '../parsing/mod_version_parser' ModVersionParser = require '../parsing/mod_version_parser'
Recipe = require './recipe' Recipe = require './recipe'
SimpleInventory = require '../crafting/simple_inventory'
######################################################################################################################## ########################################################################################################################
@@ -24,6 +25,12 @@ module.exports = class ModPack extends BaseModel
# Item Methods ################################################################################# # Item Methods #################################################################################
chooseRandomItem: ->
return null unless @_mods.length > 0
modIndex = Math.floor Math.random() * @_mods.length
return @_mods[modIndex].chooseRandomItem()
findItem: (itemSlug, options={})-> findItem: (itemSlug, options={})->
options.includeDisabled ?= false options.includeDisabled ?= false
@@ -75,7 +82,7 @@ module.exports = class ModPack extends BaseModel
result.modSlug = @_mods[0].slug result.modSlug = @_mods[0].slug
result.modVersion = @_mods[0].activeVersion result.modVersion = @_mods[0].activeVersion
craftingUrlInventory = new Inventory modPack:this craftingUrlInventory = new SimpleInventory modPack:this
if item?.multiblock? if item?.multiblock?
craftingUrlInventory.addInventory item.multiblock.inventory craftingUrlInventory.addInventory item.multiblock.inventory
else else
@@ -165,12 +172,18 @@ module.exports = class ModPack extends BaseModel
# Private Methods ############################################################################## # Private Methods ##############################################################################
_onModVersionLoaded: (modVersion)-> _onModVersionLoaded: (modVersion)->
working = true mods = @getAllMods()
@eachMod (mod)-> return true unless mods.length > 0
mod.eachModVersion (modVersion)->
working = working and (modVersion.isUnloaded or modVersion.isLoading)
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.change, this
@trigger c.event.sync, this @trigger c.event.sync, this
@@ -59,6 +59,10 @@ module.exports = class ModVersion extends BaseModel
return null if result.length is 0 return null if result.length is 0
return result return result
chooseRandomItem: ->
itemIndex = Math.floor Math.random() * @_slugs.length
return @_slugs[itemIndex]
eachItem: (callback)-> eachItem: (callback)->
for slug in @_slugs for slug in @_slugs
item = @findItem slug item = @findItem slug
+7 -12
View File
@@ -103,7 +103,7 @@ module.exports = class Recipe extends BaseModel
if modPack?.findItemByName(@condition.noun)? if modPack?.findItemByName(@condition.noun)?
result = true result = true
else if @condition.verb is 'mod' else if @condition.verb is 'mod'
modPack.eachMod (mod)-> modPack.eachMod (mod)=>
if mod.name is @condition.noun if mod.name is @condition.noun
result = true result = true
@@ -111,16 +111,7 @@ module.exports = class Recipe extends BaseModel
return result return result
isPassThroughFor: (itemSlug)-> isPassThroughFor: (itemSlug)->
amountCreated = 0 return @getQuantityProduced(itemSlug) is @getQuantityRequired(itemSlug)
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
produces: (itemSlug)-> produces: (itemSlug)->
if not @_produces? if not @_produces?
@@ -221,7 +212,11 @@ module.exports = class Recipe extends BaseModel
_computeQuantities: (pattern)-> _computeQuantities: (pattern)->
quantityMap = {} 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 '.'
continue if c is ' ' continue if c is ' '
+1
View File
@@ -40,6 +40,7 @@ module.exports = class CraftPage extends BaseModel
inventory.each (stack)=> inventory.each (stack)=>
item = @modPack.findItem stack.itemSlug, enableAsNeeded:true item = @modPack.findItem stack.itemSlug, enableAsNeeded:true
return unless item? and item.isCraftable return unless item? and item.isCraftable
@craftsman.want.add stack.itemSlug, stack.quantity @craftsman.want.add stack.itemSlug, stack.quantity
inventory.remove stack.itemSlug inventory.remove stack.itemSlug
+86
View File
@@ -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'
+1
View File
@@ -47,6 +47,7 @@ module.exports = class ItemPage extends BaseModel
mod.eachRecipe (recipe)=> mod.eachRecipe (recipe)=>
if isAcceptable recipe if isAcceptable recipe
for outputStack in recipe.output for outputStack in recipe.output
continue if recipe.isPassThroughFor outputStack.itemSlug
outputItem = @modPack.findItem outputStack.itemSlug, includeDisabled:true outputItem = @modPack.findItem outputStack.itemSlug, includeDisabled:true
result[outputItem.slug] = outputItem result[outputItem.slug] = outputItem
@@ -7,7 +7,6 @@
.content.view__browse_page .content.view__browse_page
.left .left
.view__adsense
.right .right
.tile_container .tile_container
+20 -2
View File
@@ -12,12 +12,30 @@
.tile_container { .tile_container {
display : flex; display : flex;
flex-wrap : wrap; flex-wrap : wrap;
justify-content : space-between;
.view__mod_tile { .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; 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. # All rights reserved.
# #
AdsenseController = require '../common/adsense/adsense_controller'
ModTileController = require './mod_tile/mod_tile_controller' ModTileController = require './mod_tile/mod_tile_controller'
PageController = require '../page_controller' PageController = require '../page_controller'
@@ -32,8 +31,6 @@ module.exports = class BrowsePageController extends PageController
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
@$tileContainer = @$('.tile_container') @$tileContainer = @$('.tile_container')
refresh: -> refresh: ->
@@ -8,14 +8,12 @@
.view__mod_tile { .view__mod_tile {
min-width : $size-minecraft-block * 9; min-width : $size-minecraft-block * 9;
display : flex; display: flex;
justify-content : stretch;
align-items : stretch;
a { a {
max-width: 100%;
@include floating-panel; @include floating-panel;
flex: 1 1 auto;
border : $size-border-medium solid $color-background-panel; border : $size-border-medium solid $color-background-panel;
color : $color-text; color : $color-text;
text-decoration : none; text-decoration : none;
@@ -39,6 +37,7 @@
overflow : hidden; overflow : hidden;
.title { .title {
max-width: 0;
margin-bottom : $size-margin-medium; margin-bottom : $size-margin-medium;
font-family : $font-family-header; 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 module.exports = class ModTileController extends BaseController
constructor: (options={})-> constructor: (options={})->
options.tagName = 'section'
options.templateName = 'browse_page/mod_tile' options.templateName = 'browse_page/mod_tile'
super options super options
+54 -10
View File
@@ -6,20 +6,64 @@
// //
.view__adsense { .view__adsense {
.skyscraper { left : 50%;
height : $size-skyscraper-height;
width : $size-skyscraper-width;
position : relative;
border : 0.1em solid $color-gray-faint;
margin : $size-margin-large 0; margin : $size-margin-large 0;
position : relative;
&:first-child { transform : translate(-50%);
margin-top : 0;
}
ins { ins {
position: absolute; top: 0; right: 0; bottom: 0; left: 0; 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;
}
}
&.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. # All rights reserved.
# #
BaseController = require '../../base_controller'
######################################################################################################################## ########################################################################################################################
module.exports = class AdsenseController extends BaseController module.exports = class AdsenseController
constructor: (options={})->
options.templateName = 'common/adsense'
super options
constructor: ->
@_adsEnabled = global.env in c.productionEnvs @_adsEnabled = global.env in c.productionEnvs
@_adCount = 0 @_adsPlaced = 0
@_waiting = false @_waiting = false
# Public Methods ############################################################################### # Public Methods ###############################################################################
fillAdPositions: -> fillAdPositions: ->
if @_adCount > 0 adType = @_computeAdType()
return unless @$sidebar and @$mainBody maxAds = c.adsense[adType].slotIds.length - @_adsPlaced
return unless @_adCount < @_computeMaxAds() return if maxAds is 0
return unless @_adCount < c.adsense.slotIds.length
$adContainer = $('<div class="skyscraper"></div>') logger.verbose => "Looking to place #{maxAds} more #{adType} ads..."
@$el.append $adContainer
if adType is 'skyscraper'
placedNewAd = @_createSkyscraperPositions()
else
placedNewAd = @_createBannerPositions adType
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"
reset: ->
@_adsPlaced = 0
@_waitForPageReadiness()
# Private Methods #############################################################################
_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
_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 if @_adsEnabled
$ad = $('<ins class="adsbygoogle"></ins>') $ad = $('<ins class="adsbygoogle"></ins>')
$ad.attr 'data-ad-client', c.adsense.clientId $ad.attr 'data-ad-client', c.adsense.clientId
$ad.attr 'data-ad-slot', c.adsense.slotIds[@_adCount] $ad.attr 'data-ad-slot', c.adsense.skyscraper.slotIds[@_adsPlaced]
$adContainer.append $ad $el.append $ad
@_loadAds() else
$el.addClass 'placeholder'
@_adCount += 1 $sidebar.append $el
_.defer => @fillAdPositions() placedNewAd = true
@_adsPlaced += 1
remaining -= 1
logger.info => "Placed skyscraper ad ##{@_adsPlaced}"
@_loadAd()
# BaseController Overrides ##################################################################### return placedNewAd
onDidRender: -> _createBannerPositions: (adType)->
@$mainBody = $('.page > .content > .right') $pageContent = $('.page > .content > .right')
@$sidebar = $('.page > .content > .left') remaining = @_computeAdCount adType
super remaining -= @_adsPlaced
sectionIndex = 0
placedNewAd = false
refresh: -> for sectionEl in $pageContent.find('section')
@_waitForPageReadiness() break unless remaining > 0
super
# Private Methods ############################################################################# $section = $(sectionEl)
continue unless $section.is ':visible'
_computeMaxAds: -> sectionIndex += 1
return null unless @$sidebar continue if sectionIndex % 2 is 0
result = Math.floor @$sidebar.height() / (c.adsense.skyscraper.height + c.adsense.skyscraper.margin) continue if $section.next().hasClass 'view__adsense'
return result
_loadAds: -> $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 return unless @_adsEnabled
logger.info "Loading #{@_adCount} Google AdSense ads" logger.info "Loading Google AdSense ads"
try try
global.adsbygoogle ||= [] global.adsbygoogle ||= []
global.adsbygoogle.push {} global.adsbygoogle.push {}
@@ -70,11 +139,12 @@ module.exports = class AdsenseController extends BaseController
_waitForPageReadiness: -> _waitForPageReadiness: ->
return if @_waiting 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" logger.verbose "Adsense is waiting for room to insert ads"
@_waiting = true @_waiting = true
_.delay (=> @_waiting = false; @_waitForPageReadiness()), c.duration.normal _.delay (=> @_waiting = false; @_waitForPageReadiness()), c.adsense.readinessCheckInterval
else else
logger.verbose "Adsense is ready to fill ads" logger.verbose "Adsense is ready to fill ads"
@fillAdPositions() @fillAdPositions()
@@ -9,5 +9,5 @@
.item_container .item_container
.empty_placeholder nothing .empty_placeholder nothing
.buttons .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 .button.clear: .bezel: p clear
@@ -38,12 +38,24 @@
margin-top: $size-margin-large; margin-top: $size-margin-large;
.item-selector { .item-selector {
flex : 85%; flex : 80%;
margin-right : $size-margin-medium; margin-right : $size-margin-medium;
@include screen-size(mobile) {
flex: 50%;
.full {
display: none;
}
}
} }
.clear { .clear {
flex : 15%; flex : 20%;
@include screen-size(mobile) {
flex: 50%;
}
} }
} }
} }
@@ -61,8 +73,12 @@
.quantity { .quantity {
padding-right : $size-margin-medium; padding-right : $size-margin-medium;
input { input {
width: 3em; width : 3em;
font-size : $font-size-xlarge; 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; overflow: visible;
display: flex; display: flex;
align-items: center; align-items: flex-start;
img { img {
height: $size-minecraft-block; height: $size-minecraft-block;
@@ -22,9 +22,19 @@
font-family: $font-family-text; font-family: $font-family-text;
font-size: $font-size-medium; font-size: $font-size-medium;
line-height: $size-minecraft-block; line-height: $size-minecraft-block;
overflow-x: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
} }
} }
@include screen-size(mobile) {
.view__item_tile {
a {
p {
white-space: normal;
}
}
}
}
@@ -48,7 +48,6 @@
} }
&.selected { &.selected {
flex : 0 0 auto;
background : $color-active-hover; background : $color-active-hover;
.name { .name {
@@ -9,6 +9,6 @@
.view__item_selector_popup .view__item_selector_popup
.search .search
img(src='/images/search.png') 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') img.close(src='/images/close.png')
.results .results
@@ -9,6 +9,7 @@
} }
.view__item_selector_popup { .view__item_selector_popup {
max-width: $size-minecraft-block * 20;
height : 66%; height : 66%;
background : $color-background-panel; background : $color-background-panel;
@@ -35,6 +36,7 @@
input { input {
flex: 1 1 100%; flex: 1 1 100%;
min-width: $font-size-large * 10;
background: none; background: none;
border: 0; border: 0;
@@ -50,8 +52,15 @@
.results { .results {
flex: 1 1 100%; flex: 1 1 100%;
position: relative;
overflow-x: hidden; overflow-x: hidden;
overflow-y: scroll; 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 when c.key.enter
@_chooseSelected() @_chooseSelected()
return false return false
when c.key.down when c.key.downArrow
@_selectNext() @_selectNext()
return false return false
when c.key.up when c.key.upArrow
@_selectPrevious() @_selectPrevious()
return false return false
@@ -82,6 +82,7 @@ module.exports = class ItemSelectorController extends BaseController
@model.hint = @$hintField.val() @model.hint = @$hintField.val()
@tryRefresh() @tryRefresh()
@onResultSelected @_elementControllers[0] @onResultSelected @_elementControllers[0]
return false
onPopupClicked: (event)-> onPopupClicked: (event)->
return false return false
@@ -90,6 +91,7 @@ module.exports = class ItemSelectorController extends BaseController
@_session.resolve controller.model.slug @_session.resolve controller.model.slug
@_session = null @_session = null
@_close() @_close()
return false
onResultSelected: (controller)-> onResultSelected: (controller)->
for c in @_elementControllers for c in @_elementControllers
@@ -98,6 +100,8 @@ module.exports = class ItemSelectorController extends BaseController
if controller? if controller?
controller.selected = true controller.selected = true
return false
onScreenClicked: (event)-> onScreenClicked: (event)->
@_close() @_close()
return false return false
@@ -169,6 +173,8 @@ module.exports = class ItemSelectorController extends BaseController
@_elementControllers.pop().remove() @_elementControllers.pop().remove()
_selectNext: -> _selectNext: ->
return unless @_elementControllers.length > 0
for i in [0...(@_elementControllers.length - 1)] by 1 for i in [0...(@_elementControllers.length - 1)] by 1
controller = @_elementControllers[i] controller = @_elementControllers[i]
nextController = @_elementControllers[i + 1] nextController = @_elementControllers[i + 1]
@@ -179,7 +185,13 @@ module.exports = class ItemSelectorController extends BaseController
@_showElement nextController.$el @_showElement nextController.$el
return return
controller = @_elementControllers[0]
controller.selected = true
@_showElement controller.$el
_selectPrevious: -> _selectPrevious: ->
return unless @_elementControllers.length > 0
for i in [1...@_elementControllers.length] by 1 for i in [1...@_elementControllers.length] by 1
previousController = @_elementControllers[i - 1] previousController = @_elementControllers[i - 1]
controller = @_elementControllers[i] controller = @_elementControllers[i]
@@ -190,6 +202,10 @@ module.exports = class ItemSelectorController extends BaseController
@_showElement previousController.$el @_showElement previousController.$el
return return
controller = @_elementControllers[@_elementControllers.length - 1]
controller.selected = true
@_showElement controller.$el
_showElement: ($el)-> _showElement: ($el)->
top = $el.position().top + @$resultsContainer.scrollTop() 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 ################################################################################ # Event Methods ################################################################################
onCancelClicked: (event)-> onCancelClicked: (event)->
event.preventDefault()
@model = @_originalModel @model = @_originalModel
@resetToDefaultState() @resetToDefaultState()
@_imageListController.reset() @_imageListController.reset()
@_updatePreview() @_updatePreview()
return false
onEditClicked: (event)-> onEditClicked: (event)->
event.preventDefault() return false unless @editable
return unless @editable
@_originalModel = @model @_originalModel = @model
@state = @State.waiting @state = @State.waiting
@@ -81,22 +80,22 @@ module.exports = class MarkdownSectionController extends BaseController
@state = @State.appologizing @state = @State.appologizing
w(true).delay(@_confirmDuration).then => @resetToDefaultState() w(true).delay(@_confirmDuration).then => @resetToDefaultState()
return false
onQuestionClicked: (event)-> onQuestionClicked: (event)->
event.preventDefault()
@_enterFeedback '' @_enterFeedback ''
return false
onPreviewClicked: (event)-> onPreviewClicked: (event)->
event.preventDefault()
@_updatePreview() @_updatePreview()
@state = @State.previewing @state = @State.previewing
return false
onReturnClicked: (event)-> onReturnClicked: (event)->
event.preventDefault()
@state = @State.editing @state = @State.editing
return false
onSaveClicked: (event)-> onSaveClicked: (event)->
event.preventDefault()
@state = @State.waiting @state = @State.waiting
@_endEditing() @_endEditing()
.then => .then =>
@@ -109,9 +108,11 @@ module.exports = class MarkdownSectionController extends BaseController
.then => .then =>
@state = @State.viewing @state = @State.viewing
return false
onTextChanged: (event)-> onTextChanged: (event)->
event.preventDefault()
@model = @$textarea.val() @model = @$textarea.val()
return false
# Property Methods ############################################################################# # Property Methods #############################################################################
+6 -2
View File
@@ -9,12 +9,16 @@
display: flex; display: flex;
.input { .input {
flex: 1 1 50%; flex: 0 0 auto;
align-items : center; align-items : center;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
.view__crafting_grid {
flex: 0 0 auto;
}
.tool { .tool {
margin-top : $size-margin-small; margin-top : $size-margin-small;
@@ -24,7 +28,7 @@
} }
.output { .output {
flex: 1 1 50%; flex: 1 1 100%;
margin-left: $size-margin-medium; margin-left: $size-margin-medium;
display : flex; display : flex;
+3 -1
View File
@@ -6,7 +6,9 @@
//- //-
.view__stack .view__stack
.quantity: input .quantity
input
.hover
.icon: img(src='') .icon: img(src='')
.name: a .name: a
.action.first(style="display: none") .action.first(style="display: none")
+43
View File
@@ -21,6 +21,7 @@
.quantity { .quantity {
padding-right : $size-margin-medium; padding-right : $size-margin-medium;
position : relative;
text-align : right; text-align : right;
input { input {
@@ -32,6 +33,38 @@
font-size : $font-size-large; font-size : $font-size-large;
text-align : right; 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 { .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 module.exports = class StackController extends BaseController
@::MAX_QUANTITY = 9999 @::MAX_QUANTITY = 9999
@::STACK_SIZE = 64
constructor: (options={})-> constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required' 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') @$image = @$('.icon img')
@$nameLink = @$('.name a') @$nameLink = @$('.name a')
@$quantityField = @$('.quantity input') @$quantityField = @$('.quantity input')
@$quantityHover = @$('.quantity .hover')
@$secondAction = @$('.action.second') @$secondAction = @$('.action.second')
@$secondButton = @$('.action.second .button') @$secondButton = @$('.action.second .button')
super super
@@ -124,6 +126,7 @@ module.exports = class StackController extends BaseController
@$quantityField.val quantityText @$quantityField.val quantityText
@_refreshButtons() @_refreshButtons()
@_refreshHover()
if @_editable if @_editable
@$el.addClass 'editable' @$el.addClass 'editable'
@@ -169,6 +172,20 @@ module.exports = class StackController extends BaseController
when 'remove' then $label.text '-' when 'remove' then $label.text '-'
when 'up' 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)-> _updateButtonType: ($button, type)->
for currentType in ['check', 'down', 'remove', 'up'] for currentType in ['check', 'down', 'remove', 'up']
$button.removeClass currentType $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;
}
}
}
}
+1 -1
View File
@@ -6,5 +6,5 @@
//- //-
.view__video .view__video
iframe(width="356", height="267", src="", frameborder="0", allowfullscreen="true") iframe(src="", frameborder="0", allowfullscreen="true")
.caption: p .caption: p
+4
View File
@@ -11,6 +11,10 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
iframe {
max-width: 100%;
}
.caption { .caption {
margin-top: $size-margin-small; margin-top: $size-margin-small;
+9 -17
View File
@@ -5,16 +5,8 @@
//- All rights reserved. //- 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 .content.view__craft_page
.left .left
.view__adsense
.right .right
section.instructions section.instructions
@@ -26,19 +18,19 @@
p. p.
Not sure what you'd like to make? Try one of these: Not sure what you'd like to make? Try one of these:
.items .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") 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") 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") 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") 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") 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") 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") img(src="/data/thermal_expansion/items/tesseract/icon.png")
section.want section.want
@@ -51,8 +43,6 @@
.panel .panel
.view__inventory.large.editable .view__inventory.large.editable
section.view__craftsman_working
section.need section.need
h2 Need to Gather h2 Need to Gather
.panel .panel
@@ -61,3 +51,5 @@
section.steps section.steps
h2 Steps h2 Steps
.panel .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. # All rights reserved.
# #
AdsenseController = require '../common/adsense/adsense_controller'
BaseController = require '../base_controller' BaseController = require '../base_controller'
CraftPage = require '../../models/site/craft_page' CraftPage = require '../../models/site/craft_page'
Craftsman = require '../../models/crafting/craftsman' Craftsman = require '../../models/crafting/craftsman'
CraftsmanWorkingController = require './craftsman_working/craftsman_working_controller' CraftsmanWorkingController = require './craftsman_working/craftsman_working_controller'
InventoryController = require '../common/inventory/inventory_controller' InventoryController = require '../common/inventory/inventory_controller'
PageController = require '../page_controller' PageController = require '../page_controller'
SimpleInventory = require '../../models/crafting/simple_inventory'
StepController = require './step/step_controller' StepController = require './step/step_controller'
######################################################################################################################## ########################################################################################################################
module.exports = class CraftPageController extends PageController module.exports = class CraftPageController extends PageController
@::SCROLL_BUFFER = 8 # px
constructor: (options={})-> constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required' if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.modPack? then throw new Error 'options.modPack 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 @_router = options.router
@_storage = options.storage @_storage = options.storage
# c.event Methods ################################################################################ # Event Methods ################################################################################
onHaveInventoryChanged: -> onHaveInventoryChanged: ->
logger.warning => "storing have: #{@model.craftsman.have.unparse()}"
@_storage.store 'crafting-plan:have', @model.craftsman.have.unparse() @_storage.store 'crafting-plan:have', @model.craftsman.have.unparse()
onMoveNeedToHave: (itemSlug)-> onMoveNeedToHave: (itemSlug)->
@@ -50,27 +51,39 @@ module.exports = class CraftPageController extends PageController
@model.craftsman.want.remove itemSlug @model.craftsman.want.remove itemSlug
@onWantInventoryChanged() @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: -> onWantInventoryChanged: ->
text = @model.craftsman.want.unparse() text = @model.craftsman.want.unparse()
url = c.url.crafting inventoryText:text url = c.url.crafting inventoryText:text
@router.navigate url @router.navigate url
if @model.craftsman.want.isEmpty
@model.craftsman.have.clear()
# PageController Overrides ##################################################################### # PageController Overrides #####################################################################
getMetaDescription: -> getMetaDescription: ->
return c.text.craftDescription() return c.text.craftDescription()
getTitle: -> getTitle: ->
return 'Craft' description = @model.craftsman.want.toDescription()
return null unless description?
return "Crafting Plan for #{description}"
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
@_wantInventoryController = @addChild InventoryController, '.want .view__inventory', @_wantInventoryController = @addChild InventoryController, '.want .view__inventory',
firstButtonType: 'remove' firstButtonType: 'remove'
imageLoader: @_imageLoader imageLoader: @_imageLoader
@@ -89,7 +102,6 @@ module.exports = class CraftPageController extends PageController
router: @_router router: @_router
@_haveInventoryController.on c.event.button.first, (controller, itemSlug)=> @_haveInventoryController.on c.event.button.first, (controller, itemSlug)=>
@onRemoveFromHaveInventory itemSlug @onRemoveFromHaveInventory itemSlug
@_haveInventoryController.on c.event.change, (c)=> @onHaveInventoryChanged()
@_needInventoryController = @addChild InventoryController, '.need .view__inventory', @_needInventoryController = @addChild InventoryController, '.need .view__inventory',
editable: false editable: false
@@ -102,6 +114,7 @@ module.exports = class CraftPageController extends PageController
@_workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working', @_workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working',
model: @model.craftsman model: @model.craftsman
@_workingSectionController.on c.event.click, => @_scrollTo @$workingSection
@$haveSection = @$('section.have') @$haveSection = @$('section.have')
@$instructionsSection = @$('section.instructions') @$instructionsSection = @$('section.instructions')
@@ -112,25 +125,37 @@ module.exports = class CraftPageController extends PageController
@$toolsSection = @$('section.tools') @$toolsSection = @$('section.tools')
@$workingSection = @$('.view__craftsman_working') @$workingSection = @$('.view__craftsman_working')
if c.screen.type.compute() is c.screen.type.mobile
@$('.view__inventory.large').removeClass 'large'
super super
onWillRender: -> onWillRender: ->
@model.craftsman.have.clear() @model.craftsman.have.clear()
@model.craftsman.have.parse @_storage.load('crafting-plan:have') @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 super
refresh: -> refresh: ->
@_needInventoryController.model = @model.craftsman.plan?.need @_needInventoryController.model = @model.craftsman.plan?.need
@_refreshOutdated()
@_refreshSectionVisibility() @_refreshSectionVisibility()
@_refreshSteps() @_refreshSteps()
@_adsenseController.fillAdPositions()
super super
# Backbone.View Overrides ######################################################################## # Backbone.View Overrides ########################################################################
events: -> events: ->
return _.extend super, return _.extend super,
'click .instructions a': 'routeLinkClick' 'click .instructions a': 'onSampleClicked'
# Private Methods ################################################################################ # Private Methods ################################################################################
@@ -138,7 +163,7 @@ module.exports = class CraftPageController extends PageController
controller.model.addToolsTo @model.craftsman.want controller.model.addToolsTo @model.craftsman.want
_completeStep: (controller)-> _completeStep: (controller)->
controller.model.completeInto @model.craftsman.have controller.markComplete @model.craftsman.have
_isAddingToolsPossible: (controller)-> _isAddingToolsPossible: (controller)->
tools = controller.model.recipe.tools tools = controller.model.recipe.tools
@@ -160,6 +185,12 @@ module.exports = class CraftPageController extends PageController
return true return true
_refreshOutdated: ->
if @model.craftsman.stage is Craftsman::STAGE.OUTDATED
@$el.addClass 'outdated'
else
@$el.removeClass 'outdated'
_refreshSectionVisibility: -> _refreshSectionVisibility: ->
return unless @_rendered return unless @_rendered
@@ -172,11 +203,13 @@ module.exports = class CraftPageController extends PageController
if @model.craftsman.want.isEmpty if @model.craftsman.want.isEmpty
visibleSections.push el for el in [@$instructionsSection, @$wantSection] visibleSections.push el for el in [@$instructionsSection, @$wantSection]
else if @model.craftsman.stage is Craftsman::STAGE.INVALID 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 else if not @model.craftsman.complete
visibleSections.push el for el in [@$wantSection, @$workingSection] visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
else 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 @hide $el for $el in allSections
@show $el for $el in visibleSections @show $el for $el in visibleSections
@@ -209,3 +242,28 @@ module.exports = class CraftPageController extends PageController
while @_stepControllers.length > index while @_stepControllers.length > index
@_stepControllers.pop().remove() @_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. //- All rights reserved.
//- //-
.view__item_group.section .view__craftsman_working
.content .panel
.waiting .waiting
img(src='/images/wait.gif') img(src='/images/wait.gif')
.message .message
p p
.count .count
p 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 { .view__craftsman_working {
.content { .panel {
background: $color-white;
box-shadow: none;
align-items : center; align-items : center;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
padding : $size-margin-xlarge; padding : $size-margin-xlarge;
.waiting { .waiting {
margin-bottom: $size-margin-xlarge; margin-bottom : $size-margin-xlarge;
} }
.message { .message {
margin-bottom: $size-margin-medium; margin-bottom : $size-margin-medium;
p { p {
font-family: $font-family-header; font-family : $font-family-header;
font-size: $font-size-large; font-size : $font-size-large;
text-align : center;
} }
} }
.count { .count {
p { p {
font-family: $font-family-header; font-family : $font-family-header;
font-size: $font-size-medium; 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 module.exports = class CraftsmanWorkingController extends BaseController
@::HIDE_TIMER_DURATION = 2000
constructor: (options={})-> constructor: (options={})->
if not options.model then throw new Error 'options.model is required' if not options.model then throw new Error 'options.model is required'
options.templateName = 'craft_page/craftsman_working' options.templateName = 'craft_page/craftsman_working'
super options 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 ####################################################################### # BaseController Methods #######################################################################
onDidModelChange: ->
@refresh()
onDidRender: -> onDidRender: ->
@$message = @$('.message p') @$button = @$('.button')
@$count = @$('.count p') @$count = @$('.count p')
@$message = @$('.message p')
@$outdated = @$('.outdated')
@$waiting = @$('.waiting') @$waiting = @$('.waiting')
@_controls = [@$button, @$count, @$message, @$outdated, @$waiting]
super super
refresh: -> refresh: ->
@_refreshStatusText()
super
# Private Methods ##############################################################################
_refreshStatusText: ->
return unless @$message? and @$count? return unless @$message? and @$count?
@show @$waiting button = count = message = outdated = waiting = null
switch @model.stage switch @model.stage
when Craftsman::STAGE.WAITING when Craftsman::STAGE.READY
@$message.html 'Preparing crafting calculation...' message = 'Ready to compute crafting plan!'
@$count.html '' count = 'Click "Calculate" to continue.'
button = true
when Craftsman::STAGE.GRAPHING when Craftsman::STAGE.GRAPHING
@$message.html 'Researching recipes...' message = 'Researching recipes...'
@$count.html "Found #{@model.stageCount} recipes so far..." count = "Found #{@model.stageCount} recipes so far..."
watiing = true
when Craftsman::STAGE.PLANNING when Craftsman::STAGE.PLANNING
@$message.html 'Figuring out possible crafting plans...' message = 'Figuring out possible crafting plans...'
@$count.html "Found #{@model.stageCount} possibilities so far..." count = "Found #{@model.stageCount} possibilities so far..."
watiing = true
when Craftsman::STAGE.ANALYZING when Craftsman::STAGE.ANALYZING
@$message.html 'Looking for the best plan...' message = 'Looking for the best plan...'
@$count.html "Finished checking #{@model.stageCount} so far..." count = "Finished checking #{@model.stageCount} so far..."
watiing = true
when Craftsman::STAGE.COMPLETE when Craftsman::STAGE.COMPLETE
@$message.html 'All done!' message = 'Crafting plan is complete.'
@$count.html ''
when Craftsman::STAGE.INVALID when Craftsman::STAGE.INVALID
@$message.html 'Couldn\'t make a crafting plan' message = 'Couldn\'t make a crafting plan!'
@$count.html '' count = 'Please report this problem using the Feedback box.'
@hide @waiting 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'
+2 -2
View File
@@ -11,5 +11,5 @@
.view__inventory .view__inventory
.view__recipe .view__recipe
.buttons .buttons
.button.complete: .bezel: p complete step a.button.tool: .bezel: p <span class="full">show plan for </span>tools
.button.tool: .bezel: p make this tool .button.complete: .bezel: p complete<span class="full"> step</span>
+50
View File
@@ -31,6 +31,10 @@
.view__inventory { .view__inventory {
flex: 50%; flex: 50%;
margin-left: $size-margin-large; margin-left: $size-margin-large;
.buttons {
display: none;
}
} }
.view__recipe { .view__recipe {
@@ -52,5 +56,51 @@
margin-left: $size-margin-medium; 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' BaseController = require '../../base_controller'
InventoryController = require '../../common/inventory/inventory_controller' InventoryController = require '../../common/inventory/inventory_controller'
RecipeController = require '../../common/recipe/recipe_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 @onComplete = options.onComplete or (controller)-> # do nothing
@onAddTools = options.onAddTools 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 ################################################################################ # Event Methods ################################################################################
onCompleteButtonClicked: (event)-> onCompleteButtonClicked: (event)->
return if @$completeButton.hasClass 'disabled' return if @$completeButton.hasClass 'disabled'
@onComplete this @onComplete this
onToolButtonClicked: (event)->
return if @$toolButton.hasClass 'disabled'
@onAddTools this
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@@ -63,6 +67,9 @@ module.exports = class StepController extends BaseController
onWillChangeModel: (oldModel, newModel)-> onWillChangeModel: (oldModel, newModel)->
if not newModel? then throw new Error 'model cannot be null' if not newModel? then throw new Error 'model cannot be null'
if @rendered
@$el.removeClass 'complete'
@$completeButton.removeClass 'disabled'
return super return super
refresh: -> refresh: ->
@@ -83,11 +90,19 @@ module.exports = class StepController extends BaseController
events: -> events: ->
return _.extend super, return _.extend super,
'click .button.complete': 'onCompleteButtonClicked' 'click .button.complete': 'onCompleteButtonClicked'
'click .button.tool': 'onToolButtonClicked'
# Private Methods ############################################################################## # Private Methods ##############################################################################
_refreshToolButton: -> _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 if @canAddTools this
@$toolButton.removeClass 'disabled' @$toolButton.removeClass 'disabled'
else else
+7 -5
View File
@@ -15,6 +15,10 @@
display: flex; display: flex;
@include screen-size(mobile) {
display: none;
}
.form-content { .form-content {
flex: 1 1 100%; flex: 1 1 100%;
@@ -73,13 +77,11 @@
background: $color-gray-light; background: $color-gray-light;
border: $size-border-medium solid $color-black; border: $size-border-medium solid $color-black;
border-left: 0; border-left: 0;
position: relative;
display: flex;
align-items: center;
justify-content: center;
p { p {
transform: rotate(-90deg); position: absolute; top: 50%; left: 50%;
transform: translateX(-50%) rotate(-90deg) translateX(10%);
font-family: $font-family-header; font-family: $font-family-header;
font-size: $label-size; font-size: $label-size;
+19
View File
@@ -19,12 +19,20 @@
> .content { > .content {
display: flex; display: flex;
@include screen-size(mobile) {
flex-direction: column;
}
color: $color-text-light; color: $color-text-light;
.left, .center, .right { .left, .center, .right {
flex: 1 1 33%; flex: 1 1 33%;
margin: $size-margin-large $size-margin-large $size-margin-large 0; margin: $size-margin-large $size-margin-large $size-margin-large 0;
@include screen-size(mobile) {
margin-left: $size-margin-large;
}
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -38,6 +46,7 @@
.action { .action {
flex: 1 1 auto; flex: 1 1 auto;
align-self: center; align-self: center;
margin-top: $size-margin-large;
margin-bottom: $size-margin-large; margin-bottom: $size-margin-large;
display: flex; display: flex;
@@ -55,3 +64,13 @@
height: $size-minecraft-block; height: $size-minecraft-block;
} }
} }
@include screen-size(mobile) {
.view__footer {
> .content {
.left, .center, .right {
flex: 0 0 auto;
}
}
}
}
+2
View File
@@ -21,4 +21,6 @@
.button.search: .bezel: p Search .button.search: .bezel: p Search
.button.login: .bezel: p Login .button.login: .bezel: p Login
.breadcrumb-bar
.breadcrumbs .breadcrumbs
.extra-nav
+77 -12
View File
@@ -23,24 +23,22 @@
img { img {
position : relative; position : relative;
top : -$size-minecraft-block * 0.5; height : $size-minecraft-block * 1.5;
left : -$size-minecraft-block * 0.5; width : $size-minecraft-block * 1.5;
height : $size-minecraft-block * 2.0;
width : $size-minecraft-block * 2.0;
} }
} }
h1 { h1 {
flex: 1 1 auto; flex: 1 1 auto;
white-space: nowrap;
} }
.addthis_sharing_toolbox { .addthis_sharing_toolbox {
flex : 0 0 auto; flex : 0 0 auto;
min-height : 37px; min-height : 37px; // actual size of addthis component
min-width : 144px; min-width : 144px;
margin-right : $size-margin-small; margin-right : $size-margin-small;
&.placeholder { &.placeholder {
border : 1px solid orange; border : 1px solid orange;
text-align : center; text-align : center;
@@ -62,24 +60,38 @@
align-items : center; align-items : center;
display : flex; display : flex;
flex-wrap : wrap; flex-wrap : wrap;
justify-content : space-around; justify-content : center;
padding : $size-margin-medium $size-margin-medium; padding : $size-margin-medium $size-margin-medium;
padding-top : 0; padding-top : 0;
.button { .button {
flex : 1 1 20%; flex-grow : 1;
min-width : 4 * $size-minecraft-block; flex-shrink : 1;
min-width : 3 * $size-minecraft-block;
max-width : 5 * $size-minecraft-block; max-width : 5 * $size-minecraft-block;
margin-top: $size-margin-medium; margin-top : $size-margin-medium;
margin-right : $size-margin-small;
&:last-child {
margin-right: 0;
}
} }
} }
.breadcrumbs { .breadcrumb-bar {
background: $color-screen; background: $color-screen;
padding: 0 ($size-margin-medium + $size-margin-large);
font-family: $font-family-control; font-family: $font-family-control;
font-size: $font-size-medium; font-size: $font-size-medium;
line-height: $font-size-medium + 2 * $size-margin-small;
padding: $size-margin-small $size-margin-medium; display: flex;
.breadcrumbs {
flex: 1 1 75%;
text-indent: -$size-margin-large;
&:before { &:before {
content: ""; content: "";
@@ -94,4 +106,57 @@
margin: 0 $size-margin-medium; margin: 0 $size-margin-medium;
} }
} }
.extra-nav {
flex: 1 1 25%;
align-self: flex-end;
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' BaseController = require '../base_controller'
ItemSelectorController = require '../common/item_selector/item_selector_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 @router.navigate '/news', trigger:true
return false return false
onSearch: -> onSearch: (event, hint='')->
@_selector.launch() @_selector.launch hint
.then (itemSlug)=> .then (itemSlug)=>
return unless itemSlug?
itemDisplay = @_modPack.findItemDisplay itemSlug itemDisplay = @_modPack.findItemDisplay itemSlug
@router.navigate itemDisplay.itemUrl, trigger:true @router.navigate itemDisplay.itemUrl, trigger:true
return false return false
@@ -62,8 +65,11 @@ module.exports = class HeaderController extends BaseController
@$('.addthis_sharing_toolbox').addClass 'placeholder' @$('.addthis_sharing_toolbox').addClass 'placeholder'
@$breadcrumbs = @$('.breadcrumbs') @$breadcrumbs = @$('.breadcrumbs')
@$extraNav = @$('.extra-nav')
@$loginButtonLabel = @$('.button.login p') @$loginButtonLabel = @$('.button.login p')
@$title = $('title') @$title = $('title')
@_checkForSearchRequest()
super super
onWillChangeModel: (oldModel, newModel)-> onWillChangeModel: (oldModel, newModel)->
@@ -75,6 +81,8 @@ module.exports = class HeaderController extends BaseController
@$loginButtonLabel.text if global.site.user? then "Logout" else "Login" @$loginButtonLabel.text if global.site.user? then "Logout" else "Login"
@_refreshBreadcrumbs() @_refreshBreadcrumbs()
@_refreshExtraNav()
@_refreshSelectedNavButton()
@_refreshTitle() @_refreshTitle()
super super
@@ -87,10 +95,16 @@ module.exports = class HeaderController extends BaseController
'click .login': 'onLogin' 'click .login': 'onLogin'
'click .news': 'onNews' 'click .news': 'onNews'
'click .search': 'onSearch' 'click .search': 'onSearch'
'click .breadcrumbs a': 'routeLinkClick' 'click .breadcrumb-bar a': 'routeLinkClick'
# Private Methods ############################################################################## # Private Methods ##############################################################################
_checkForSearchRequest: ->
params = new UrlParams search:{type:'string'}
return unless params.search?
_.delay (=> @onSearch {}, params.search), c.duration.slow
_refreshBreadcrumbs: -> _refreshBreadcrumbs: ->
breadcrumbs = @model?.controller?.getBreadcrumbs() breadcrumbs = @model?.controller?.getBreadcrumbs()
breadcrumbs ?= [] breadcrumbs ?= []
@@ -106,6 +120,23 @@ module.exports = class HeaderController extends BaseController
else else
@hide @$breadcrumbs @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: -> _refreshTitle: ->
title = @model?.controller?.getTitle() title = @model?.controller?.getTitle()
if title if title
+4 -2
View File
@@ -12,7 +12,7 @@ html
link(href="/images/favicon.png" rel="icon" type="image/png") link(href="/images/favicon.png" rel="icon" type="image/png")
link(href="/main.css" rel="stylesheet" type="text/css" ) link(href="/main.css" rel="stylesheet" type="text/css" )
meta(charset="UTF-8") meta(charset="UTF-8")
meta(name="viewport" content="width=480") meta(name="viewport" content="user-scalable=no, width=device-width")
body body
.view__feedback .view__feedback
@@ -21,7 +21,7 @@ html
.page .page
.view__header .view__header
.content(style="display: none") .content.hidden
.content-loading .content-loading
img(src="/images/wait.gif") img(src="/images/wait.gif")
@@ -32,4 +32,6 @@ html
include ../includes/_google_adsense.jade include ../includes/_google_adsense.jade
include ../includes/_google_analytics.jade include ../includes/_google_analytics.jade
include ../includes/_google_sitelinks.jade
include ../includes/_twitter_follow.jade
+6 -3
View File
@@ -36,19 +36,22 @@ html {
} }
& > *:first-child { & > *:first-child {
flex: 0 0 50%; flex: 1 1 100%;
box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow; box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow;
} }
} }
.page { .page {
margin : $size-margin-large 0;
max-width : $size-page-width; max-width : $size-page-width;
width : 100%; width : 100%;
background : $color-background-page; @include screen-size(desktop) {
margin : $size-margin-large 0;
box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow; box-shadow : $size-margin-small $size-margin-small $size-margin-large $color-shadow;
}
background : $color-background-page;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
+1 -2
View File
@@ -7,7 +7,6 @@
.content.view__item_page .content.view__item_page
.left .left
.view__adsense
.right .right
.about .about
@@ -17,7 +16,7 @@
.title .title
a.sourceMod a.sourceMod
.button-row .button-row
.button.craftingPlan: .bezel: p View Crafting Plan .button.craftingPlan: .bezel: p View <span class="full">Crafting </span>Plan
.right .right
p Official Link: p Official Link:
a.officialLink project page a.officialLink project page
+48 -1
View File
@@ -48,7 +48,7 @@
.button { .button {
flex: 1 1 100%; 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. # All rights reserved.
# #
AdsenseController = require '../common/adsense/adsense_controller'
EditableFile = require '../../models/site/editable_file' EditableFile = require '../../models/site/editable_file'
Item = require '../../models/game/item' Item = require '../../models/game/item'
ItemGroupController = require '../common/item_group/item_group_controller' ItemGroupController = require '../common/item_group/item_group_controller'
@@ -42,6 +41,7 @@ module.exports = class ItemPageController extends PageController
@_itemSlug = options.itemSlug @_itemSlug = options.itemSlug
@_modPack = options.modPack @_modPack = options.modPack
@_router = options.router @_router = options.router
@_triggerEditing = options.login
@_modPack.on c.event.change, => @_modPack.on c.event.change, =>
@tryRefresh() @tryRefresh()
@@ -68,6 +68,13 @@ module.exports = class ItemPageController extends PageController
$("<b>#{display.itemName}</b>") $("<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: -> getMetaDescription: ->
return null unless @_itemSlug? return null unless @_itemSlug?
display = @_modPack.findItemDisplay @_itemSlug display = @_modPack.findItemDisplay @_itemSlug
@@ -83,9 +90,11 @@ module.exports = class ItemPageController extends PageController
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidModelChange: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper', router: @_router @trigger c.event.change
super
onDidRender: ->
options = imageLoader:@_imageLoader, modPack:@_modPack, router:@_router, show:false options = imageLoader:@_imageLoader, modPack:@_modPack, router:@_router, show:false
@_multiblockController = @addChild MultiblockViewerController, '.view__multiblock_viewer', options @_multiblockController = @addChild MultiblockViewerController, '.view__multiblock_viewer', options
@_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options @_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options
@@ -102,6 +111,7 @@ module.exports = class ItemPageController extends PageController
enterFeedback: @_enterFeedback enterFeedback: @_enterFeedback
@$aboutImage = @$('.about img') @$aboutImage = @$('.about img')
@$craftingPlanButton = @$('.button.craftingPlan')
@$name = @$('.about .title') @$name = @$('.about .title')
@$officialLink = @$('.about a.officialLink') @$officialLink = @$('.about a.officialLink')
@$sourceModLink = @$('.about a.sourceMod') @$sourceModLink = @$('.about a.sourceMod')
@@ -135,6 +145,15 @@ module.exports = class ItemPageController extends PageController
else else
@hide @$aboutLinks @hide @$aboutLinks
if @model.item.isCraftable
@show @$craftingPlanButton
else
@hide @$craftingPlanButton
if @_triggerEditing
@_triggerEditing = false
@_descriptionController.onEditClicked {}
@show() @show()
else else
@hide() @hide()
@@ -317,7 +336,7 @@ module.exports = class ItemPageController extends PageController
item = @_modPack.findItem @_itemSlug, includeDisabled:true item = @_modPack.findItem @_itemSlug, includeDisabled:true
if item? if item?
if not ItemSlug.equal item.slug, @_itemSlug 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 return
@model.item = item @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 { .view__recipe_detail {
display : flex; display : flex;
.input, .output{ .input, .output {
flex : 0 1 33%; flex : 0 1 33%;
h3 { h3 {
@@ -20,8 +20,13 @@
} }
} }
.input {
order: 10;
}
.pattern { .pattern {
flex : 0 1 33%; flex : 0 1 33%;
order: 20;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
@@ -36,9 +41,48 @@
} }
} }
.output {
order: 30;
}
&:not(:first-child) { &:not(:first-child) {
border-top : 1px solid $color-gray-light; border-top : 1px solid $color-gray-light;
margin-top : $size-margin-medium; margin-top : $size-margin-medium;
padding-top : $size-margin-large; 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 ##############################################################################
+5 -3
View File
@@ -1,5 +1,5 @@
//- //-
//- Crafting Guide - item_page.jade //- Crafting Guide - mod_page.jade
//- //-
//- Copyright © 2014-2016 by Redwood Labs //- Copyright © 2014-2016 by Redwood Labs
//- All rights reserved. //- All rights reserved.
@@ -7,7 +7,6 @@
.content.view__mod_page .content.view__mod_page
.left .left
.view__adsense
.right .right
.about .about
@@ -17,8 +16,11 @@
.title .title
.author .author
.description .description
.modpack
span.checkbox
span.label I have this mod in my modpack
.version .version
span in my mod pack span I'm using version:
select select
.warning. .warning.
<b>PLEASE NOTE:</b> By selecting "no", crafting plans, search, and other features will ignore items <b>PLEASE NOTE:</b> By selecting "no", crafting plans, search, and other features will ignore items
+77 -2
View File
@@ -1,5 +1,5 @@
// //
// Crafting Guide - item_page.scss // Crafting Guide - mod_page.scss
// //
// Copyright © 2014-2016 by Redwood Labs // Copyright © 2014-2016 by Redwood Labs
// All rights reserved. // All rights reserved.
@@ -49,8 +49,44 @@
line-height: $font-size-medium * 1.25; 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 { .version {
margin-top: $size-margin-large; margin-top: $size-margin-medium;
font-family: $font-family-control; font-family: $font-family-control;
font-size: $font-size-medium; 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. # All rights reserved.
# #
AdsenseController = require '../common/adsense/adsense_controller'
BaseController = require '../base_controller' BaseController = require '../base_controller'
Item = require '../../models/game/item' Item = require '../../models/game/item'
ItemGroupController = require '../common/item_group/item_group_controller' ItemGroupController = require '../common/item_group/item_group_controller'
@@ -29,6 +28,14 @@ module.exports = class ModPageController extends BaseController
# Event Methods ################################################################################ # Event Methods ################################################################################
onToggleEnabled: ->
if @model.activeVersion is Mod.Version.None
@model.activeVersion = Mod.Version.Latest
else
@model.activeVersion = Mod.Version.None
return false
onVersionChanged: -> onVersionChanged: ->
@model.activeVersion = @$versionSelector.val() @model.activeVersion = @$versionSelector.val()
return false return false
@@ -58,8 +65,6 @@ module.exports = class ModPageController extends BaseController
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model: 'skyscraper'
@$author = @$('.about .author') @$author = @$('.about .author')
@$description = @$('.about .description') @$description = @$('.about .description')
@$documentationLink = @$('.about .documentation') @$documentationLink = @$('.about .documentation')
@@ -67,15 +72,18 @@ module.exports = class ModPageController extends BaseController
@$homePageLink = @$('.about .homePage') @$homePageLink = @$('.about .homePage')
@$itemGroups = @$(".itemGroups") @$itemGroups = @$(".itemGroups")
@$logo = @$('.about img') @$logo = @$('.about img')
@$modpackSection = @$('.modpack')
@$title = @$('.about .title') @$title = @$('.about .title')
@$tutorialsContainer = @$('section.tutorials .panel') @$tutorialsContainer = @$('section.tutorials .panel')
@$tutorialsSection = @$('section.tutorials') @$tutorialsSection = @$('section.tutorials')
@$versionSection = @$('.version')
@$versionSelector = @$('.version select') @$versionSelector = @$('.version select')
@$warning = @$('.warning') @$warning = @$('.warning')
super super
refresh: -> refresh: ->
@_refreshAboutBlock() @_refreshAboutBlock()
@_refreshEnabled()
@_refreshItemGroups() @_refreshItemGroups()
@_refreshTutorials() @_refreshTutorials()
@_refreshVersionSelector() @_refreshVersionSelector()
@@ -86,6 +94,7 @@ module.exports = class ModPageController extends BaseController
events: -> events: ->
return _.extend super, return _.extend super,
'change .version select': 'onVersionChanged' 'change .version select': 'onVersionChanged'
'click .modpack': 'onToggleEnabled'
# Private Methods ############################################################################## # Private Methods ##############################################################################
@@ -107,6 +116,19 @@ module.exports = class ModPageController extends BaseController
@$logo.attr 'src', '' @$logo.attr 'src', ''
@$title.text '' @$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: -> _refreshItemGroups: ->
@_groupControllers ?= [] @_groupControllers ?= []
groupIndex = 0 groupIndex = 0
@@ -124,6 +146,7 @@ module.exports = class ModPageController extends BaseController
router: @_router router: @_router
title: if group is Item.Group.Other then 'Items' else group title: if group is Item.Group.Other then 'Items' else group
_.defer =>
@_groupControllers.push controller @_groupControllers.push controller
@$itemGroups.append controller.$el @$itemGroups.append controller.$el
controller.render() controller.render()
@@ -163,19 +186,16 @@ module.exports = class ModPageController extends BaseController
_refreshVersionSelector: -> _refreshVersionSelector: ->
modVersions = @model.modVersions modVersions = @model.modVersions
if (@model.activeVersion is Mod.Version.None) or modVersions.length < 2
@hide @$versionSection
else
@show @$versionSection
selectedModVersion = @effectiveModVersion selectedModVersion = @effectiveModVersion
@$versionSelector.empty() @$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 for modVersion in @model.modVersions
$option = $("<option value=\"#{modVersion.version}\">#{modVersion.version}</option>") $option = $("<option value=\"#{modVersion.version}\">#{modVersion.version}</option>")
if modVersion is selectedModVersion if modVersion is selectedModVersion
+78 -52
View File
@@ -7,9 +7,86 @@
.content.view__news_page .content.view__news_page
.left .left
.view__adsense
.right .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 section
h3 2016-04-05 h3 2016-04-05
.panel .panel
@@ -79,54 +156,3 @@
p. p.
With many thanks to <a href="https://github.com/pkmnfrk">Mike Caron</a>, I'm pleased to announce 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>! 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.
+10
View File
@@ -8,6 +8,15 @@
.view__news_page { .view__news_page {
@include layout-body-with-sidebar; @include layout-body-with-sidebar;
& > .right {
display: flex;
flex-direction: column;
align-items: stretch;
.view__twitter {
align-self: center;
}
section { section {
&:not(:first-child) { &:not(:first-child) {
margin-top : $size-margin-large; margin-top : $size-margin-large;
@@ -27,4 +36,5 @@
} }
} }
} }
}
} }
@@ -5,7 +5,6 @@
# All rights reserved. # 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: -> getTitle: ->
return "News" return "News"
# BaseController Overrides #####################################################################
onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
# Backbone.View Overrides ###################################################################### # Backbone.View Overrides ######################################################################
events: -> events: ->
+4
View File
@@ -19,6 +19,10 @@ module.exports = class PageController extends BaseController
getBreadcrumbs: -> getBreadcrumbs: ->
return [] return []
getExtraNav: ->
# subclasses may override this to provide extra content in the right-hand side of the breadcrumb bar
return null
getMetaDescription: -> getMetaDescription: ->
# subclasses should override this to return the page-specific text for the meta description tag # subclasses should override this to return the page-specific text for the meta description tag
return null return null
+15 -2
View File
@@ -11,6 +11,7 @@ ItemPageController = require './item_page/item_page_controller'
ItemSlug = require '../models/game/item_slug' ItemSlug = require '../models/game/item_slug'
LoginPageController = require './login_page/login_page_controller' LoginPageController = require './login_page/login_page_controller'
ModPageController = require './mod_page/mod_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' NewsPageController = require './news_page/news_page_controller'
TutorialPageController = require './tutorial_page/tutorial_page_controller' TutorialPageController = require './tutorial_page/tutorial_page_controller'
UrlParams = require './url_params' UrlParams = require './url_params'
@@ -66,6 +67,10 @@ module.exports = class Router extends Backbone.Router
'craft/:text/': 'route__craft' 'craft/:text/': 'route__craft'
'craft/:text/index.html': '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/': 'route__login' 'login/': 'route__login'
'login/index.html': 'route__login' 'login/index.html': 'route__login'
@@ -98,17 +103,25 @@ module.exports = class Router extends Backbone.Router
@_siteController.setPage 'browseMod', controller @_siteController.setPage 'browseMod', controller
route__browseModItem: (modSlug, itemSlug)-> route__browseModItem: (modSlug, itemSlug)->
params = new UrlParams login:{type:'boolean', default:false}
slug = new ItemSlug modSlug, itemSlug slug = new ItemSlug modSlug, itemSlug
controller = new ItemPageController @_makeOptions {itemSlug:slug} controller = new ItemPageController @_makeOptions {itemSlug:slug, login:params.login}
@_siteController.setPage 'browseModItem', controller @_siteController.setPage 'browseModItem', controller
route__browseTutorial: (modSlug, tutorialSlug)-> 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 @_siteController.setPage 'browseTutorial', controller
route__configure: -> route__configure: ->
@route__craft() @route__craft()
route__editMod: (modSlug)->
controller = new ModEditorPageController @_makeOptions()
controller.model = @_siteController.modPack.getMod modSlug
@_siteController.setPage 'editMod', controller
route__craft: (text)-> route__craft: (text)->
controller = new CraftPageController @_makeOptions {} controller = new CraftPageController @_makeOptions {}
controller.model.params = inventoryText:text controller.model.params = inventoryText:text
+15 -6
View File
@@ -5,8 +5,10 @@
# All rights reserved. # All rights reserved.
# #
AdsenseController = require './common/adsense/adsense_controller'
BaseController = require './base_controller' BaseController = require './base_controller'
FeedbackController = require './feedback/feedback_controller' FeedbackController = require './feedback/feedback_controller'
FileCache = require '../models/site/file_cache'
FooterController = require './footer/footer_controller' FooterController = require './footer/footer_controller'
GitHubUser = require '../models/site/github_user' GitHubUser = require '../models/site/github_user'
HeaderController = require './header/header_controller' HeaderController = require './header/header_controller'
@@ -26,11 +28,13 @@ module.exports = class SiteController extends BaseController
super options super options
@client = options.client @client = options.client
@fileCache = new FileCache c.url.modpackArchive()
@imageLoader = new ImageLoader defaultUrl:'/images/unknown.png' @imageLoader = new ImageLoader defaultUrl:'/images/unknown.png'
@modPack = new ModPack @modPack = new ModPack {}, fileCache:@fileCache
@router = new Router this @router = new Router this
@storage = options.storage @storage = options.storage
@_adsenseController = new AdsenseController
@_currentPage = null @_currentPage = null
@_currentPageController = null @_currentPageController = null
@_user = null @_user = null
@@ -42,7 +46,7 @@ module.exports = class SiteController extends BaseController
m.activeModVersion.fetch() if m.activeModVersion? m.activeModVersion.fetch() if m.activeModVersion?
for modSlug, modData of c.defaultMods 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 mod.on c.event.change + ':activeModVersion', makeResponder mod
@storage.register "mod:#{mod.slug}", mod, 'activeVersion', modData.defaultVersion @storage.register "mod:#{mod.slug}", mod, 'activeVersion', modData.defaultVersion
mod.fetch() mod.fetch()
@@ -51,8 +55,8 @@ module.exports = class SiteController extends BaseController
if global.env isnt 'prerender' if global.env isnt 'prerender'
@modPack.once c.event.sync, => @modPack.once c.event.sync, =>
@$pageContent.css 'display', '' @$pageContent.removeClass 'hidden'
@$pageContentLoading.css 'display', 'none' @$pageContentLoading.addClass 'hidden'
loadCurrentUser: -> loadCurrentUser: ->
@client.fetchCurrentUser() @client.fetchCurrentUser()
@@ -80,7 +84,7 @@ module.exports = class SiteController extends BaseController
resumeAfterLogin: -> resumeAfterLogin: ->
url = @storage.load 'post-login-url' 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 if url? then @router.navigate url, trigger:true
@storage.store 'post-login-url', null @storage.store 'post-login-url', null
@@ -142,16 +146,21 @@ module.exports = class SiteController extends BaseController
$pageContent = $('.page > .content') $pageContent = $('.page > .content')
$pageContent.removeClass() $pageContent.removeClass()
$pageContent.addClass 'content' $pageContent.addClass 'content'
$pageContent.css display:''
if not @$pageContentLoading.hasClass 'hidden'
$pageContent.addClass 'hidden'
window.scrollTo 0, 0 window.scrollTo 0, 0
@_headerController.model = controller: controller @_headerController.model = controller: controller, page: page
@_currentPageController.user = @user @_currentPageController.user = @user
@_currentPageController.onWillShow() @_currentPageController.onWillShow()
@_currentPageController.$el = $pageContent @_currentPageController.$el = $pageContent
@_currentPageController.render() @_currentPageController.render()
@_adsenseController.reset()
_resetGlobals: -> _resetGlobals: ->
if global.env in c.productionEnvs if global.env in c.productionEnvs
for key, value of global for key, value of global
@@ -7,7 +7,6 @@
.view__tutorial_page .view__tutorial_page
.left .left
.view__adsense
.right .right
.about .about
@@ -51,12 +51,28 @@
margin-top : -$size-margin-medium; margin-top : -$size-margin-medium;
display : flex; display : flex;
flex-wrap : wrap; flex-wrap : wrap;
justify-content: space-between;
padding-right : -$size-margin-medium;
& > * { & > * {
flex : 1 1 100%;
margin-right : $size-margin-medium; margin-right : $size-margin-medium;
margin-top : $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. # All rights reserved.
# #
AdsenseController = require '../common/adsense/adsense_controller'
PageController = require '../page_controller' PageController = require '../page_controller'
MarkdownSectionController = require '../common/markdown_section/markdown_section_controller' MarkdownSectionController = require '../common/markdown_section/markdown_section_controller'
VideoController = require '../common/video/video_controller' VideoController = require '../common/video/video_controller'
@@ -60,8 +59,6 @@ module.exports = class TutorialPageController extends PageController
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper'
@$sourceModLink = @$('.sourceMod a') @$sourceModLink = @$('.sourceMod a')
@$officialLink = @$('.officialLink a') @$officialLink = @$('.officialLink a')
@$officialLinkPanel = @$('.officialLink') @$officialLinkPanel = @$('.officialLink')
+5 -8
View File
@@ -47,7 +47,7 @@
background : url('/images/button-background-hover.png') repeat; background : url('/images/button-background-hover.png') repeat;
} }
&:active { &:active, &.active {
background : url('/images/button-background-active.png') repeat; background : url('/images/button-background-active.png') repeat;
.bezel { .bezel {
@@ -69,15 +69,12 @@
} }
} }
.page > .content { .hidden {
min-height: $size-skyscraper-height; display: none !important;
} }
.skyscraper { .page > .content {
height : $size-skyscraper-height - 2px; min-height: $size-ad-skyscraper-height;
width : $size-skyscraper-width - 2px;
border : 1px solid $color-gray-medium;
} }
.scrollDisabled { .scrollDisabled {
+3
View File
@@ -8,6 +8,9 @@
// normalize all values // normalize all values
@import './reset'; @import './reset';
// define media breakpoints
@import './media';
// define variables // define variables
@import './colors'; @import './colors';
@import './fonts'; @import './fonts';
+22
View File
@@ -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 }
}
}
+65 -47
View File
@@ -10,6 +10,11 @@
filter : blur($radius); 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 { @mixin grayscale {
-webkit-filter : grayscale(100%); -webkit-filter : grayscale(100%);
-moz-filter : grayscale(100%); -moz-filter : grayscale(100%);
@@ -18,6 +23,66 @@
filter : gray; 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 { @mixin no-select {
-webkit-touch-callout : none; /* iOS Safari */ -webkit-touch-callout : none; /* iOS Safari */
-webkit-user-select : none; /* Chrome/Safari/Opera */ -webkit-user-select : none; /* Chrome/Safari/Opera */
@@ -26,36 +91,6 @@
user-select : none; /* non-prefixed version, currently not supported by any browser */ 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 { @mixin pixel-image {
image-rendering : -moz-crisp-edges; /* Firefox */ image-rendering : -moz-crisp-edges; /* Firefox */
image-rendering : -o-crisp-edges; /* Opera */ image-rendering : -o-crisp-edges; /* Opera */
@@ -63,20 +98,3 @@
image-rendering : crisp-edges; image-rendering : crisp-edges;
-ms-interpolation-mode : nearest-neighbor; /* IE (non-standard property) */ -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;
}
}
}
+6 -2
View File
@@ -25,5 +25,9 @@ $size-minecraft-block : 32px;
$size-page-width : $size-rem * 80; $size-page-width : $size-rem * 80;
$size-skyscraper-height : 600px; $size-ad-large-mobile-banner-height : 100px;
$size-skyscraper-width : 160px; $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;
+39 -5
View File
@@ -8,23 +8,38 @@
######################################################################################################################## ########################################################################################################################
exports.adsense = adsense = {} exports.adsense = adsense = {}
adsense.adTypeMap = desktop:'skyscraper', tablet:'leaderboard', mobile:'largeMobileBanner'
adsense.clientId = 'ca-pub-6593013914878730' 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 = {}
adsense.skyscraper.height = 600 adsense.skyscraper.cssClass = 'skyscraper'
adsense.skyscraper.width = 160 adsense.skyscraper.height = 600 # px
adsense.skyscraper.margin = 24 adsense.skyscraper.margin = 24 # px
adsense.slotIds = ['7613920409', '9574673605', '3388539204'] adsense.skyscraper.slotIds = ['7613920409', '9574673605', '3388539204']
adsense.skyscraper.width = 160 # px
exports.defaultMods = defaultMods = {} exports.defaultMods = defaultMods = {}
defaultMods.minecraft = { defaultVersion: '1.7.10' } # Minecraft must be first defaultMods.minecraft = { defaultVersion: '1.7.10' } # Minecraft must be first
defaultMods.advanced_solar_panels = { defaultVersion: '3.5.1' } defaultMods.advanced_solar_panels = { defaultVersion: '3.5.1' }
defaultMods.agricraft = { defaultVersion: '1.4.6' }
defaultMods.applied_energistics_2 = { defaultVersion: 'rv1-stable-1' } defaultMods.applied_energistics_2 = { defaultVersion: 'rv1-stable-1' }
defaultMods.big_reactors = { defaultVersion: '0.4.2A2' } defaultMods.big_reactors = { defaultVersion: '0.4.2A2' }
defaultMods.buildcraft = { defaultVersion: '6.4.6' } defaultMods.buildcraft = { defaultVersion: '6.4.6' }
defaultMods.computercraft = { defaultVersion: '1.74' } defaultMods.computercraft = { defaultVersion: '1.74' }
defaultMods.enderio = { defaultVersion: '2.2.7.325' }
defaultMods.ender_storage = { defaultVersion: '1.4.5.29' } defaultMods.ender_storage = { defaultVersion: '1.4.5.29' }
defaultMods.enderio = { defaultVersion: '2.2.7.325' }
defaultMods.extra_cells = { defaultVersion: '2.2.73b129' } defaultMods.extra_cells = { defaultVersion: '2.2.73b129' }
defaultMods.extra_utilities = { defaultVersion: '1.2.2' } defaultMods.extra_utilities = { defaultVersion: '1.2.2' }
defaultMods.forestry = { defaultVersion: '3.4.0.7' } 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.industrial_craft_2 = { defaultVersion: '2.2.663' }
defaultMods.iron_chests = { defaultVersion: '6.0.62.742' } defaultMods.iron_chests = { defaultVersion: '6.0.62.742' }
defaultMods.jabba = { defaultVersion: '1.2.1a' } defaultMods.jabba = { defaultVersion: '1.2.1a' }
defaultMods.logistics_pipes = { defaultVersion: '0.9.3.100' }
defaultMods.mekanism = { defaultVersion: '7.1.1.127' } defaultMods.mekanism = { defaultVersion: '7.1.1.127' }
defaultMods.minefactory_reloaded = { defaultVersion: '2.8.0RC8-86' } defaultMods.minefactory_reloaded = { defaultVersion: '2.8.0RC8-86' }
defaultMods.modular_powersuits = { defaultVersion: '0.11.0-300-thermal-expansion' } defaultMods.modular_powersuits = { defaultVersion: '0.11.0-300-thermal-expansion' }
defaultMods.opencomputers = { defaultVersion: '1.5.22' } 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.railcraft = { defaultVersion: '9.5.0' }
defaultMods.simply_jetpacks = { defaultVersion: '1.4.1' } defaultMods.simply_jetpacks = { defaultVersion: '1.4.1' }
defaultMods.solar_flux = { defaultVersion: '0.5b' } defaultMods.solar_flux = { defaultVersion: '0.5b' }
defaultMods.storage_drawers = { defaultVersion: '1.7.10-1.6.2' } defaultMods.storage_drawers = { defaultVersion: '1.7.10-1.6.2' }
defaultMods.thermal_dynamics = { defaultVersion: '1.0.0RC7-98' } defaultMods.thermal_dynamics = { defaultVersion: '1.0.0RC7-98' }
defaultMods.thermal_expansion = { defaultVersion: '4.0.0B8-23' } defaultMods.thermal_expansion = { defaultVersion: '4.0.0B8-23' }
defaultMods.tinkers_construct = { defaultVersion: '1.7.10-1.8.8' }
exports.duration = duration = {} exports.duration = duration = {}
duration.snap = 100 duration.snap = 100
@@ -109,6 +128,20 @@ exports.productionEnvs = [ 'staging', 'production' ]
exports.requiredMods = [ 'minecraft' ] 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 = {}
exports.server.defaultPort = 8080 exports.server.defaultPort = 8080
@@ -133,6 +166,7 @@ url.login = _.template "/login"
url.mod = _.template "/browse/<%= modSlug %>/" url.mod = _.template "/browse/<%= modSlug %>/"
url.modData = _.template "/data/<%= modSlug %>/mod.cg" url.modData = _.template "/data/<%= modSlug %>/mod.cg"
url.modIcon = _.template "/data/<%= modSlug %>/icon.png" url.modIcon = _.template "/data/<%= modSlug %>/icon.png"
url.modpackArchive = _.template "/data/modpack.cg"
url.modVersionData = _.template "/data/<%= modSlug %>/versions/<%= modVersion %>/mod-version.cg" url.modVersionData = _.template "/data/<%= modSlug %>/versions/<%= modVersion %>/mod-version.cg"
url.root = _.template "/" url.root = _.template "/"
url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/" url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/"
+1
View File
@@ -16,5 +16,6 @@ sendIndex = (request, response)->
router.get '/browse*', sendIndex router.get '/browse*', sendIndex
router.get '/craft*', sendIndex router.get '/craft*', sendIndex
router.get '/edit*', sendIndex
router.get '/login*', sendIndex router.get '/login*', sendIndex
router.get '/news*', sendIndex router.get '/news*', sendIndex