Skip to content

Commit

Permalink
Item + localization
Browse files Browse the repository at this point in the history
Wrapped up adding a item and commented everything.
  • Loading branch information
Oskar Edholm committed Mar 18, 2017
1 parent b374e57 commit 30b238e
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 8 deletions.
37 changes: 35 additions & 2 deletions common/net/oskyedz/stickyNote/init/ModItems.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,58 @@
import net.oskyedz.stickyNote.item.ItemStickyNote;
import net.oskyedz.stickyNote.lib.Names;

/**
* This is where we handle Item registration. Typically, you should also store references to your items for quick
* access. Note there are two initialization methods here, init (common, both client and server) and initClient
* (client-side only).
*/

public class ModItems {

/*
* Item references for easy access.
*/

public static ItemStickyNote stickyNoteItem;

/**
* The common initializer. Registers items, but not models. The game will crash if we try to do anything with models
* on the server, as those classes don't even exist on that side!
*
* This should be called during preInit.
*/

public static void init() {

// Initialize the item and store the reference.
stickyNoteItem = new ItemStickyNote();
// Setting the registry name is how Forge tells items apart.
stickyNoteItem.setRegistryName(new ResourceLocation(stickyNote.MOD_ID, Names.STICKY_NOTE));
// Finally, register the item! Must be done AFTER setting the registry name.
GameRegistry.register(stickyNoteItem);

}

/**
* The client-side initializer. Here we handle model registration. Note the @SideOnly annotation. This causes the method
* to exist only on the client-side, preventing servers from crashing.
*
* This should be called during init, calling during preInit will crash.
*/

@SideOnly(Side.CLIENT)
public static void initClient(ItemModelMesher mesher) {

ModelResourceLocation model = new ModelResourceLocation(stickyNote.RESOURCEPREFIX + Names.STICKY_NOTE, "inventory");
// Create a MRL for the model. Note we have two parameters and the second must be "inventory". We can reuse this
// variable for each item of course, since most Java variables just contain a reference to an object.
ModelResourceLocation model = new ModelResourceLocation(
stickyNote.RESOURCEPREFIX + Names.STICKY_NOTE, "inventory");
// Here we list all models the item can possibly have. An array will work, or just list each MRL for the final
// parameters.
ModelLoader.registerItemVariants(stickyNoteItem, model);
// Finally, we associate each MRL (model) with different metadata values for the item. This must be called for each
// variant! And even if the variants don't depend on metadata.
mesher.register(stickyNoteItem, 0, model);

}

}
18 changes: 16 additions & 2 deletions common/net/oskyedz/stickyNote/item/ItemStickyNote.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.oskyedz.stickyNote.item;

import scala.swing.TextComponent;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
Expand All @@ -11,21 +10,36 @@
import net.oskyedz.stickyNote.stickyNote;
import net.oskyedz.stickyNote.lib.Names;

/**
* A very basic item with no subtypes/variants
*/

public class ItemStickyNote extends Item {

/**
* Called when the item is right-clicked. By overriding this method, we can changed the behavior of the item! Note
* the @Override annotation. You should use these EVERY TIME you override a method. If the method signatures change
* between Minecraft versions (and that happens fairly often), you will get a compiler error. This makes porting much,
* much easier! Otherwise, you'll have a hard time figuring out why certain methods suddenly aren't being called.
*/

@Override

public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) {

if (!worldIn.isRemote) //send message from server
playerIn.sendMessage(new TextComponentString("You used my item!"));
return super.onItemRightClick(worldIn, playerIn, handIn);

}

/**
* Returns the unlocalized the name for the item. Make sure to add a corresponding line to your localization file!
*/
@Override
public String getUnlocalizedName(ItemStack stack) {

return "item." + stickyNote.RESOURCEPREFIX + Names.STICKY_NOTE; // item.stickyNote:sticky_note
return "item." + stickyNote.RESOURCEPREFIX + Names.STICKY_NOTE; // item.stickyNote:stickynote_item

}

Expand Down
7 changes: 6 additions & 1 deletion common/net/oskyedz/stickyNote/lib/Names.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package net.oskyedz.stickyNote.lib;

/**
* Used to store String constants for names of things, like blocks and items. Don't hardcode the names. That opens the possibility of
* making a mistake in one place... And if your names don't line up, things will break!
*/

public class Names {

/*
* Items
*/

public static final String STICKY_NOTE = "sticky_note"; //Only for demonstration purposes. Has to be lower case, can have e underscore.
public static final String STICKY_NOTE = "stickynote_item"; //Only for demonstration purposes. Has to be lower case, can have e underscore.

}
3 changes: 3 additions & 0 deletions resources/assets/stickynote/lang/en_US.lang
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
< en_US.lang - English localization file for the mod StickyNote >

item.stickynote:stickynote_item.name=Sticky Note
3 changes: 3 additions & 0 deletions resources/assets/stickynote/lang/sv_SE.lang
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
< sv_SE.lang - Swedish localization file for the mod StickyNote >

item.stickynote:stickynote_item.name=Fästisar
7 changes: 7 additions & 0 deletions resources/assets/stickynote/models/item/stickynote_item.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "stickynote:items/stickynote_item"
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions resources/mcmod.info
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
"version": "${version}",
"mcversion": "${mcversion}",
"url": "https://github.com/AMinecraftplayer/stickyNote-1.11.2",
"authors": [ "OskyEdz" ],
"credits": "Thanks SilentChaos512, for making a awesome Youtube-tutorial! Thanks to the Forge team for all their hard work!",
"logoFile": "",
"updateUrl": "Currently not working :(",
"authorList": [ "OskyEdz" ],
"credits": "Thanks SilentChaos512, for making a awesome Youtube-tutorial! Thanks to the Forge team and the FML guys for all their hard work!",
"logoFile": "/sticky_note.png",
"screenshots": [],
"dependencies": []
}
]
Binary file added resources/sticky_note.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
195 changes: 195 additions & 0 deletions scripts/makeJSON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
"""Somewhat simple Minecraft model JSON generator written in Python.
Modified to use Forge blockstate JSONs. Fully supports blocks with variants.
Usage: python makejson.py [block|item] filename [subtypeCount] [otherOptions]
Other options (type "option=value"):
layer -- The layer the texture will be on (lower layers will get a texture called "blank")
texture -- The name of the texture to use. Default is the same as the file name.
type -- The parent model for items. Default is "generated" and should not be changed in most cases.
Examples:
python makejson.py item gem 16
python makejson.py item myitem texture=mytexture
python makejson.py block the_block texture=derp_face
"""

import sys
import re
import os

# Your mod ID. Should be all lowercase letters and underscores, nothing else. This absolutely must match your mod ID!
MOD_ID = 'stickynote'
# The directories to write the files to. I let the script write to an output directory, then copy
# the files to my resources folder when I'm happy with the results. You could change this to output
# directly to your resources folder, but I would not recommend it.
DIR_OUTPUT_BLOCKSTATES = 'output/blockstates/'
DIR_OUTPUT_BLOCKS = 'output/models/block/'
DIR_OUTPUT_ITEMS = 'output/models/item/'

def createDirIfNeeded(name):
"""Create a directory if it does not exist."""
if not os.path.exists(name):
os.makedirs(name)

def createAllDirs():
"""Create all directories we may need."""
createDirIfNeeded(DIR_OUTPUT_BLOCKSTATES)
createDirIfNeeded(DIR_OUTPUT_BLOCKS)
createDirIfNeeded(DIR_OUTPUT_ITEMS)

def writeBlockJSON(name, texture, variantKey, variantValues):
"""Creates a Forge blockstate JSON for the block.
Arguments:
name -- The name to give the files (.json is automatically appended)
texture -- The name of the texture to use.
variantKey -- The name for the variants.
variantValues -- The values of the variants
"""
print('Writing block %s (texture %s)' % (name, texture))

list = []
list.append('{')
list.append(' "forge_marker": 1,')
list.append(' "defaults": {')
list.append(' "model": "cube_all",')
list.append(' "transform": "forge:default-block"')
list.append(' },')
list.append(' "variants": {')
list.append(' "inventory": [{')
# The "inventory" variant is for blocks without subtypes
# We could include this is blocks with subtypes, but would likely get missing texture errors.
if not variantKey or len(variantValues) == 0:
list.append(' "textures": {')
list.append(' "all": "%s:blocks/%s"' % (MOD_ID, texture))
list.append(' }')
list.append(' }]' + (',' if len(variantValues) > 0 else ''))

if variantKey and len(variantValues) > 0:
list.append(' "%s": {' % variantKey)
index = 0 # Optionally could use index in the texture name (Gems does this, for example)
for value in variantValues:
list.append(' "%s": {' % value)
list.append(' "textures": {')
list.append(' "all": "%s:blocks/%s_%s"' % (MOD_ID, texture, value))
list.append(' }')
list.append(' }' + (',' if value != variantValues[-1] else ''))
index += 1
list.append(' }')

list.append(' }')
list.append('}')

f = open(DIR_OUTPUT_BLOCKSTATES + name + '.json', 'w')
for line in list:
f.write(line + '\n')
f.close()

def writeItemJSON(name, texture, layer=0, item_type='generated'):
"""Creates the JSON file needed for an item. Multi-layer models can be
created, but the textures for all but the highest layer cannot be named. In
those cases, you will need to either modify the files yourself, or modify
this script to fit your needs.
Arguments:
name -- The name to give the file (.json is automatically appended)
texture -- The name of the texture to use. Only the highest layer can be named.
layer -- The index of the highest layer (layers start at 0)
item_type -- The 'parent' model for the item.
"""
print('Writing item %s (texture %s)' % (name, texture))

f = open(DIR_OUTPUT_ITEMS + name + '.json', 'w')
f.write('{\n')
f.write(' "parent": "item/%s",\n' % item_type)
f.write(' "textures": {\n')
for i in range(0, layer):
f.write(' "layer%d": "%s:items/Blank",\n' % (i, MOD_ID))
f.write(' "layer%d": "%s:items/%s"\n' % (layer, MOD_ID, texture))
f.write(' }\n')
f.write('}\n')
f.write('\n')
f.close()



# regex to match numbers
numRegex = re.compile("^\d+$")

# Blocks require 3 files to be created, items only need 1.
isBlock = False
# Name for the file(s) being created
name = ''
# The texture name. Typically the same as name, but a different value can be specified.
texture = ''
# The number of subtypes. If greater than 1, it will create files like name0, name1, etc.
count = 1
# The layer the texture should be on. If greater than 0, lower layers will be given a texture called "blank".
# If you need to use this for any reason (unlikely) create a fully transparent item texture and name it "blank".
# This is only for items.
layer = 0
# The "parent" for items. Typically you want "generated".
type = 'generated'
variantKey = ''
variantValues = []



# read command line arguments
for arg in sys.argv:
# lowercase argument for matching purposes
argl = str.lower(arg)
matchNum = numRegex.match(arg)
# try to match some optional arguments
matchCount = re.compile('count=').match(argl)
matchLayer = re.compile('layer=').match(argl)
matchTexture = re.compile('texture=').match(argl)
matchType = re.compile('type=').match(argl)
matchVariantKey = re.compile('variant_?key=').match(argl)
matchVariantValues = re.compile('variant_?values?=').match(argl)

# Block or item? Default is item.
if argl == 'block':
isBlock = True
elif argl == 'item':
isBlock = False

if matchNum or matchCount: # subtype count
count = int(matchNum.group(0))
elif matchLayer: # layer index
layer = int(re.search('\d+', argl).group(0))
elif matchTexture: # texture name
texture = re.sub('texture=', '', arg)
elif matchType: # item parent model
type = re.sub('type=', '', arg)
elif matchVariantKey:
variantKey = re.sub('variant_?key=', '', argl)
elif matchVariantValues:
variantValues = re.sub('variant_?values?=', '', argl).split(',')
elif arg != 'makejson.py':
name = arg

if name == '': # name must be provided in command line!
print('No block/item name specified!')
exit(1)
if texture == '': # if no texture specified, use file name
texture = name
if count < 1: # just in case user does something silly...
count = 1

# create the output directories...
createAllDirs()

for i in range(count):
filename = name
textureName = texture
# if we have subtypes, append the index
if count > 1:
filename += str(i)
textureName += str(i)
# write the file(s)!
if isBlock:
writeBlockJSON(filename, textureName, variantKey, variantValues)
else:
writeItemJSON(filename, textureName, layer, type)
7 changes: 7 additions & 0 deletions scripts/output/models/item/stickynote_item.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "stickynote:items/stickynote_item"
}
}

0 comments on commit 30b238e

Please sign in to comment.