Merge branch 'andrewminer-tutorial-pages' into andrewminer-thermal-dynamics
This commit is contained in:
Binary file not shown.
@@ -16,6 +16,7 @@ fs = require 'fs'
|
||||
|
||||
modSlugs = {}
|
||||
itemSlugs = {}
|
||||
tutorialSlugs = []
|
||||
|
||||
base = 'http://crafting-guide.com'
|
||||
|
||||
@@ -41,9 +42,15 @@ for modSlug, modData of DefaultMods
|
||||
modVersion.eachItem (item)->
|
||||
itemSlugs[item.slug] = item.slug
|
||||
|
||||
for tutorial in mod.tutorials
|
||||
tutorialSlugs.push mod:mod.slug, tutorial:tutorial.slug
|
||||
|
||||
for modSlug in _.values(modSlugs).sort()
|
||||
urls.push base + "/browse/#{modSlug}/"
|
||||
|
||||
for tutorialSlug in tutorialSlugs
|
||||
urls.push base + "/browse/#{tutorialSlug.mod}/tutorials/#{tutorialSlug.tutorial}/"
|
||||
|
||||
for key in _.keys(itemSlugs).sort()
|
||||
itemSlug = itemSlugs[key]
|
||||
urls.push base + "/browse/#{itemSlug.mod}/#{itemSlug.item}/"
|
||||
|
||||
@@ -69,6 +69,9 @@ Url.mod = _.template "/browse/<%= modSlug %>/"
|
||||
Url.modData = _.template "/data/<%= modSlug %>/mod.cg"
|
||||
Url.modIcon = _.template "/browse/<%= modSlug %>/icon.png"
|
||||
Url.modVersionData = _.template "/data/<%= modSlug %>/<%= modVersion %>/mod-version.cg"
|
||||
Url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/"
|
||||
Url.tutorialData = _.template "/data/<%= modSlug %>/tutorials/<%= tutorialSlug %>.cg"
|
||||
Url.tutorialIcon = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/icon.png"
|
||||
|
||||
exports.UrlParam = UrlParam = {}
|
||||
UrlParam.quantity = 'count'
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
###
|
||||
Crafting Guide - markdown_section_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class MarkdownSectionController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
options.model ?= ''
|
||||
options.title ?= 'Description'
|
||||
options.templateName = 'markdown_section'
|
||||
super options
|
||||
|
||||
@title = options.title
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$title = @$('h2')
|
||||
@$markdownPanel = @$('.markdown')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$title.html @title
|
||||
|
||||
@$markdownPanel.empty()
|
||||
@$markdownPanel.html _.parseMarkdown @model
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .markdown': 'routeLinkClick'
|
||||
@@ -11,6 +11,7 @@ ItemGroupController = require './item_group_controller'
|
||||
Mod = require '../models/mod'
|
||||
ModPack = require '../models/mod_pack'
|
||||
PageController = require './page_controller'
|
||||
TutorialController = require './tutorial_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Text} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
@@ -55,15 +56,17 @@ module.exports = class ModPageController extends PageController
|
||||
onDidRender: ->
|
||||
@adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
|
||||
|
||||
@$name = @$('.name')
|
||||
@$byline = @$('.byline p')
|
||||
@$description = @$('.description p')
|
||||
@$documentationLink = @$('.documentation')
|
||||
@$downloadLink = @$('.download')
|
||||
@$homePageLink = @$('.homePage')
|
||||
@$groupContainer = @$('.itemGroups')
|
||||
@$titleImage = @$('.titleImage img')
|
||||
@$versionSelector = @$('select.version')
|
||||
@$name = @$('.name')
|
||||
@$byline = @$('.byline p')
|
||||
@$description = @$('.description p')
|
||||
@$documentationLink = @$('.documentation')
|
||||
@$downloadLink = @$('.download')
|
||||
@$homePageLink = @$('.homePage')
|
||||
@$groupContainer = @$('.itemGroups')
|
||||
@$titleImage = @$('.titleImage img')
|
||||
@$tutorialsSection = @$('.tutorials')
|
||||
@$tutorialsContainer = @$('.tutorials .panel')
|
||||
@$versionSelector = @$('select.version')
|
||||
|
||||
super
|
||||
|
||||
@@ -83,6 +86,7 @@ module.exports = class ModPageController extends PageController
|
||||
@_refreshLink @$downloadLink, @model.downloadUrl
|
||||
|
||||
@_refreshItemGroups()
|
||||
@_refreshTutorials()
|
||||
@_refreshVersions()
|
||||
super
|
||||
|
||||
@@ -128,7 +132,7 @@ module.exports = class ModPageController extends PageController
|
||||
|
||||
while @_groupControllers.length > groupIndex + 1
|
||||
controller = @_groupControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, -> @remove()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> @remove()
|
||||
|
||||
_refreshLink: ($link, url)->
|
||||
if url?
|
||||
@@ -137,6 +141,32 @@ module.exports = class ModPageController extends PageController
|
||||
else
|
||||
$link.slideUp duration:Duration.normal
|
||||
|
||||
_refreshTutorials: ->
|
||||
@_tutorialControllers ?= []
|
||||
tutorials = @model.tutorials
|
||||
|
||||
if tutorials.length is 0
|
||||
@$tutorialsSection.addClass 'hidden'
|
||||
else
|
||||
@$tutorialsSection.removeClass 'hidden'
|
||||
|
||||
index = 0
|
||||
for tutorial in tutorials
|
||||
controller = @_tutorialControllers[index]
|
||||
if not controller?
|
||||
controller = new TutorialController model:tutorial
|
||||
controller.render()
|
||||
@$tutorialsContainer.append controller.$el
|
||||
@_tutorialControllers.push controller
|
||||
else
|
||||
controller.model = model
|
||||
|
||||
index += 1
|
||||
|
||||
while @_tutorialControllers.length > index
|
||||
controller = @_tutorialControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> @remove()
|
||||
|
||||
_refreshVersions: ->
|
||||
@$versionSelector.empty()
|
||||
return unless @model?
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
###
|
||||
Crafting Guide - tutorial_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class TutorialController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
options.templateName = 'tutorial'
|
||||
super options
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$icon = @$('img')
|
||||
@$link = @$('a')
|
||||
@$title = @$('p')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
templateData = modSlug:@model.modSlug, tutorialSlug:@model.slug
|
||||
@$icon.attr 'src', Url.tutorialIcon templateData
|
||||
@$link.attr 'href', Url.tutorial templateData
|
||||
@$title.html @model.name
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
@@ -0,0 +1,159 @@
|
||||
###
|
||||
Crafting Guide - tutorial_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
AdsenseController = require './adsense_controller'
|
||||
BaseController = require './base_controller'
|
||||
MarkdownSectionController = require './markdown_section_controller'
|
||||
VideoController = require './video_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class TutorialPageController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.modSlug? then throw new Error 'options.modSlug is required'
|
||||
if not options.tutorialSlug? then throw new Error 'options.tutorialSlug is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
options.model ?= null
|
||||
options.templateName = 'tutorial_page'
|
||||
super options
|
||||
|
||||
@modPack = options.modPack
|
||||
@imageLoader = options.imageLoader
|
||||
@modSlug = options.modSlug
|
||||
@tutorialSlug = options.tutorialSlug
|
||||
|
||||
@modPack.on Event.change, => @_resolveTutorial()
|
||||
@_resolveTutorial()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
|
||||
|
||||
@$byline = @$('.byline')
|
||||
@$bylineLink = @$('.byline a')
|
||||
@$name = @$('.name')
|
||||
@$officialLink = @$('a.officialPage')
|
||||
@$sectionsContainer = @$('.sections')
|
||||
@$title = @$('h1.name')
|
||||
@$titleImage = @$('.titleImage img')
|
||||
@$videosSection = @$('.videos')
|
||||
@$videosSectionTitle = @$('.videos h2')
|
||||
@$videosSectionPanel = @$('.videos .panel')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if @model? and @model.isLoaded
|
||||
@$el.removeClass 'hidden'
|
||||
else
|
||||
@$el.addClass 'hidden'
|
||||
|
||||
@_refreshByline()
|
||||
@_refreshOfficialUrl()
|
||||
@_refreshSections()
|
||||
@_refreshTitle()
|
||||
@_refreshVideos()
|
||||
super
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshByline: ->
|
||||
if @model?
|
||||
@$byline.removeClass 'hidden'
|
||||
@$bylineLink.html @modPack.getMod(@modSlug).name
|
||||
@$bylineLink.attr 'href', Url.mod modSlug:@modSlug
|
||||
else
|
||||
@$byline.addClass 'hidden'
|
||||
|
||||
_refreshOfficialUrl: ->
|
||||
if @model?.officialUrl?
|
||||
@$officialLink.attr 'href', @model.officialUrl
|
||||
@$officialLink.removeClass 'hidden'
|
||||
else
|
||||
@$officialLink.addClass 'hidden'
|
||||
|
||||
_refreshTitle: ->
|
||||
if @model?
|
||||
@$title.html @model.name
|
||||
@$titleImage.attr 'src', Url.tutorialIcon modSlug:@modSlug, tutorialSlug:@tutorialSlug
|
||||
else
|
||||
@$title.empty()
|
||||
@$titleImage.removeAttr 'src'
|
||||
|
||||
_refreshSections: ->
|
||||
@_sectionControllers ?= []
|
||||
index = 0
|
||||
|
||||
if @model?
|
||||
for section in @model.sections
|
||||
controller = @_sectionControllers[index]
|
||||
if not controller?
|
||||
controller = new MarkdownSectionController title:section.title, model:section.content
|
||||
controller.render()
|
||||
@$sectionsContainer.append controller.$el
|
||||
@_sectionControllers.push controller
|
||||
else
|
||||
controller.title = section.title
|
||||
controller.model = section.model
|
||||
controller.refresh()
|
||||
|
||||
index += 1
|
||||
|
||||
while @_sectionControllers.length > index
|
||||
controller = @_sectionController.pop()
|
||||
controller.$el.fadeOut duration:Duration.normal, complete:-> @remove()
|
||||
|
||||
_refreshVideos: ->
|
||||
@_videoControllers ?= []
|
||||
index = 0
|
||||
|
||||
videos = @model?.videos or []
|
||||
if videos? and videos.length > 0
|
||||
@$videosSection.slideDown duration:Duration.normal
|
||||
@$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos'
|
||||
|
||||
for video in videos
|
||||
controller = @_videoControllers[index]
|
||||
if not controller?
|
||||
controller = new VideoController model:video
|
||||
@_videoControllers.push controller
|
||||
controller.render()
|
||||
@$videosSectionPanel.append controller.$el
|
||||
else
|
||||
controller.model = video
|
||||
index++
|
||||
else
|
||||
@$videosSection.slideUp duration:Duration.normal
|
||||
|
||||
while @_videoControllers.length > index
|
||||
controller = @_videoControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
|
||||
|
||||
_resolveTutorial: ->
|
||||
return if @model?
|
||||
|
||||
mod = @modPack.getMod @modSlug
|
||||
if not mod?
|
||||
logger.error => "cannot find the mod for: #{@modSlug}"
|
||||
router.navigate '/', trigger:true
|
||||
return
|
||||
|
||||
if not mod.isLoaded
|
||||
mod.fetch()
|
||||
return
|
||||
|
||||
@model = mod.getTutorial @tutorialSlug
|
||||
if not @model?
|
||||
logger.error => "mod #{@modSlug} doesn't have a tutorial for: #{@tutorialSlug}"
|
||||
return
|
||||
|
||||
@model.fetch()
|
||||
@@ -16,6 +16,7 @@ ItemSlug = require './models/item_slug'
|
||||
Mod = require './models/mod'
|
||||
ModPack = require './models/mod_pack'
|
||||
ModPageController = require './controllers/mod_page_controller'
|
||||
TutorialPageController = require './controllers/tutorial_page_controller'
|
||||
Storage = require './models/storage'
|
||||
UrlParams = require './url_params'
|
||||
{ProductionEnvs} = require './constants'
|
||||
@@ -64,13 +65,14 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
||||
@_recordPageView()
|
||||
|
||||
routes:
|
||||
'(/)': 'route__home'
|
||||
'browse(/)': 'route__browse'
|
||||
'browse/:modSlug(/)': 'route__browseMod'
|
||||
'browse/:modSlug/:itemSlug(/)': 'route__browseModItem'
|
||||
'configure(/)': 'route__configure'
|
||||
'craft(/)': 'route__craft'
|
||||
'craft/:text': 'route__craft'
|
||||
'(/)': 'route__home'
|
||||
'browse(/)': 'route__browse'
|
||||
'browse/:modSlug(/)': 'route__browseMod'
|
||||
'browse/:modSlug/:itemSlug(/)': 'route__browseModItem'
|
||||
'browse/:modSlug/tutorials/:tutorialSlug(/)': 'route__browseTutorial'
|
||||
'configure(/)': 'route__configure'
|
||||
'craft(/)': 'route__craft'
|
||||
'craft/:text': 'route__craft'
|
||||
|
||||
'item/:itemSlug': 'deprecated__item'
|
||||
'crafting/(:text)': 'deprecated__crafting'
|
||||
@@ -100,6 +102,10 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
||||
controller = new ItemPageController _.extend {itemSlug:slug}, @_defaultOptions
|
||||
@_setPage 'browseModItem', controller
|
||||
|
||||
route__browseTutorial: (modSlug, tutorialSlug)->
|
||||
controller = new TutorialPageController _.extend {modSlug:modSlug, tutorialSlug:tutorialSlug}, @_defaultOptions
|
||||
@_setPage 'browseTutorial', controller
|
||||
|
||||
route__configure: ->
|
||||
@_setPage 'configure', new ConfigurePageController _.extend {}, @_defaultOptions
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = class ItemPage extends BaseModel
|
||||
|
||||
compileDescription: ->
|
||||
return null unless @item?.description?
|
||||
description = markdown.parse @item.description, 'Maruku'
|
||||
description = _.parseMarkdown @item.description
|
||||
return description
|
||||
|
||||
findComponentInItems: ->
|
||||
|
||||
@@ -16,6 +16,7 @@ module.exports = class Mod extends BaseModel
|
||||
|
||||
constructor: (attributes={}, options={})->
|
||||
if not attributes.slug? then throw new Error 'attributes.slug is required'
|
||||
|
||||
attributes.author ?= ''
|
||||
attributes.description ?= ''
|
||||
attributes.documentationUrl ?= null
|
||||
@@ -23,11 +24,13 @@ module.exports = class Mod extends BaseModel
|
||||
attributes.homePageUrl ?= null
|
||||
attributes.modPack ?= null
|
||||
attributes.name ?= ''
|
||||
|
||||
super attributes, options
|
||||
|
||||
@_activeModVersion = null
|
||||
@_activeVersion = null
|
||||
@_modVersions = []
|
||||
@_tutorials = []
|
||||
|
||||
Object.defineProperties this,
|
||||
'activeModVersion': { get:-> @_activeModVersion }
|
||||
@@ -107,6 +110,31 @@ module.exports = class Mod extends BaseModel
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getActiveVersion: ->
|
||||
return @_activeVersion
|
||||
|
||||
setActiveVersion: (version)->
|
||||
return if version is @_activeVersion
|
||||
|
||||
version ?= Mod.Version.None
|
||||
if version is Mod.Version.Latest then version = _.last(@_modVersions).version
|
||||
|
||||
if version is Mod.Version.None
|
||||
@_activeVersion = version
|
||||
@_activateModVersion null
|
||||
|
||||
@trigger Event.change + ':activeVersion', this, @_activeVersion
|
||||
@trigger Event.change, this
|
||||
else
|
||||
for modVersion in @_modVersions
|
||||
if version is modVersion.version
|
||||
@_activateModVersion modVersion
|
||||
break
|
||||
|
||||
@_activeVersion = version
|
||||
@trigger Event.change + ':activeVersion', this, @_activeVersion
|
||||
@trigger Event.change, this
|
||||
|
||||
addModVersion: (modVersion)->
|
||||
return unless modVersion?
|
||||
return if @_modVersions.indexOf(modVersion) isnt -1
|
||||
@@ -136,30 +164,22 @@ module.exports = class Mod extends BaseModel
|
||||
|
||||
return null
|
||||
|
||||
getActiveVersion: ->
|
||||
return @_activeVersion
|
||||
addTutorial: (tutorial)->
|
||||
return unless tutorial?
|
||||
if @getTutorial(tutorial.slug)? then throw new Error "duplicate tutorial: #{tutorial.name}"
|
||||
@_tutorials.push tutorial
|
||||
tutorial.modSlug = @slug
|
||||
|
||||
setActiveVersion: (version)->
|
||||
return if version is @_activeVersion
|
||||
getAllTutorials: ->
|
||||
return @_tutorials[..]
|
||||
|
||||
version ?= Mod.Version.None
|
||||
if version is Mod.Version.Latest then version = _.last(@_modVersions).version
|
||||
getTutorial: (tutorialSlug)->
|
||||
for tutorial in @_tutorials
|
||||
return tutorial if tutorial.slug is tutorialSlug
|
||||
return null
|
||||
|
||||
if version is Mod.Version.None
|
||||
@_activeVersion = version
|
||||
@_activateModVersion null
|
||||
|
||||
@trigger Event.change + ':activeVersion', this, @_activeVersion
|
||||
@trigger Event.change, this
|
||||
else
|
||||
for modVersion in @_modVersions
|
||||
if version is modVersion.version
|
||||
@_activateModVersion modVersion
|
||||
break
|
||||
|
||||
@_activeVersion = version
|
||||
@trigger Event.change + ':activeVersion', this, @_activeVersion
|
||||
@trigger Event.change, this
|
||||
Object.defineProperties @prototype,
|
||||
tutorials: { get:@prototype.getAllTutorials }
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ module.exports = class CommandParserVersionBase
|
||||
|
||||
shortestIndent = Number.MAX_VALUE
|
||||
for hereDocLine in hereDocLines
|
||||
continue if hereDocLine.trim().length is 0
|
||||
shortestIndent = Math.min hereDocLine.match(/( *).*/)[1].length, shortestIndent
|
||||
|
||||
for i in [0...hereDocLines.length]
|
||||
|
||||
@@ -8,6 +8,7 @@ All rights reserved.
|
||||
CommandParserVersionBase = require './command_parser_version_base'
|
||||
Mod = require '../mod'
|
||||
ModVersion = require '../mod_version'
|
||||
Tutorial = require '../tutorial'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -47,17 +48,23 @@ module.exports = class ModParserV1 extends CommandParserVersionBase
|
||||
if downloadUrl.length is 0 then throw new Error 'downloadUrl cannot be empty (omit it instead)'
|
||||
@_rawData.downloadUrl = downloadUrl
|
||||
|
||||
_command_name: (name)->
|
||||
if @_rawData.name? then throw new Error 'duplicate declaration of "name"'
|
||||
if name.length is 0 then throw new Error '"name" cannot be empty'
|
||||
@_rawData.name = name
|
||||
|
||||
_command_homePageUrl: (homePageUrl='')->
|
||||
if @_rawData.homePageUrl? then throw new Error 'duplicate declaration of "homePageUrl"'
|
||||
if homePageUrl.length is 0 then throw new Error 'homePageUrl cannot be empty'
|
||||
|
||||
@_rawData.homePageUrl = homePageUrl
|
||||
|
||||
_command_name: (name)->
|
||||
if @_rawData.name? then throw new Error 'duplicate declaration of "name"'
|
||||
if name.length is 0 then throw new Error '"name" cannot be empty'
|
||||
@_rawData.name = name
|
||||
|
||||
_command_tutorial: (nameParts...)->
|
||||
name = nameParts.join(', ').trim()
|
||||
if name.length is 0 then throw new Error '"name" cannot be empty'
|
||||
@_rawData.tutorialNames ?= []
|
||||
@_rawData.tutorialNames.push name
|
||||
|
||||
_command_version: (version='')->
|
||||
if version.length is 0 then throw new Error 'version cannot be empty'
|
||||
|
||||
@@ -78,5 +85,9 @@ module.exports = class ModParserV1 extends CommandParserVersionBase
|
||||
model.name = rawData.name
|
||||
model.homePageUrl = rawData.homePageUrl
|
||||
|
||||
if rawData.tutorialNames?
|
||||
for tutorialName in rawData.tutorialNames
|
||||
model.addTutorial new Tutorial name:tutorialName
|
||||
|
||||
for version in rawData.versions
|
||||
model.addModVersion new ModVersion modSlug:model.slug, version:version
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
###
|
||||
Crafting Guide - tutorial_parser_v1.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
CommandParserVersionBase = require './command_parser_version_base'
|
||||
Tutorial = require '../tutorial'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class TutorialParserV1 extends CommandParserVersionBase
|
||||
|
||||
# CommandParserVersionBase Overrides ###########################################################
|
||||
|
||||
_buildModel: (rawData, model)->
|
||||
@_buildTutorial rawData, model
|
||||
|
||||
_unparseModel: (builder, model)->
|
||||
@_unparseTutorial builder, model
|
||||
|
||||
# Command Methods ##############################################################################
|
||||
|
||||
_command_content: (contentParts...)->
|
||||
if not @_rawData.currentSection? then throw new Error 'cannot declare "title" before "section"'
|
||||
if @_rawData.currentSection.content? then throw new Error 'duplicate declaration of content'
|
||||
content = contentParts.join(', ').trim()
|
||||
if not content.length > 0 then throw new Error 'content cannot be empty'
|
||||
|
||||
@_rawData.currentSection.content = content
|
||||
|
||||
_command_officialUrl: (officialUrl)->
|
||||
if @_rawData.officialUrl? then throw new Error 'duplicate declaration of "officialUrl"'
|
||||
if officialUrl.length is 0 then throw new Error 'officialUrl cannot be empty'
|
||||
@_rawData.officialUrl = officialUrl
|
||||
|
||||
_command_section: (textParts...)->
|
||||
@_rawData.sections ?= []
|
||||
@_rawData.sections.push @_rawData.currentSection = {}
|
||||
|
||||
_command_title: (titleParts...)->
|
||||
if not @_rawData.currentSection? then throw new Error 'cannot declare "title" before "section"'
|
||||
if @_rawData.currentSection.title? then throw new Error 'duplicate declaration of title'
|
||||
title = titleParts.join(', ').trim()
|
||||
if not title.length > 0 then throw new Error 'title cannot be empty'
|
||||
|
||||
@_rawData.currentSection.title = title
|
||||
|
||||
_command_video: (youTubeId, nameParts...)->
|
||||
if not youTubeId?.length then throw new Error 'video declaration requires a YouTubeID'
|
||||
name = nameParts.join ', '
|
||||
if not name?.length then throw new Error 'video declaration requires a name'
|
||||
|
||||
@_rawData.videos ?= []
|
||||
@_rawData.videos.push youTubeId:youTubeId, name:name
|
||||
|
||||
# Object Building Methods ######################################################################
|
||||
|
||||
_buildTutorial: (rawData, model)->
|
||||
if not rawData.sections? then throw new Error 'the "section" declaration is required'
|
||||
|
||||
model.officialUrl = rawData.officialUrl
|
||||
model.videos = rawData.videos
|
||||
model.sections = rawData.sections
|
||||
@@ -0,0 +1,35 @@
|
||||
###
|
||||
Crafting Guide - tutorial.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseModel = require './base_model'
|
||||
TutorialParser = require './tutorial_parser'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class Tutorial extends BaseModel
|
||||
|
||||
constructor: (attributes={}, options={})->
|
||||
if not attributes.name?.length > 0 then throw new Error "attributes.name cannot be empty"
|
||||
attributes.modSlug ?= null
|
||||
attributes.officialUrl ?= null
|
||||
attributes.sections ?= []
|
||||
attributes.slug ?= _.slugify attributes.name
|
||||
attributes.videos ?= []
|
||||
super attributes, options
|
||||
|
||||
# Backbone.Model Overrides #####################################################################
|
||||
|
||||
parse: (text)->
|
||||
TutorialParser = require './tutorial_parser' # to avoid require cycles
|
||||
@_parser ?= new TutorialParser model:this
|
||||
@_parser.parse text
|
||||
|
||||
return null # prevent calling `set`
|
||||
|
||||
url: ->
|
||||
return Url.tutorialData modSlug:@modSlug, tutorialSlug:@slug
|
||||
@@ -0,0 +1,19 @@
|
||||
###
|
||||
Crafting Guide - tutorial_parser.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
VersionedParserBase = require './versioned_parser_base'
|
||||
TutorialParserV1 = require './parser_versions/tutorial_parser_v1'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class TutorialParser extends VersionedParserBase
|
||||
|
||||
# VersionedParserBase Overrides ################################################################
|
||||
|
||||
_createParsers: (options)->
|
||||
return result =
|
||||
'1': new TutorialParserV1 options
|
||||
@@ -40,9 +40,9 @@ describe 'command_parser_version_base.coffee', ->
|
||||
expect(result[1]).to.be.null
|
||||
|
||||
it 'trims smallest leading whitespace', ->
|
||||
parser._lines = ['command: <<-END', ' alpha', ' bravo', ' charlie', 'END', 'command1: arg2']
|
||||
parser._lines = ['command: <<-END', ' alpha', ' bravo', '', ' charlie', 'END', 'command1: arg2']
|
||||
parser._lineNumber = 1
|
||||
|
||||
result = parser._parseHereDoc parser._lines[0]
|
||||
result[0].should.equal 'command: '
|
||||
result[1].should.equal 'alpha\n bravo\ncharlie'
|
||||
result[1].should.equal 'alpha\n bravo\n\ncharlie'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
###
|
||||
Crafting Guide - underscore.coffee
|
||||
Crafting Guide - underscore_mixins.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
@@ -7,12 +7,15 @@ All rights reserved.
|
||||
|
||||
_.mixin
|
||||
|
||||
parseMarkdown: (text)->
|
||||
return markdown.parse text, 'Maruku'
|
||||
|
||||
slugify: (text)->
|
||||
return null unless text?
|
||||
|
||||
result = text.toLowerCase()
|
||||
result = result.replace /[^a-zA-Z0-9_]/g, '_'
|
||||
result = result.replace /__+/, '_'
|
||||
result = result.replace /__+/g, '_'
|
||||
result = result.replace /^_/, ''
|
||||
result = result.replace /_$/, ''
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//-
|
||||
//- Crafting Guide - markdown_section.jade
|
||||
//-
|
||||
//- Copyright (c) 2015 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.view__markdown_section.section
|
||||
h2
|
||||
.panel.markdown
|
||||
@@ -20,4 +20,8 @@
|
||||
.byline: p
|
||||
.description: p
|
||||
|
||||
.tutorials.section
|
||||
h2 Tutorials
|
||||
.panel
|
||||
|
||||
.itemGroups
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
//-
|
||||
//- Crafting Guide - tutorial.jade
|
||||
//-
|
||||
//- Copyright (c) 2015 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.view__tutorial
|
||||
a
|
||||
img
|
||||
.caption: p
|
||||
@@ -0,0 +1,23 @@
|
||||
//-
|
||||
//- Crafting Guide - tutorial_page.jade
|
||||
//-
|
||||
//- Copyright (c) 2015 by Redwood Labs
|
||||
//- All rights reserved.
|
||||
//-
|
||||
|
||||
.view__tutorial_page
|
||||
.sidebar
|
||||
.titleImage: a: img
|
||||
a.officialPage.externalLink(target="new"): p Offical Documentation
|
||||
|
||||
.view__adsense
|
||||
|
||||
.mainBody
|
||||
h1.name
|
||||
.byline: p from <a></a>
|
||||
|
||||
.sections
|
||||
|
||||
.videos.section
|
||||
h2
|
||||
.panel
|
||||
+32
-9
@@ -5,6 +5,16 @@ Copyright (C) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
.byline {
|
||||
margin: 0.25em 0 2em 0;
|
||||
|
||||
p {
|
||||
font-family: $font-family-normal;
|
||||
font-size: $font-size-normal;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -22,6 +32,20 @@ All rights reserved.
|
||||
|
||||
.error-new { background: $color-error-new !important; }
|
||||
|
||||
.hidden {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mainBody {
|
||||
position: relative; width: 81.25%;
|
||||
|
||||
display: inline-block;
|
||||
padding: 1em;
|
||||
padding-top: 2em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: relative; width: 18.75%;
|
||||
|
||||
@@ -53,15 +77,6 @@ All rights reserved.
|
||||
}
|
||||
}
|
||||
|
||||
.mainBody {
|
||||
position: relative; width: 81.25%;
|
||||
|
||||
display: inline-block;
|
||||
padding: 1em;
|
||||
padding-top: 2em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 3em;
|
||||
|
||||
@@ -86,4 +101,12 @@ All rights reserved.
|
||||
background: white;
|
||||
padding: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.videos {
|
||||
display: none;
|
||||
|
||||
.panel {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,19 @@ All rights reserved.
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
margin: 2em 2em 0 2em;
|
||||
|
||||
li {
|
||||
font-family: $font-family-normal;
|
||||
font-size: $font-size-normal;
|
||||
line-height: $font-size-normal + 0.15em;
|
||||
list-style: decimal;
|
||||
margin: 0.66em 0 0 2em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ul {
|
||||
margin: 2em 2em 0 2em;
|
||||
|
||||
|
||||
@@ -48,6 +48,12 @@ h1 {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-xx-large;
|
||||
}
|
||||
|
||||
&.name {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-x-large;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
|
||||
@@ -23,4 +23,5 @@ All rights reserved.
|
||||
@import 'mod_page';
|
||||
@import 'mod_selector';
|
||||
@import 'stack';
|
||||
@import 'tutorial';
|
||||
@import 'video';
|
||||
|
||||
@@ -24,22 +24,6 @@ All rights reserved.
|
||||
}
|
||||
|
||||
.mainBody {
|
||||
h1.name {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-x-large;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.byline {
|
||||
display: none;
|
||||
margin: 0.25em 0 2em 0;
|
||||
|
||||
p {
|
||||
font-family: $font-family-normal;
|
||||
font-size: $font-size-normal;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.recipes {
|
||||
display: none;
|
||||
@@ -61,14 +45,6 @@ All rights reserved.
|
||||
.usedToMake {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.videos {
|
||||
display: none;
|
||||
|
||||
.panel {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view__item {
|
||||
|
||||
@@ -23,22 +23,6 @@ All rights reserved.
|
||||
|
||||
.mainBody {
|
||||
|
||||
.name {
|
||||
font-family: $font-family-header;
|
||||
font-size: $font-size-x-large;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.byline {
|
||||
margin: 0.25em 0 2em 0;
|
||||
|
||||
p {
|
||||
font-family: $font-family-normal;
|
||||
font-size: $font-size-normal;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-bottom: 4em;
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Crafting Guide - tutorial.scss
|
||||
|
||||
Copyright (C) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
.view__tutorial {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
vertical-align: top;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.caption {
|
||||
position: relative; width: 100%;
|
||||
display: block;
|
||||
|
||||
p {
|
||||
margin-top: 0.5em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 378 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,107 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<title>The Ultimate Minecraft Crafting Guide</title>
|
||||
<meta charset="UTF-8">
|
||||
<link href="/images/favicon.png" rel="icon" type="image/png">
|
||||
<link rel="stylesheet" type="text/css" href="/css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/jquery-ui.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="view__feedback" style="left: -250px; "><input name="name" placeholder="name (optional)"><input name="email" placeholder="email (optional)"><label name="comment">Comment:</label><textarea name="comment"></textarea><button name="send" disabled="disabled">send</button><div class="error"><p>Sending failed. Please try again later.</p></div><div class="label"><img src="/images/paper.png"><p>Feedback</p></div></div>
|
||||
<div class="view__screen"></div>
|
||||
<div class="content">
|
||||
<div class="view__header">
|
||||
<h1><a href="/" class="logo"><img src="/images/workbench_front.png"></a>
|
||||
<p>Crafting Guide for Minecraft</p>
|
||||
</h1>
|
||||
<div class="addthis_sharing_toolbox"></div>
|
||||
<div class="divider bottom"></div>
|
||||
<div class="navBar"><a data-page="home" href="/" style="z-index: 104; ">
|
||||
<p>Home</p>
|
||||
<div class="dot" style="opacity: 0; "></div></a><a data-page="configure" href="/configure/" style="z-index: 103; ">
|
||||
<p>Configure</p>
|
||||
<div class="dot" style="opacity: 0; "></div></a><a data-page="browse" href="/browse/" style="z-index: 102; ">
|
||||
<p>Browse</p>
|
||||
<div class="dot" style="opacity: 1; "></div></a><a data-page="craft" href="/craft/" style="z-index: 101; ">
|
||||
<p>Craft</p>
|
||||
<div class="dot" style="opacity: 0; "></div></a></div>
|
||||
</div>
|
||||
<div class="view__tutorial_page page" style=""><div class="sidebar"><div class="titleImage"><a><img src="/browse/buildcraft/tutorials/gates_wires_and_chips/icon.png"></a></div><a target="new" class="officialPage externalLink hidden"><p>Offical Documentation</p></a><div class="view__adsense placeholder sidebar_skyscraper"></div></div><div class="mainBody"><h1 class="name">Gates, Wires, and Chips</h1><div class="byline"><p>from <a href="/browse/buildcraft/">Buildcraft</a></p></div><div class="sections"><div class="view__markdown_section section"><h2>What do gates do?</h2><div class="panel markdown"><p>BuildCraft gates are devices which can be attached to a pipe to detect and interact with objects nearby. Gates
|
||||
can read a wide variety of conditions: that a nearby chest is full, or that a <a href="/browse/buildcraft/combustion_engine">Combustion
|
||||
Engine</a> is about to overheat. In reaction to these conditions, gates can
|
||||
emit various kinds of signals (including redstone signals) to control other gates and/or machines.</p></div></div><div class="view__markdown_section section"><h2>An Example: Controlling Engines</h2><div class="panel markdown"><p>Before diving into all the details, let's look at a realistic example of what you might do with gates. This is a
|
||||
small power plant driving a quarry.</p>
|
||||
|
||||
<p><img alt="" src="./example_1_overview.png"></p>
|
||||
|
||||
<p>Here are the important pieces of the build:</p>
|
||||
|
||||
<ol><li>The on/off switch for the entire operation. Flipping the switch creates a redstone signal.</li><li>A <a href="/browse/buildcraft/basic_gate/">Basic Gate</a> attached to a <a href="/browse/buildcraft/structure_pipe">Structure Pipe</a> reads the redstone signal and generates a red pipe wire signal.</li><li><a href="/browse/buildcraft/red_pipe_wire">Red Pipe Wire</a> follows the <a href="/browse/buildcraft/cobblestone_kinesis_pipe">Cobblestone Kinesis Pipe</a>, transmitting the signal throughout the rest of the build.</li><li>Another Basic Gate receives the red pipe wire signal and converts it back to a redstone signal, thus turning
|
||||
the <a href="/browse/buildcraft/combustion_engine">Combustion Engine</a>s on.</li><li>The red pipe wire signal is also received by Basic Gates next to the <a href="/browse/buildcraft/redstone_engine">Redstone
|
||||
Engine</a>s, turning them on as well, and causing both fuel and water to
|
||||
flow into the engines.</li><li>Finally, the power generated by the Combusion Engines flows into the <a href="/browse/buildcraft/quarry/">Quarry</a>.</li></ol></div></div></div><div class="videos section" style="display: block; "><h2>Video</h2><div class="panel"><div class="view__video"><iframe width="365" height="273" src="http://www.youtube.com/embed/J6-VUApZGQs?modestbranding=1&autohide=1&showinfo=0" frameborder="0" allowfullscreen="true"></iframe><div class="caption"><p>Buildcraft Gates Tutorial, Part 1</p></div></div></div></div></div></div>
|
||||
<div class="view__footer">
|
||||
<div class="divider top"></div>
|
||||
<div class="left">
|
||||
<h2>
|
||||
<p>About</p>
|
||||
</h2>
|
||||
<p>
|
||||
Crafting Guide gives step-by-step tutorials for making anything in Minecraft or its many mods. Just say what
|
||||
you'd like to make, what you already have, it will do the rest, giving you a list of raw materials you need
|
||||
to collect and step-by-step instructions of how much to make of which items in the proper order. You can
|
||||
even ask it to include the materials and instructions for all the tools you'll need along the way!
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="center">
|
||||
<h2>
|
||||
<p>Donate</p>
|
||||
</h2>
|
||||
<p>Crafting Guide is free for all, but if you find it helpful, donations in any amount are gratefully accepted.</p>
|
||||
<div class="action">
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top" class="centered">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
<input type="hidden" name="hosted_button_id" value="GCB2TYZJYLAE6">
|
||||
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"><img src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h2>
|
||||
<p>Get Involved</p>
|
||||
</h2>
|
||||
<p>
|
||||
Crafting Guide is completely open-source, and you can help! Whether you want to write a recipe book (all
|
||||
simple JSON), or implement new features, just head over to GitHub to get started.
|
||||
</p>
|
||||
<div class="action">
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=andrewminer&repo=crafting-guide&type=fork&size=large" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="32"></iframe>
|
||||
</div>
|
||||
</div><a href="/test.html" rel="nofollow">
|
||||
<div class="divider bottom"></div></a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/underscore.js"></script>
|
||||
<script src="/js/jquery.js"></script>
|
||||
<script src="/js/backbone.js"></script>
|
||||
<script src="/js/jade.js"></script>
|
||||
<script src="/js/markdown.js"></script>
|
||||
<script src="/js/when.js"></script>
|
||||
<script src="/js/jquery-ui.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<script>
|
||||
if (window.location.hostname === 'crafting-guide.com') {
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-54970416-2', 'crafting-guide.com');
|
||||
ga('require', 'displayfeatures');
|
||||
ga('require', 'linkid', 'linkid.js');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
||||
@@ -8,3 +8,5 @@ documentationUrl: http://www.mod-buildcraft.com/wiki/doku.php
|
||||
downloadUrl: http://www.mod-buildcraft.com/download/
|
||||
|
||||
version: 6.2.6
|
||||
|
||||
tutorial: Gates, Wires, and Chips
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
schema: 1
|
||||
|
||||
section:
|
||||
title: What do gates do?
|
||||
content: <<-END
|
||||
BuildCraft gates are devices which can be attached to a pipe to detect and interact with objects nearby. Gates
|
||||
can read a wide variety of conditions: that a nearby chest is full, or that a [Combustion
|
||||
Engine](/browse/buildcraft/combustion_engine) is about to overheat. In reaction to these conditions, gates can
|
||||
emit various kinds of signals (including redstone signals) to control other gates and/or machines.
|
||||
END
|
||||
|
||||
section:
|
||||
title: An Example: Controlling Engines
|
||||
content: <<-END
|
||||
Before diving into all the details, let's look at a realistic example of what you might do with gates. This is a
|
||||
small power plant driving a quarry.
|
||||
|
||||

|
||||
|
||||
Here are the important pieces of the build:
|
||||
|
||||
1. The on/off switch for the entire operation. Flipping the switch creates a redstone signal.
|
||||
2. A [Basic Gate](/browse/buildcraft/basic_gate/) attached to a [Structure Pipe]
|
||||
(/browse/buildcraft/structure_pipe) reads the redstone signal and generates a red pipe wire signal.
|
||||
3. [Red Pipe Wire](/browse/buildcraft/red_pipe_wire) follows the [Cobblestone Kinesis Pipe]
|
||||
(/browse/buildcraft/cobblestone_kinesis_pipe), transmitting the signal throughout the rest of the build.
|
||||
4. Another Basic Gate receives the red pipe wire signal and converts it back to a redstone signal, thus turning
|
||||
the [Combustion Engine](/browse/buildcraft/combustion_engine)s on.
|
||||
5. The red pipe wire signal is also received by Basic Gates next to the [Redstone
|
||||
Engine](/browse/buildcraft/redstone_engine)s, turning them on as well, and causing both fuel and water to
|
||||
flow into the engines.
|
||||
6. Finally, the power generated by the Combusion Engines flows into the [Quarry](/browse/buildcraft/quarry/).
|
||||
END
|
||||
|
||||
video: J6-VUApZGQs, Buildcraft Gates Tutorial, Part 1
|
||||
@@ -13,6 +13,7 @@ http://crafting-guide.com/browse/minecraft/
|
||||
http://crafting-guide.com/browse/railcraft/
|
||||
http://crafting-guide.com/browse/thermal_dynamics/
|
||||
http://crafting-guide.com/browse/thermal_expansion/
|
||||
http://crafting-guide.com/browse/buildcraft/tutorials/gates_wires_and_chips/
|
||||
http://crafting-guide.com/browse/applied_energistics_2/128_spatial_component/
|
||||
http://crafting-guide.com/browse/applied_energistics_2/128_spatial_storage_cell/
|
||||
http://crafting-guide.com/browse/applied_energistics_2/16_spatial_component/
|
||||
|
||||
Reference in New Issue
Block a user