code:
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		8433696F1F1D888E00840DA9 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8433696E1F1D888E00840DA9 /* OpenGL.framework */; };
		843369711F1D889C00840DA9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 843369701F1D889C00840DA9 /* Cocoa.framework */; };
		843369731F1D88A000840DA9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 843369721F1D88A000840DA9 /* IOKit.framework */; };
		843369751F1D88A800840DA9 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 843369741F1D88A800840DA9 /* CoreVideo.framework */; };
		8437F8981F2F540300E89305 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433694E1F1D885F00840DA9 /* main.cpp */; };
		8437F89A1F2F543400E89305 /* StringUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8437F8991F2F543400E89305 /* StringUtils.cpp */; };
		8437F89C1F2F54B600E89305 /* HTTPRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369501F1D885F00840DA9 /* HTTPRequest.cpp */; };
		8437F89D1F2F54B900E89305 /* HTTPResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369521F1D885F00840DA9 /* HTTPResponse.cpp */; };
		8437F89E1F2F54BE00E89305 /* WebResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843C30E71F2F5110006F00B3 /* WebResource.cpp */; };
		8437F89F1F2F552500E89305 /* AnimeComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369151F1D885F00840DA9 /* AnimeComponent.cpp */; };
		8437F8A01F2F552900E89305 /* BoxComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369171F1D885F00840DA9 /* BoxComponent.cpp */; };
		8437F8A11F2F552C00E89305 /* Component.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369191F1D885F00840DA9 /* Component.cpp */; };
		8437F8A21F2F552E00E89305 /* ComponentBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433691B1F1D885F00840DA9 /* ComponentBuilder.cpp */; };
		8437F8A31F2F553100E89305 /* TextComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433691D1F1D885F00840DA9 /* TextComponent.cpp */; };
		8437F8A41F2F555600E89305 /* DIVElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 849C756A1F2BF9580082827A /* DIVElement.cpp */; };
		8437F8A51F2F555600E89305 /* Element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 849C756C1F2BF9580082827A /* Element.cpp */; };
		8437F8A61F2F555600E89305 /* STRONGElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 849C756E1F2BF9580082827A /* STRONGElement.cpp */; };
		8437F8A71F2F555600E89305 /* AElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369201F1D885F00840DA9 /* AElement.cpp */; };
		8437F8A81F2F555600E89305 /* BLOCKQUOTEElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369221F1D885F00840DA9 /* BLOCKQUOTEElement.cpp */; };
		8437F8A91F2F555600E89305 /* H1Element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369261F1D885F00840DA9 /* H1Element.cpp */; };
		8437F8AA1F2F555600E89305 /* H2Element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369281F1D885F00840DA9 /* H2Element.cpp */; };
		8437F8AB1F2F555600E89305 /* H3Element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433692A1F1D885F00840DA9 /* H3Element.cpp */; };
		8437F8AC1F2F555600E89305 /* LIElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433692C1F1D885F00840DA9 /* LIElement.cpp */; };
		8437F8AD1F2F555600E89305 /* PElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433692E1F1D885F00840DA9 /* PElement.cpp */; };
		8437F8AE1F2F555600E89305 /* SPANElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369321F1D885F00840DA9 /* SPANElement.cpp */; };
		8437F8AF1F2F555600E89305 /* Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433693E1F1D885F00840DA9 /* Window.cpp */; };
		8437F8B01F2F555600E89305 /* TextRasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369411F1D885F00840DA9 /* TextRasterizer.cpp */; };
		8437F8B11F2F555600E89305 /* TextRasterizerCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369431F1D885F00840DA9 /* TextRasterizerCache.cpp */; };
		8437F8B21F2F555600E89305 /* HTMLParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369461F1D885F00840DA9 /* HTMLParser.cpp */; };
		8437F8B31F2F555600E89305 /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843369481F1D885F00840DA9 /* Node.cpp */; };
		8437F8B41F2F555600E89305 /* TagNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433694A1F1D885F00840DA9 /* TagNode.cpp */; };
		8437F8B51F2F555600E89305 /* TextNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8433694C1F1D885F00840DA9 /* TextNode.cpp */; };
		844925051F1D94ED007E8644 /* DejaVuSerif-Bold.ttf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B6602B1F1D8DF000AEFBEC /* DejaVuSerif-Bold.ttf */; };
		844925061F1D94EF007E8644 /* DejaVuSerif.ttf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 844925041F1D9478007E8644 /* DejaVuSerif.ttf */; };
		846965401F32A9EF00980986 /* BrowsingHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 846965391F32A9EF00980986 /* BrowsingHistory.cpp */; };
		846965411F32A9EF00980986 /* CommandLineParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8469653B1F32A9EF00980986 /* CommandLineParams.cpp */; };
		846965421F32A9EF00980986 /* Log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8469653D1F32A9EF00980986 /* Log.cpp */; };
		846965431F32A9EF00980986 /* URL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8469653E1F32A9EF00980986 /* URL.cpp */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		843369061F1D881B00840DA9 /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 12;
			dstPath = "";
			dstSubfolderSpec = 6;
			files = (
				844925051F1D94ED007E8644 /* DejaVuSerif-Bold.ttf in CopyFiles */,
				844925061F1D94EF007E8644 /* DejaVuSerif.ttf in CopyFiles */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		843369081F1D881B00840DA9 /* Saltasaurus */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Saltasaurus; sourceTree = BUILT_PRODUCTS_DIR; };
		843369151F1D885F00840DA9 /* AnimeComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimeComponent.cpp; sourceTree = "<group>"; };
		843369161F1D885F00840DA9 /* AnimeComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimeComponent.h; sourceTree = "<group>"; };
		843369171F1D885F00840DA9 /* BoxComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BoxComponent.cpp; sourceTree = "<group>"; };
		843369181F1D885F00840DA9 /* BoxComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoxComponent.h; sourceTree = "<group>"; };
		843369191F1D885F00840DA9 /* Component.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Component.cpp; sourceTree = "<group>"; };
		8433691A1F1D885F00840DA9 /* Component.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Component.h; sourceTree = "<group>"; };
		8433691B1F1D885F00840DA9 /* ComponentBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComponentBuilder.cpp; sourceTree = "<group>"; };
		8433691C1F1D885F00840DA9 /* ComponentBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComponentBuilder.h; sourceTree = "<group>"; };
		8433691D1F1D885F00840DA9 /* TextComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextComponent.cpp; sourceTree = "<group>"; };
		8433691E1F1D885F00840DA9 /* TextComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextComponent.h; sourceTree = "<group>"; };
		843369201F1D885F00840DA9 /* AElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AElement.cpp; sourceTree = "<group>"; };
		843369211F1D885F00840DA9 /* AElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AElement.h; sourceTree = "<group>"; };
		843369221F1D885F00840DA9 /* BLOCKQUOTEElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BLOCKQUOTEElement.cpp; sourceTree = "<group>"; };
		843369231F1D885F00840DA9 /* BLOCKQUOTEElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLOCKQUOTEElement.h; sourceTree = "<group>"; };
		843369261F1D885F00840DA9 /* H1Element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = H1Element.cpp; sourceTree = "<group>"; };
		843369271F1D885F00840DA9 /* H1Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = H1Element.h; sourceTree = "<group>"; };
		843369281F1D885F00840DA9 /* H2Element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = H2Element.cpp; sourceTree = "<group>"; };
		843369291F1D885F00840DA9 /* H2Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = H2Element.h; sourceTree = "<group>"; };
		8433692A1F1D885F00840DA9 /* H3Element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = H3Element.cpp; sourceTree = "<group>"; };
		8433692B1F1D885F00840DA9 /* H3Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = H3Element.h; sourceTree = "<group>"; };
		8433692C1F1D885F00840DA9 /* LIElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LIElement.cpp; sourceTree = "<group>"; };
		8433692D1F1D885F00840DA9 /* LIElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LIElement.h; sourceTree = "<group>"; };
		8433692E1F1D885F00840DA9 /* PElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PElement.cpp; sourceTree = "<group>"; };
		8433692F1F1D885F00840DA9 /* PElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PElement.h; sourceTree = "<group>"; };
		843369321F1D885F00840DA9 /* SPANElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SPANElement.cpp; sourceTree = "<group>"; };
		843369331F1D885F00840DA9 /* SPANElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPANElement.h; sourceTree = "<group>"; };
		843369361F1D885F00840DA9 /* FontShader.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = FontShader.frag; sourceTree = "<group>"; };
		843369371F1D885F00840DA9 /* FontShader.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = FontShader.vert; sourceTree = "<group>"; };
		843369391F1D885F00840DA9 /* FontShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontShader.h; sourceTree = "<group>"; };
		8433693A1F1D885F00840DA9 /* hashsum */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = hashsum; sourceTree = "<group>"; };
		8433693B1F1D885F00840DA9 /* TextureShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureShader.h; sourceTree = "<group>"; };
		8433693C1F1D885F00840DA9 /* TextureShader.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = TextureShader.frag; sourceTree = "<group>"; };
		8433693D1F1D885F00840DA9 /* TextureShader.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = TextureShader.vert; sourceTree = "<group>"; };
		8433693E1F1D885F00840DA9 /* Window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Window.cpp; sourceTree = "<group>"; };
		8433693F1F1D885F00840DA9 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = "<group>"; };
		843369411F1D885F00840DA9 /* TextRasterizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextRasterizer.cpp; sourceTree = "<group>"; };
		843369421F1D885F00840DA9 /* TextRasterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextRasterizer.h; sourceTree = "<group>"; };
		843369431F1D885F00840DA9 /* TextRasterizerCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextRasterizerCache.cpp; sourceTree = "<group>"; };
		843369441F1D885F00840DA9 /* TextRasterizerCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextRasterizerCache.h; sourceTree = "<group>"; };
		843369461F1D885F00840DA9 /* HTMLParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLParser.cpp; sourceTree = "<group>"; };
		843369471F1D885F00840DA9 /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParser.h; sourceTree = "<group>"; };
		843369481F1D885F00840DA9 /* Node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Node.cpp; sourceTree = "<group>"; };
		843369491F1D885F00840DA9 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Node.h; sourceTree = "<group>"; };
		8433694A1F1D885F00840DA9 /* TagNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TagNode.cpp; sourceTree = "<group>"; };
		8433694B1F1D885F00840DA9 /* TagNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagNode.h; sourceTree = "<group>"; };
		8433694C1F1D885F00840DA9 /* TextNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextNode.cpp; sourceTree = "<group>"; };
		8433694D1F1D885F00840DA9 /* TextNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextNode.h; sourceTree = "<group>"; };
		8433694E1F1D885F00840DA9 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../src/main.cpp; sourceTree = SOURCE_ROOT; };
		843369501F1D885F00840DA9 /* HTTPRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPRequest.cpp; sourceTree = "<group>"; };
		843369511F1D885F00840DA9 /* HTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTTPRequest.h; sourceTree = "<group>"; };
		843369521F1D885F00840DA9 /* HTTPResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPResponse.cpp; sourceTree = "<group>"; };
		843369531F1D885F00840DA9 /* HTTPResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTTPResponse.h; sourceTree = "<group>"; };
		8433696E1F1D888E00840DA9 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
		843369701F1D889C00840DA9 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
		843369721F1D88A000840DA9 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
		843369741F1D88A800840DA9 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
		8437F8991F2F543400E89305 /* StringUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringUtils.cpp; path = "/Users/admin/Sites/nr-textwork170728/xcode/../src/StringUtils.cpp"; sourceTree = "<absolute>"; };
		8437F89B1F2F545D00E89305 /* StringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringUtils.h; path = "/Users/admin/Sites/nr-textwork170728/xcode/../src/StringUtils.h"; sourceTree = "<absolute>"; };
		843C30E71F2F5110006F00B3 /* WebResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebResource.cpp; path = "/Users/admin/Sites/nr-textwork170728/xcode/../src/WebResource.cpp"; sourceTree = "<absolute>"; };
		843C30E81F2F5110006F00B3 /* WebResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebResource.h; path = "/Users/admin/Sites/nr-textwork170728/xcode/../src/WebResource.h"; sourceTree = "<absolute>"; };
		843C31291F2F5307006F00B3 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = info.plist; path = xcode/info.plist; sourceTree = "<group>"; };
		844925041F1D9478007E8644 /* DejaVuSerif.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = DejaVuSerif.ttf; path = ../DejaVuSerif.ttf; sourceTree = SOURCE_ROOT; };
		846965381F32A9EF00980986 /* Log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Log.h; sourceTree = "<group>"; };
		846965391F32A9EF00980986 /* BrowsingHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BrowsingHistory.cpp; sourceTree = "<group>"; };
		8469653A1F32A9EF00980986 /* BrowsingHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowsingHistory.h; sourceTree = "<group>"; };
		8469653B1F32A9EF00980986 /* CommandLineParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommandLineParams.cpp; sourceTree = "<group>"; };
		8469653C1F32A9EF00980986 /* CommandLineParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommandLineParams.h; sourceTree = "<group>"; };
		8469653D1F32A9EF00980986 /* Log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Log.cpp; sourceTree = "<group>"; };
		8469653E1F32A9EF00980986 /* URL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URL.cpp; sourceTree = "<group>"; };
		8469653F1F32A9EF00980986 /* URL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URL.h; sourceTree = "<group>"; };
		849C756A1F2BF9580082827A /* DIVElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DIVElement.cpp; sourceTree = "<group>"; };
		849C756B1F2BF9580082827A /* DIVElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DIVElement.h; sourceTree = "<group>"; };
		849C756C1F2BF9580082827A /* Element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Element.cpp; sourceTree = "<group>"; };
		849C756D1F2BF9580082827A /* Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Element.h; sourceTree = "<group>"; };
		849C756E1F2BF9580082827A /* STRONGElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = STRONGElement.cpp; sourceTree = "<group>"; };
		849C756F1F2BF9580082827A /* STRONGElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STRONGElement.h; sourceTree = "<group>"; };
		84B6602B1F1D8DF000AEFBEC /* DejaVuSerif-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "DejaVuSerif-Bold.ttf"; path = "../DejaVuSerif-Bold.ttf"; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		843369051F1D881B00840DA9 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				843369751F1D88A800840DA9 /* CoreVideo.framework in Frameworks */,
				843369731F1D88A000840DA9 /* IOKit.framework in Frameworks */,
				843369711F1D889C00840DA9 /* Cocoa.framework in Frameworks */,
				8433696F1F1D888E00840DA9 /* OpenGL.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		843368FF1F1D881B00840DA9 = {
			isa = PBXGroup;
			children = (
				8433690A1F1D881B00840DA9 /* Saltasaurus */,
				843369091F1D881B00840DA9 /* Products */,
				8433696D1F1D888E00840DA9 /* Frameworks */,
			);
			sourceTree = "<group>";
		};
		843369091F1D881B00840DA9 /* Products */ = {
			isa = PBXGroup;
			children = (
				843369081F1D881B00840DA9 /* Saltasaurus */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		8433690A1F1D881B00840DA9 /* Saltasaurus */ = {
			isa = PBXGroup;
			children = (
				843C31291F2F5307006F00B3 /* info.plist */,
				84B6602B1F1D8DF000AEFBEC /* DejaVuSerif-Bold.ttf */,
				844925041F1D9478007E8644 /* DejaVuSerif.ttf */,
				843369121F1D885F00840DA9 /* src */,
			);
			name = Saltasaurus;
			path = "/Users/admin/Sites/nr-textwork170728";
			sourceTree = "<absolute>";
		};
		843369121F1D885F00840DA9 /* src */ = {
			isa = PBXGroup;
			children = (
				843369131F1D885F00840DA9 /* graphics */,
				843369451F1D885F00840DA9 /* html */,
				8433694F1F1D885F00840DA9 /* networking */,
				8433694E1F1D885F00840DA9 /* main.cpp */,
				8437F8991F2F543400E89305 /* StringUtils.cpp */,
				8437F89B1F2F545D00E89305 /* StringUtils.h */,
				843C30E71F2F5110006F00B3 /* WebResource.cpp */,
				843C30E81F2F5110006F00B3 /* WebResource.h */,
				846965391F32A9EF00980986 /* BrowsingHistory.cpp */,
				8469653A1F32A9EF00980986 /* BrowsingHistory.h */,
				8469653B1F32A9EF00980986 /* CommandLineParams.cpp */,
				8469653C1F32A9EF00980986 /* CommandLineParams.h */,
				8469653D1F32A9EF00980986 /* Log.cpp */,
				846965381F32A9EF00980986 /* Log.h */,
				8469653E1F32A9EF00980986 /* URL.cpp */,
				8469653F1F32A9EF00980986 /* URL.h */,
			);
			path = src;
			sourceTree = "<group>";
		};
		843369131F1D885F00840DA9 /* graphics */ = {
			isa = PBXGroup;
			children = (
				843369141F1D885F00840DA9 /* components */,
				8433691F1F1D885F00840DA9 /* elements */,
				843369341F1D885F00840DA9 /* opengl */,
				843369401F1D885F00840DA9 /* text */,
			);
			path = graphics;
			sourceTree = "<group>";
		};
		843369141F1D885F00840DA9 /* components */ = {
			isa = PBXGroup;
			children = (
				843369151F1D885F00840DA9 /* AnimeComponent.cpp */,
				843369161F1D885F00840DA9 /* AnimeComponent.h */,
				843369171F1D885F00840DA9 /* BoxComponent.cpp */,
				843369181F1D885F00840DA9 /* BoxComponent.h */,
				843369191F1D885F00840DA9 /* Component.cpp */,
				8433691A1F1D885F00840DA9 /* Component.h */,
				8433691B1F1D885F00840DA9 /* ComponentBuilder.cpp */,
				8433691C1F1D885F00840DA9 /* ComponentBuilder.h */,
				8433691D1F1D885F00840DA9 /* TextComponent.cpp */,
				8433691E1F1D885F00840DA9 /* TextComponent.h */,
			);
			path = components;
			sourceTree = "<group>";
		};
		8433691F1F1D885F00840DA9 /* elements */ = {
			isa = PBXGroup;
			children = (
				849C756A1F2BF9580082827A /* DIVElement.cpp */,
				849C756B1F2BF9580082827A /* DIVElement.h */,
				849C756C1F2BF9580082827A /* Element.cpp */,
				849C756D1F2BF9580082827A /* Element.h */,
				849C756E1F2BF9580082827A /* STRONGElement.cpp */,
				849C756F1F2BF9580082827A /* STRONGElement.h */,
				843369201F1D885F00840DA9 /* AElement.cpp */,
				843369211F1D885F00840DA9 /* AElement.h */,
				843369221F1D885F00840DA9 /* BLOCKQUOTEElement.cpp */,
				843369231F1D885F00840DA9 /* BLOCKQUOTEElement.h */,
				843369261F1D885F00840DA9 /* H1Element.cpp */,
				843369271F1D885F00840DA9 /* H1Element.h */,
				843369281F1D885F00840DA9 /* H2Element.cpp */,
				843369291F1D885F00840DA9 /* H2Element.h */,
				8433692A1F1D885F00840DA9 /* H3Element.cpp */,
				8433692B1F1D885F00840DA9 /* H3Element.h */,
				8433692C1F1D885F00840DA9 /* LIElement.cpp */,
				8433692D1F1D885F00840DA9 /* LIElement.h */,
				8433692E1F1D885F00840DA9 /* PElement.cpp */,
				8433692F1F1D885F00840DA9 /* PElement.h */,
				843369321F1D885F00840DA9 /* SPANElement.cpp */,
				843369331F1D885F00840DA9 /* SPANElement.h */,
			);
			path = elements;
			sourceTree = "<group>";
		};
		843369341F1D885F00840DA9 /* opengl */ = {
			isa = PBXGroup;
			children = (
				843369351F1D885F00840DA9 /* shaders */,
				8433693E1F1D885F00840DA9 /* Window.cpp */,
				8433693F1F1D885F00840DA9 /* Window.h */,
			);
			path = opengl;
			sourceTree = "<group>";
		};
		843369351F1D885F00840DA9 /* shaders */ = {
			isa = PBXGroup;
			children = (
				843369361F1D885F00840DA9 /* FontShader.frag */,
				843369371F1D885F00840DA9 /* FontShader.vert */,
				843369381F1D885F00840DA9 /* gen */,
				8433693C1F1D885F00840DA9 /* TextureShader.frag */,
				8433693D1F1D885F00840DA9 /* TextureShader.vert */,
			);
			path = shaders;
			sourceTree = "<group>";
		};
		843369381F1D885F00840DA9 /* gen */ = {
			isa = PBXGroup;
			children = (
				843369391F1D885F00840DA9 /* FontShader.h */,
				8433693A1F1D885F00840DA9 /* hashsum */,
				8433693B1F1D885F00840DA9 /* TextureShader.h */,
			);
			path = gen;
			sourceTree = "<group>";
		};
		843369401F1D885F00840DA9 /* text */ = {
			isa = PBXGroup;
			children = (
				843369411F1D885F00840DA9 /* TextRasterizer.cpp */,
				843369421F1D885F00840DA9 /* TextRasterizer.h */,
				843369431F1D885F00840DA9 /* TextRasterizerCache.cpp */,
				843369441F1D885F00840DA9 /* TextRasterizerCache.h */,
			);
			path = text;
			sourceTree = "<group>";
		};
		843369451F1D885F00840DA9 /* html */ = {
			isa = PBXGroup;
			children = (
				843369461F1D885F00840DA9 /* HTMLParser.cpp */,
				843369471F1D885F00840DA9 /* HTMLParser.h */,
				843369481F1D885F00840DA9 /* Node.cpp */,
				843369491F1D885F00840DA9 /* Node.h */,
				8433694A1F1D885F00840DA9 /* TagNode.cpp */,
				8433694B1F1D885F00840DA9 /* TagNode.h */,
				8433694C1F1D885F00840DA9 /* TextNode.cpp */,
				8433694D1F1D885F00840DA9 /* TextNode.h */,
			);
			name = html;
			path = ../src/html;
			sourceTree = "<group>";
		};
		8433694F1F1D885F00840DA9 /* networking */ = {
			isa = PBXGroup;
			children = (
				843369501F1D885F00840DA9 /* HTTPRequest.cpp */,
				843369511F1D885F00840DA9 /* HTTPRequest.h */,
				843369521F1D885F00840DA9 /* HTTPResponse.cpp */,
				843369531F1D885F00840DA9 /* HTTPResponse.h */,
			);
			path = networking;
			sourceTree = "<group>";
		};
		8433696D1F1D888E00840DA9 /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				843369741F1D88A800840DA9 /* CoreVideo.framework */,
				843369721F1D88A000840DA9 /* IOKit.framework */,
				843369701F1D889C00840DA9 /* Cocoa.framework */,
				8433696E1F1D888E00840DA9 /* OpenGL.framework */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		843369071F1D881B00840DA9 /* Saltasaurus */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 8433690F1F1D881B00840DA9 /* Build configuration list for PBXNativeTarget "Saltasaurus" */;
			buildPhases = (
				843369041F1D881B00840DA9 /* Sources */,
				843369051F1D881B00840DA9 /* Frameworks */,
				843369061F1D881B00840DA9 /* CopyFiles */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Saltasaurus;
			productName = Saltasaurus;
			productReference = 843369081F1D881B00840DA9 /* Saltasaurus */;
			productType = "com.apple.product-type.tool";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		843369001F1D881B00840DA9 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0830;
				ORGANIZATIONNAME = RetroTech;
				TargetAttributes = {
					843369071F1D881B00840DA9 = {
						CreatedOnToolsVersion = 8.3.3;
						ProvisioningStyle = Automatic;
					};
				};
			};
			buildConfigurationList = 843369031F1D881B00840DA9 /* Build configuration list for PBXProject "Saltasaurus" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
			);
			mainGroup = 843368FF1F1D881B00840DA9;
			productRefGroup = 843369091F1D881B00840DA9 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				843369071F1D881B00840DA9 /* Saltasaurus */,
			);
		};
/* End PBXProject section */

/* Begin PBXSourcesBuildPhase section */
		843369041F1D881B00840DA9 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8437F8A41F2F555600E89305 /* DIVElement.cpp in Sources */,
				8437F8A51F2F555600E89305 /* Element.cpp in Sources */,
				8437F8A61F2F555600E89305 /* STRONGElement.cpp in Sources */,
				8437F8A71F2F555600E89305 /* AElement.cpp in Sources */,
				8437F8A81F2F555600E89305 /* BLOCKQUOTEElement.cpp in Sources */,
				8437F8A91F2F555600E89305 /* H1Element.cpp in Sources */,
				8437F8AA1F2F555600E89305 /* H2Element.cpp in Sources */,
				846965411F32A9EF00980986 /* CommandLineParams.cpp in Sources */,
				8437F8AB1F2F555600E89305 /* H3Element.cpp in Sources */,
				8437F8AC1F2F555600E89305 /* LIElement.cpp in Sources */,
				8437F8AD1F2F555600E89305 /* PElement.cpp in Sources */,
				846965431F32A9EF00980986 /* URL.cpp in Sources */,
				8437F8AE1F2F555600E89305 /* SPANElement.cpp in Sources */,
				8437F8AF1F2F555600E89305 /* Window.cpp in Sources */,
				8437F8B01F2F555600E89305 /* TextRasterizer.cpp in Sources */,
				8437F8B11F2F555600E89305 /* TextRasterizerCache.cpp in Sources */,
				8437F8B21F2F555600E89305 /* HTMLParser.cpp in Sources */,
				8437F8B31F2F555600E89305 /* Node.cpp in Sources */,
				8437F8B41F2F555600E89305 /* TagNode.cpp in Sources */,
				8437F8B51F2F555600E89305 /* TextNode.cpp in Sources */,
				8437F8A21F2F552E00E89305 /* ComponentBuilder.cpp in Sources */,
				8437F89A1F2F543400E89305 /* StringUtils.cpp in Sources */,
				846965421F32A9EF00980986 /* Log.cpp in Sources */,
				8437F8981F2F540300E89305 /* main.cpp in Sources */,
				8437F89D1F2F54B900E89305 /* HTTPResponse.cpp in Sources */,
				8437F89C1F2F54B600E89305 /* HTTPRequest.cpp in Sources */,
				8437F89E1F2F54BE00E89305 /* WebResource.cpp in Sources */,
				846965401F32A9EF00980986 /* BrowsingHistory.cpp in Sources */,
				8437F89F1F2F552500E89305 /* AnimeComponent.cpp in Sources */,
				8437F8A01F2F552900E89305 /* BoxComponent.cpp in Sources */,
				8437F8A11F2F552C00E89305 /* Component.cpp in Sources */,
				8437F8A31F2F553100E89305 /* TextComponent.cpp in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin XCBuildConfiguration section */
		8433690D1F1D881B00840DA9 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "-";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.12;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = macosx;
			};
			name = Debug;
		};
		8433690E1F1D881B00840DA9 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "-";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.12;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = macosx;
			};
			name = Release;
		};
		843369101F1D881B00840DA9 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CLANG_CXX_LANGUAGE_STANDARD = "c++14";
				GCC_C_LANGUAGE_STANDARD = "compiler-default";
				HEADER_SEARCH_PATHS = (
					/usr/local/include/freetype2,
					/usr/local/include/harfbuzz,
					/usr/local/include/,
				);
				INFOPLIST_FILE = "$(SRCROOT)/info.plist";
				LIBRARY_SEARCH_PATHS = /usr/local/lib;
				MACOSX_DEPLOYMENT_TARGET = 10.12;
				OTHER_LDFLAGS = (
					"-lglfw3",
					"-lharfbuzz",
					"-lfreetype",
					"-lGLEW",
				);
				PRELINK_LIBS = "";
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		843369111F1D881B00840DA9 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CLANG_CXX_LANGUAGE_STANDARD = "c++14";
				GCC_C_LANGUAGE_STANDARD = "compiler-default";
				HEADER_SEARCH_PATHS = (
					/usr/local/include/freetype2,
					/usr/local/include/harfbuzz,
					/usr/local/include/,
				);
				INFOPLIST_FILE = "$(SRCROOT)/info.plist";
				LIBRARY_SEARCH_PATHS = /usr/local/lib;
				MACOSX_DEPLOYMENT_TARGET = 10.12;
				OTHER_LDFLAGS = (
					"-lglfw3",
					"-lharfbuzz",
					"-lfreetype",
					"-lGLEW",
				);
				PRELINK_LIBS = "";
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		843369031F1D881B00840DA9 /* Build configuration list for PBXProject "Saltasaurus" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				8433690D1F1D881B00840DA9 /* Debug */,
				8433690E1F1D881B00840DA9 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		8433690F1F1D881B00840DA9 /* Build configuration list for PBXNativeTarget "Saltasaurus" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				843369101F1D881B00840DA9 /* Debug */,
				843369111F1D881B00840DA9 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 843369001F1D881B00840DA9 /* Project object */;
}


code:
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:Saltasaurus.xcodeproj">
   </FileRef>
</Workspace>

repo_name: vaartis/netrunner

license: mit


code:
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0830"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "843369071F1D881B00840DA9"
               BuildableName = "Saltasaurus"
               BlueprintName = "Saltasaurus"
               ReferencedContainer = "container:Saltasaurus.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "843369071F1D881B00840DA9"
            BuildableName = "Saltasaurus"
            BlueprintName = "Saltasaurus"
            ReferencedContainer = "container:Saltasaurus.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      enableAddressSanitizer = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "843369071F1D881B00840DA9"
            BuildableName = "Saltasaurus"
            BlueprintName = "Saltasaurus"
            ReferencedContainer = "container:Saltasaurus.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <CommandLineArguments>
         <CommandLineArgument
            argument = "http://endchan.xyz/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://www.browserscope.org/"
            isEnabled = "YES">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://Anhai.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://A\han.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "ittp://4chon.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "motherfuckingpebsitehttp://4chon.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://Drhan.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://FchIp.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://ccfaa.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://motherfuckingwebsite.com/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://4chan.org/"
            isEnabled = "NO">
         </CommandLineArgument>
         <CommandLineArgument
            argument = "http://boards.4chan.org/g/"
            isEnabled = "NO">
         </CommandLineArgument>
      </CommandLineArguments>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "843369071F1D881B00840DA9"
            BuildableName = "Saltasaurus"
            BlueprintName = "Saltasaurus"
            ReferencedContainer = "container:Saltasaurus.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


code:
<?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>SchemeUserState</key>
	<dict>
		<key>Saltasaurus.xcscheme</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
	<key>SuppressBuildableAutocreation</key>
	<dict>
		<key>843369071F1D881B00840DA9</key>
		<dict>
			<key>primary</key>
			<true/>
		</dict>
	</dict>
</dict>
</plist>


code:
<?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>NSSupportsAutomaticGraphicsSwitching</key>
	<true/>
</dict>
</plist>


code:
// For those who want the bleeding edge
buildscript {
    repositories {
        jcenter()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
    }
}
apply plugin: 'net.minecraftforge.gradle.forge'

version = file('CURRENT_VERSION').text.trim()
group= "astrotibs.notenoughpets" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "NotEnoughPets-1.9.4"

minecraft {
    version = "1.9.4-12.17.0.1976"
    runDir = "run"
	replaceIn 'src/main/java/astrotibs/notenoughpets/util/Reference.java'
	replace '@VERSION@', project.version

    // the mappings can be changed at any time, and must be in the following format.
    // snapshot_YYYYMMDD   snapshot are built nightly.
    // stable_#            stables are built at the discretion of the MCP team.
    // Use non-default mappings at your own risk. they may not allways work.
    // simply re-run your setup task after changing the mappings to update your workspace.
    mappings = "snapshot_20160518"
    // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
}

dependencies {
    // you may put jars on which you depend on in ./libs
    // or you may define them like so..
    //compile "some.group:artifact:version:classifier"
    //compile "some.group:artifact:version"

    // real examples
    //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev'  // adds buildcraft to the dev env
    //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env

    // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
    //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'

    // the deobf configurations:  'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
    // except that these dependencies get remapped to your current MCP mappings
    //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
    //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'

    // for more info...
    // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
    // http://www.gradle.org/docs/current/userguide/dependency_management.html

}

processResources
{
    // this will ensure that this task is redone when the versions change.
    inputs.property "version", project.version
    inputs.property "mcversion", project.minecraft.version

    // replace stuff in mcmod.info, nothing else
    from(sourceSets.main.resources.srcDirs) {
        include 'mcmod.info'

        // replace version and mcversion
        expand 'version':project.version, 'mcversion':project.minecraft.version
    }

    // copy everything else, thats not the mcmod.info
    from(sourceSets.main.resources.srcDirs) {
        exclude 'mcmod.info'
    }
}

license: unknown


code:
package astrotibs.notenoughpets;

import java.io.File;

import astrotibs.notenoughpets.client.render.RenderMooshroomNEP;
import astrotibs.notenoughpets.client.render.RenderOcelotNEP;
import astrotibs.notenoughpets.client.render.RenderParrotNEP;
import astrotibs.notenoughpets.client.render.RenderWolfNEP;
import astrotibs.notenoughpets.config.GeneralConfig;
import astrotibs.notenoughpets.entity.EntityMooshroomNEP;
import astrotibs.notenoughpets.entity.EntityOcelotNEP;
import astrotibs.notenoughpets.entity.EntityParrotNEP;
import astrotibs.notenoughpets.entity.EntityWolfNEP;
import astrotibs.notenoughpets.events.EventHandlerNEP;
import astrotibs.notenoughpets.network.MessageShoulderParrots;
import astrotibs.notenoughpets.network.NetworkHelper;
import astrotibs.notenoughpets.proxy.CommonProxy;
import astrotibs.notenoughpets.spawnegg.SpawnEggRegistry;
import astrotibs.notenoughpets.util.Reference;
import astrotibs.notenoughpets.version.DevVersionWarning;
import astrotibs.notenoughpets.version.VersionChecker;
import net.minecraft.client.Minecraft;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Biomes;
import net.minecraft.item.Item;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.relauncher.Side;

/*
 * Loot 0 sword:
 * give @p diamond_sword 1 0 {ench:[{id:16,lvl:1000},{id:34,lvl:99}]}
 * Loot 3 sword
 * give @p golden_sword 1 0 {ench:[{id:16,lvl:1000},{id:34,lvl:99},{id:21,lvl:3}]}
 */

@Mod(
		modid = Reference.MOD_ID,
		name = Reference.MOD_NAME,
		version = Reference.VERSION,
		guiFactory = Reference.GUI_FACTORY
		)
public class ModNotEnoughPets
{

	//Copied from Village Names
	public static File configDirectory;

	@SidedProxy(clientSide = Reference.CLIENT_PROXY, serverSide = Reference.SERVER_PROXY)
	public static CommonProxy PROXY;

	public static SimpleNetworkWrapper NECNetworkWrapper;

	public static CreativeTabs spawnEggTabNEC = new CreativeTabs(Reference.MOD_ID)
	{
		@Override
		public Item getTabIconItem() {return SpawnEggRegistry.SPAWN_EGG;}
	};

    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
		// Copied from ChocoCraft Plus
		configDirectory = new File(event.getModConfigurationDirectory(), "notenoughpets.cfg");//new File(ModChocoCraft.configFolder, "chococraft.json");
		GeneralConfig.init(configDirectory);//new File(configDirectory, "general.cfg"));

		// Spawn egg stuff
		SpawnEggRegistry.init();

    	// Cat listener:
    	MinecraftForge.EVENT_BUS.register(new EventHandlerNEP());

    	// Register sound events -- required as per 1.9
        Reference.registerSounds();

    	// Version check monitor
        if ((Reference.VERSION).contains("DEV")) {MinecraftForge.EVENT_BUS.register(DevVersionWarning.instance);}
        else if (GeneralConfig.versionChecker) {MinecraftForge.EVENT_BUS.register(VersionChecker.instance);}

        // Establish the channel
        NECNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel(Reference.MOD_CHANNEL);

        // Register different messages here
        int messageID = 0;
        NECNetworkWrapper.registerMessage(NetworkHelper.ShoulderParrotsHandler.class, MessageShoulderParrots.class, messageID++, Side.CLIENT);

		// The following overrides the mcmod.info file!
		// Adapted from Jabelar's Magic Beans:
		// https://github.com/jabelar/MagicBeans-1.7.10/blob/e48456397f9c6c27efce18e6b9ad34407e6bc7c7/src/main/java/com/blogspot/jabelarminecraft/magicbeans/MagicBeans.java
        event.getModMetadata().autogenerated = false ; // stops it from complaining about missing mcmod.info

        event.getModMetadata().name = 			// name
        		//EnumChatFormatting.YELLOW +
        		Reference.MOD_NAME;

        event.getModMetadata().version = 		// version
        		Reference.VERSION;

        event.getModMetadata().credits = 		// credits
        		//EnumChatFormatting.AQUA +
        		"Vanilla textures by Jappa. Custom by AstroTibs and by submission.";

        event.getModMetadata().authorList.clear();
        event.getModMetadata().authorList.add(  // authorList - added as a list
        		//EnumChatFormatting.BLUE +
        		"AstroTibs");

        event.getModMetadata().url = //EnumChatFormatting.GRAY +
        		Reference.URL;

        event.getModMetadata().description = 	// description
	       		//EnumChatFormatting.YELLOW +
	       		"Adds new cat/dog/parrot skins and behavior settings. Cats and dogs spawn as strays in villages.";

        event.getModMetadata().logoFile = "assets"+File.separator+"notenoughpets"+File.separator+"nep_banner.png";

    }
    /**
     * Register the mod entity type with FML

     * @param entityClass The entity class
     * @param entityName A unique name for the entity
     * @param id A mod specific ID for the entity
     * @param mod The mod
     * @param trackingRange The range at which MC will send tracking updates
     * @param updateFrequency The frequency of tracking updates
     * @param sendsVelocityUpdates Whether to send velocity information packets as well
     */
    @EventHandler
    public void init(FMLInitializationEvent event)
    {
    	// If this code runs on the server, you will get a crash.
		if (event.getSide()== Side.CLIENT)
		{
			SpawnEggRegistry.inventoryRenders();
		}

    	int entityIDs = 0; // Increment this to make sure everything has its own model register

    	// Changed names to reference constants
    	EntityRegistry.registerModEntity(EntityOcelotNEP.class, Reference.MOB_OCELOT_NEP, entityIDs++, this, 64, 3, true);
    	EntityRegistry.registerModEntity(EntityWolfNEP.class, Reference.MOB_WOLF_NEP, entityIDs++, this, 64, 3, true);
    	EntityRegistry.registerModEntity(EntityMooshroomNEP.class, Reference.MOB_MOOSHROOM_NEP, entityIDs++, this, 64, 3, true);

    	if (GeneralConfig.enableNEPParrots)
    	{
	    	EntityRegistry.registerModEntity(EntityParrotNEP.class, Reference.MOB_PARROT_NEP, entityIDs++, this, 64, 3, true);
	    	EntityRegistry.addSpawn(EntityParrotNEP.class, 40, 1, 2, EnumCreatureType.CREATURE, Biomes.JUNGLE);
    	}

    	PROXY.init(event);

    	// Trying this version instead
    	if (event.getSide() == Side.CLIENT) {

	        Minecraft.getMinecraft().getRenderManager().entityRenderMap.put(EntityOcelotNEP.class,
	        		new RenderOcelotNEP(Minecraft.getMinecraft().getRenderManager()));

            Minecraft.getMinecraft().getRenderManager().entityRenderMap.put(EntityWolfNEP.class,
            		new RenderWolfNEP(Minecraft.getMinecraft().getRenderManager()));

	        Minecraft.getMinecraft().getRenderManager().entityRenderMap.put(EntityMooshroomNEP.class,
	        		new RenderMooshroomNEP(Minecraft.getMinecraft().getRenderManager()));

	        Minecraft.getMinecraft().getRenderManager().entityRenderMap.put(EntityParrotNEP.class,
	        		new RenderParrotNEP(Minecraft.getMinecraft().getRenderManager()));
    	}

    }

    // Add spawn eggs to the registry
	@EventHandler
	public void postInit(FMLPostInitializationEvent event)
	{
		SpawnEggRegistry.addAllSpawnEggs();
	}

    private static int getRGBInt(int rInt, int gInt, int bInt)
	{
		return (rInt << 16) + (gInt << 8) + bInt;
	}

}


code:
package astrotibs.notenoughpets.ai;

import java.util.Iterator;

import astrotibs.notenoughpets.config.GeneralConfig;
import astrotibs.notenoughpets.entity.EntityParrotNEP;
import astrotibs.notenoughpets.pathfinding.minecraft.PathNavigateFlying;
import astrotibs.notenoughpets.util.Reference;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIFollowOwner;
import net.minecraft.entity.ai.EntityAITasks;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;

// Re-written in v2.0.0 so that Parrots can follow you
public class EntityAIFollowOwnerNEP extends EntityAIBase
{
	private final EntityTameable thePet;
    private EntityLivingBase theOwner;
    protected World world;
    private final double followSpeed;
    private final PathNavigate petPathfinder;
    private int timeToRecalcPath;
    float maxDist;
    float minDist;
    private float oldWaterCost;

	public EntityAIFollowOwnerNEP(EntityTameable tameableIn, double followSpeedIn, float minDistIn, float maxDistIn)
	{
		this.thePet = tameableIn;
        this.world = tameableIn.worldObj;
        this.followSpeed = followSpeedIn;
        this.petPathfinder = tameableIn.getNavigator();
        this.minDist = minDistIn;
        this.maxDist = maxDistIn;
        this.setMutexBits(3);

        if (!(tameableIn.getNavigator() instanceof PathNavigateGround) && !(tameableIn.getNavigator() instanceof PathNavigateFlying))
        {
            throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal");
        }
	}

    /**
     * Returns whether the EntityAIBase should begin execution.
     */
	@Override
    public boolean shouldExecute()
    {
        EntityLivingBase entitylivingbase = this.thePet.getOwner();

        if (entitylivingbase == null)
        {
            return false;
        }
        else if (entitylivingbase instanceof EntityPlayer && ((EntityPlayer)entitylivingbase).isSpectator())
        {
            return false;
        }
        else if (this.thePet.isSitting())
        {
            return false;
        }
        else if (this.thePet.getDistanceSqToEntity(entitylivingbase) < (double)(this.minDist * this.minDist))
        {
            return false;
        }
        else
        {
            this.theOwner = entitylivingbase;
            return true;
        }
    }

    /**
     * Returns whether an in-progress EntityAIBase should continue executing
     */
	@Override
    public boolean continueExecuting()
    {
        return !this.petPathfinder.noPath() && this.thePet.getDistanceSqToEntity(this.theOwner) > (double)(this.maxDist * this.maxDist) && !this.thePet.isSitting();
    }

    /**
     * Execute a one shot task or start executing a continuous task
     */
	@Override
    public void startExecuting()
    {
        this.timeToRecalcPath = 0;
        this.oldWaterCost = this.thePet.getPathPriority(PathNodeType.WATER);
        this.thePet.setPathPriority(PathNodeType.WATER, 0.0F);
    }

    /**
     * Reset the task's internal state. Called when this task is interrupted by another one
     */
	@Override
    public void resetTask()
    {
        this.theOwner = null;
        this.petPathfinder.clearPathEntity();
        this.thePet.setPathPriority(PathNodeType.WATER, this.oldWaterCost);
    }

    /**
     * Updates the task. This was introduced in order to allow control over the entity's teleport range.
     */
	@Override
    public void updateTask()
    {
		this.thePet.getLookHelper().setLookPositionWithEntity(this.theOwner, 10.0F, (float)this.thePet.getVerticalFaceSpeed());

        if (!this.thePet.isSitting())
        {
            if (--this.timeToRecalcPath <= 0)
            {
                this.timeToRecalcPath = 10;

                if (!this.petPathfinder.tryMoveToEntityLiving(this.theOwner, this.followSpeed))
                {
                    if (!this.thePet.getLeashed() && !this.thePet.isRiding())
                    {
                    	// Teleportation handler - rejigged
                    	float catTeleportDist = Math.max(GeneralConfig.followTeleportCat, 3F);
                    	float dogTeleportDist = Math.max(GeneralConfig.followTeleportDog, 3F);
                    	float parrotTeleportDist = Math.max(GeneralConfig.followTeleportParrot, 3F); // v2.0.0

                        if (
                        		(
                        				this.thePet instanceof EntityOcelot
                        				&& GeneralConfig.followTeleportCat > 0 // Fixed to allow teleport disabling - v2.1.0
                        				&& this.thePet.getDistanceSqToEntity(this.theOwner) >= (catTeleportDist*catTeleportDist)
                        				)
                        		||
                        		(
                        				this.thePet instanceof EntityWolf
                        				&& GeneralConfig.followTeleportDog > 0 // Fixed to allow teleport disabling - v2.1.0
                        				&& this.thePet.getDistanceSqToEntity(this.theOwner) >= (dogTeleportDist*dogTeleportDist)
                        				)
                        		||
                        		( // v2.0.0
                        				this.thePet instanceof EntityParrotNEP
                        				&& GeneralConfig.followTeleportParrot > 0 // Fixed to allow teleport disabling - v2.1.0
                        				&& this.thePet.getDistanceSqToEntity(this.theOwner) >= (parrotTeleportDist*parrotTeleportDist)
                        				)
                        		||
                        		(
                        				!(this.thePet instanceof EntityOcelot)
                        				&& !(this.thePet instanceof EntityWolf)
                        				&& !(this.thePet instanceof EntityParrotNEP) // v2.0.0
                        				&& this.thePet.getDistanceSqToEntity(this.theOwner) >= 144.0D
                        				)
                        		)
                        {
                            int i = MathHelper.floor_double(this.theOwner.posX) - 2;
                            int j = MathHelper.floor_double(this.theOwner.posZ) - 2;
                            int k = MathHelper.floor_double(this.theOwner.getEntityBoundingBox().minY);

                            for (int l = 0; l <= 4; ++l)
                            {
                                for (int i1 = 0; i1 <= 4; ++i1)
                                {
                                	if ((l < 1 || i1 < 1 || l > 3 || i1 > 3) && this.isTeleportFriendlyBlock(i, j, k, l, i1)) // outsourced to isTeleportFriendlyBlock
                                			//&& World.doesBlockHaveSolidTopSurface(theWorld_reflected, new BlockPos(i + l, k - 1, j + i1))
                                			//&& world_reflected.getBlockState( new BlockPos(i + l, k - 1, j + i1) ).isSideSolid(world_reflected,  new BlockPos(i + l, k - 1, j + i1), EnumFacing.UP)
                                			//&& this.isEmptyBlock(new BlockPos(i + l, k, j + i1))
                                			//&& this.isEmptyBlock(new BlockPos(i + l, k + 1, j + i1)))
                                    {
                                		// Added half-block offset to setLocationAndAngles - v1.3.0
                                        this.thePet.setLocationAndAngles((double)((float)(i + l)+Reference.SPAWN_BLOCK_OFFSET), (double)k, (double)((float)(j + i1)+Reference.SPAWN_BLOCK_OFFSET), this.thePet.rotationYaw, this.thePet.rotationPitch);
                                        this.petPathfinder.clearPathEntity();
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

	// v2.0.0
    protected boolean isTeleportFriendlyBlock(int x, int z, int y, int xOffset, int zOffset)
    {
		//World world_reflected = ReflectionHelper.getPrivateValue( EntityAIFollowOwner.class, this, new String[]{"world", "field_75342_a"} );

    	return this.world.getBlockState( new BlockPos(x + xOffset, y - 1, z + zOffset) ).isSideSolid(this.world,  new BlockPos(x + xOffset, y - 1, z + zOffset), EnumFacing.UP)
    			&& this.isEmptyBlock(new BlockPos(x + xOffset, y, z + zOffset))
    			&& this.isEmptyBlock(new BlockPos(x + xOffset, y + 1, z + zOffset));
    }

	/*
	 * Not visible, for some stupid reason
	 */

	private boolean isEmptyBlock(BlockPos pos)
    {
		//World world_reflected = ReflectionHelper.getPrivateValue( EntityAIFollowOwner.class, this, new String[]{"world", "field_75342_a"} );
		IBlockState iblockstate = this.world.getBlockState(pos);
        Block block = iblockstate.getBlock();
        return block == Blocks.AIR ? true : !iblockstate.isFullCube();
    }

    /**
     * Iterates through entity's AI tasks, and removes the vanilla "follow" version so that it can be replaced with NEC's.
     */
    public static void removeVanillaFollow(EntityTameable entity)
    {
        Iterator iterator = entity.tasks.taskEntries.iterator();

        while (iterator.hasNext())
        {
            EntityAITasks.EntityAITaskEntry entityaitaskentry = (EntityAITasks.EntityAITaskEntry)iterator.next();
            EntityAIBase entityaibase1 = entityaitaskentry.action;

            if (
            		entityaibase1 instanceof EntityAIFollowOwner
            		)
            {
            	iterator.remove();
            }
        }
    }

}


code:
package astrotibs.notenoughpets.ai;

import java.util.Iterator;

import javax.annotation.Nullable;

import astrotibs.notenoughpets.config.GeneralConfig;
import astrotibs.notenoughpets.util.FunctionsNEP;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAITasks;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.ReflectionHelper;

public class EntityAITemptNEP extends EntityAITempt
{
	public EntityAITemptNEP(EntityCreature temptedEntityIn, double speedIn, Item temptItemIn, boolean scaredByPlayerMovementIn)
	{
		super(temptedEntityIn, speedIn, temptItemIn, scaredByPlayerMovementIn);
	}

    /**
     * Returns whether the EntityAIBase should begin execution.
     */
	@Override
    public boolean shouldExecute()
    {
		String[] delayTemptCounter_fields = new String[]{"delayTemptCounter", "field_75290_i"};
		int delayTemptCounter = ReflectionHelper.getPrivateValue(EntityAITempt.class, this, delayTemptCounter_fields);

        if (delayTemptCounter > 0)
        {
        	ReflectionHelper.setPrivateValue(EntityAITempt.class, this, delayTemptCounter-1, delayTemptCounter_fields); //--this.delayTemptCounter;
            return false;
        }
        else
        {
    		String[] temptingPlayer_fields = new String[]{"temptingPlayer", "field_75289_h"};

//            this.temptingPlayer = this.temptedEntity.worldObj.getClosestPlayerToEntity(this.temptedEntity, 10.0D);
    		String[] temptedEntity_fields = new String[]{"temptedEntity", "field_75284_a"};
        	EntityCreature temptedEntity = ReflectionHelper.getPrivateValue(EntityAITempt.class, this, temptedEntity_fields);
        	ReflectionHelper.setPrivateValue(EntityAITempt.class, this,
        			temptedEntity.worldObj.getClosestPlayerToEntity(temptedEntity, 10.0D),
        			temptingPlayer_fields);

        	EntityPlayer temptingPlayer = ReflectionHelper.getPrivateValue(EntityAITempt.class, this, temptingPlayer_fields);

            if (temptingPlayer == null)
            {
                return false;
            }
            else
            {
                return isTempting(temptingPlayer.getHeldItemMainhand()) || isTempting(temptingPlayer.getHeldItemOffhand());
            }
        }
    }

    protected boolean isTempting(@Nullable ItemStack stack)
    {
        return stack == null ? false : FunctionsNEP.isItemStackOnList(stack, GeneralConfig.catBreedingItem_a);
    }

	/**
	 * Iterates through entity's AI tasks, and removes the vanilla "follow" version so that it can be replaced with NEC's.
	 */
	public static void removeVanillaTempt(EntityTameable entity)
	{
		Iterator iterator = entity.tasks.taskEntries.iterator();

		while (iterator.hasNext())
		{
			EntityAITasks.EntityAITaskEntry entityaitaskentry = (EntityAITasks.EntityAITaskEntry)iterator.next();
			EntityAIBase entityaibase1 = entityaitaskentry.action;

			if (entityaibase1 instanceof EntityAITempt)
			{
				iterator.remove();
			}
		}
	}
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import astrotibs.notenoughpets.ai.EntityAIFollowOwnerNEP;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;

/**
 * Pasted in from 1.12.2
 */
public class EntityAIFollowOwnerFlying extends EntityAIFollowOwnerNEP
{
    public EntityAIFollowOwnerFlying(EntityTameable thePetIn, double followSpeedIn, float minDistIn, float maxDistIn)
    {
        super(thePetIn, followSpeedIn, minDistIn, maxDistIn);
    }

    public boolean isEmptyBlock(BlockPos pos)
    {
    	//World world_reflected = ReflectionHelper.getPrivateValue( EntityAIFollowOwner.class, this, new String[]{"world", "field_75342_a"} );

		IBlockState iblockstate = this.world.getBlockState(pos);
        Block block = iblockstate.getBlock();
        return block == Blocks.AIR ? true : !iblockstate.isFullCube();
    }

    @Override
    protected boolean isTeleportFriendlyBlock(int x, int z, int y, int xOffset, int zOffset)
    {
    	//World world_reflected = ReflectionHelper.getPrivateValue( EntityAIFollowOwner.class, this, new String[]{"world", "field_75342_a"} );

    	BlockPos pos = new BlockPos(x + xOffset, y - 1, z + zOffset);
        IBlockState iblockstate = this.world.getBlockState(pos);

        return ( (this.world.getBlockState(pos).isSideSolid(this.world, pos, EnumFacing.UP) || this.world.getBlockState(pos).getMaterial() == Material.LEAVES)
        		&& this.isEmptyBlock(pos.up())
        		&& this.isEmptyBlock(pos.up(2)));
    }
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import java.util.List;

import javax.annotation.Nullable;

import com.google.common.base.Predicate;

import astrotibs.notenoughpets.pathfinding.minecraft.PathNavigateFlying;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityLookHelper;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.pathfinding.PathNodeType;

public class EntityAIFollowParrot extends EntityAIBase
{
    private final EntityLiving entity;
    private final Predicate<EntityLiving> followPredicate;
    private EntityLiving followingEntity;
    private final double speedModifier;
    private final PathNavigate navigation;
    private int timeToRecalcPath;
    private final float stopDistance;
    private float oldWaterCost;
    private final float areaSize;

    public EntityAIFollowParrot(final EntityLiving entityTameable, double speed, float followBegin, float followCutoff)
    {
        this.entity = entityTameable;
        this.followPredicate = new Predicate<EntityLiving>()
        {
            public boolean apply(@Nullable EntityLiving p_apply_1_)
            {
                return p_apply_1_ != null && entityTameable.getClass() != p_apply_1_.getClass();
            }
        };
        this.speedModifier = speed;
        this.navigation = entityTameable.getNavigator();
        this.stopDistance = followBegin;
        this.areaSize = followCutoff;
        this.setMutexBits(3);

        if (!(entityTameable.getNavigator() instanceof PathNavigateGround) && !(entityTameable.getNavigator() instanceof PathNavigateFlying))
        {
            throw new IllegalArgumentException("Unsupported mob type for FollowMobGoal");
        }
    }

    /**
     * Returns whether the EntityAIBase should begin execution.
     */
    public boolean shouldExecute()
    {
        List<EntityLiving> list = this.entity.worldObj.<EntityLiving>getEntitiesWithinAABB(EntityLiving.class, this.entity.getEntityBoundingBox().expandXyz((double)this.areaSize), this.followPredicate);

        if (!list.isEmpty())
        {
            for (EntityLiving entityliving : list)
            {
                if (!entityliving.isInvisible())
                {
                    this.followingEntity = entityliving;
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns whether an in-progress EntityAIBase should continue executing
     */
    public boolean shouldContinueExecuting()
    {
        return this.followingEntity != null && !this.navigation.noPath() && this.entity.getDistanceSqToEntity(this.followingEntity) > (double)(this.stopDistance * this.stopDistance);
    }

    /**
     * Execute a one shot task or start executing a continuous task
     */
    public void startExecuting()
    {
        this.timeToRecalcPath = 0;
        this.oldWaterCost = this.entity.getPathPriority(PathNodeType.WATER);
        this.entity.setPathPriority(PathNodeType.WATER, 0.0F);
    }

    /**
     * Reset the task's internal state. Called when this task is interrupted by another one
     */
    public void resetTask()
    {
        this.followingEntity = null;
        this.navigation.clearPathEntity();
        this.entity.setPathPriority(PathNodeType.WATER, this.oldWaterCost);
    }

    /**
     * Keep ticking a continuous task that has already been started
     */
    public void updateTask()
    {
        if (this.followingEntity != null && !this.entity.getLeashed())
        {
            this.entity.getLookHelper().setLookPositionWithEntity(this.followingEntity, 10.0F, (float)this.entity.getVerticalFaceSpeed());

            if (--this.timeToRecalcPath <= 0)
            {
                this.timeToRecalcPath = 10;
                double d0 = this.entity.posX - this.followingEntity.posX;
                double d1 = this.entity.posY - this.followingEntity.posY;
                double d2 = this.entity.posZ - this.followingEntity.posZ;
                double d3 = d0 * d0 + d1 * d1 + d2 * d2;

                if (d3 > (double)(this.stopDistance * this.stopDistance))
                {
                    this.navigation.tryMoveToEntityLiving(this.followingEntity, this.speedModifier);
                }
                else
                {
                    this.navigation.clearPathEntity();
                    EntityLookHelper entitylookhelper = this.followingEntity.getLookHelper();

                    if (d3 <= (double)this.stopDistance || entitylookhelper.getLookPosX() == this.entity.posX && entitylookhelper.getLookPosY() == this.entity.posY && entitylookhelper.getLookPosZ() == this.entity.posZ)
                    {
                        double d4 = this.followingEntity.posX - this.entity.posX;
                        double d5 = this.followingEntity.posZ - this.entity.posZ;
                        this.navigation.tryMoveToXYZ(this.entity.posX - d4, this.entity.posY, this.entity.posZ - d5, this.speedModifier);
                    }
                }
            }
        }
    }
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import astrotibs.notenoughpets.entity.EntityShoulderRiding;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.player.EntityPlayer;

public class EntityAILandOnOwnersShoulder extends EntityAIBase
{
    private final EntityShoulderRiding entity;
    private EntityPlayer owner;
    private boolean isSittingOnShoulder;

    public EntityAILandOnOwnersShoulder(EntityShoulderRiding entityShoulder)
    {
        this.entity = entityShoulder;
    }

    /**
     * Returns whether the EntityAIBase should begin execution.
     */
    public boolean shouldExecute()
    {
        EntityLivingBase entitylivingbase = this.entity.getOwner();
        boolean flag = entitylivingbase != null && !((EntityPlayer)entitylivingbase).isSpectator() && !((EntityPlayer)entitylivingbase).capabilities.isFlying && !entitylivingbase.isInWater();
        return !this.entity.isSitting() && flag && this.entity.canSitOnShoulder();
    }

    /**
     * Determine if this AI Task is interruptible by a higher (= lower value) priority task. All vanilla AITask have
     * this value set to true.
     */
    public boolean isInterruptible()
    {
        return !this.isSittingOnShoulder;
    }

    /**
     * Execute a one shot task or start executing a continuous task
     */
    public void startExecuting()
    {
        this.owner = (EntityPlayer)this.entity.getOwner();
        this.isSittingOnShoulder = false;
    }

    /**
     * Keep ticking a continuous task that has already been started
     */
    public void updateTask()
    {
        if (!this.isSittingOnShoulder && !this.entity.isSitting() && !this.entity.getLeashed()
        		&& this.entity.getActivePotionEffects().size() == 0 // Must have no potion effects, to prevent loopholes -v2.0.0
        		)
        {
            if (this.entity.getEntityBoundingBox().intersectsWith(this.owner.getEntityBoundingBox()))
            {
                this.isSittingOnShoulder = this.entity.setEntityOnShoulder(this.owner);
            }
        }
    }
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import astrotibs.notenoughpets.pathfinding.minecraft.PathNavigateFlying;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.pathfinding.PathNavigateGround;

public class EntityAISwimmingNEP extends EntityAIBase
{
	private final EntityLiving entity;

    public EntityAISwimmingNEP(EntityLiving entityIn)
    {
        this.entity = entityIn;
        this.setMutexBits(4);

        if (entityIn.getNavigator() instanceof PathNavigateGround)
        {
            ((PathNavigateGround)entityIn.getNavigator()).setCanSwim(true);
        }
        else if (entityIn.getNavigator() instanceof PathNavigateFlying)
        {
            ((PathNavigateFlying)entityIn.getNavigator()).setCanFloat(true);
        }
	}

    /**
     * Returns whether the EntityAIBase should begin execution.
     */
    public boolean shouldExecute()
    {
        return this.entity.isInWater() || this.entity.isInLava();
    }

    /**
     * Keep ticking a continuous task that has already been started
     */
    public void updateTask()
    {
        if (this.entity.getRNG().nextFloat() < 0.8F)
        {
            this.entity.getJumpHelper().setJumping();
        }
    }
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import javax.annotation.Nullable;

import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.RandomPositionGenerator;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.ReflectionHelper;

public class EntityAIWanderAvoidWater extends EntityAIWander
{
    protected final float probability;

    public EntityAIWanderAvoidWater(EntityCreature creature, double speed)
    {
        this(creature, speed, 0.001F);
    }

    public EntityAIWanderAvoidWater(EntityCreature creature, double speed, float probability)
    {
        super(creature, speed);
        this.probability = probability;
    }

    @Nullable
    protected Vec3d getPosition()
    {
    	EntityCreature entity_reflected = ReflectionHelper.getPrivateValue( EntityAIWander.class, this, new String[]{"entity", "field_75457_a"} );

        if (entity_reflected.isInWater())
        {
            Vec3d vec3d = RandomPositionGenerator.findRandomTarget(entity_reflected, 15, 7);
            return vec3d == null ? RandomPositionGenerator.findRandomTarget(entity_reflected, 10, 7) : vec3d;
        }
        else
        {
            return entity_reflected.getRNG().nextFloat() >= this.probability ? RandomPositionGenerator.findRandomTarget(entity_reflected, 10, 7) : RandomPositionGenerator.findRandomTarget(entity_reflected, 10, 7);
        }
    }
}


code:
package astrotibs.notenoughpets.ai.minecraft;

import java.util.Iterator;

import javax.annotation.Nullable;

import net.minecraft.block.Block;
import net.minecraft.block.BlockLeaves;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.RandomPositionGenerator;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.ReflectionHelper;

public class EntityAIWanderAvoidWaterFlying extends EntityAIWanderAvoidWater
{
    public EntityAIWanderAvoidWaterFlying(EntityCreature p_i47413_1_, double p_i47413_2_)
    {
        super(p_i47413_1_, p_i47413_2_);
    }

    @Nullable
    protected Vec3d getPosition()
    {
        Vec3d vec3d = null;

        EntityCreature entity_reflected = ReflectionHelper.getPrivateValue( EntityAIWander.class, this, new String[]{"entity", "field_75457_a"} );

        if (entity_reflected.isInWater() || this.isOverWater())
        {
            vec3d = RandomPositionGenerator.findRandomTarget(entity_reflected, 15, 15);
        }

        if (entity_reflected.getRNG().nextFloat() >= this.probability)
        {
            vec3d = this.getTreePos();
        }

        return vec3d == null ? super.getPosition() : vec3d;
    }

    @Nullable
    private Vec3d getTreePos()
    {
    	EntityCreature entity_reflected = ReflectionHelper.getPrivateValue( EntityAIWander.class, this, new String[]{"entity", "field_75457_a"} );

        BlockPos blockpos = new BlockPos(entity_reflected);
        BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
        BlockPos.MutableBlockPos blockpos$mutableblockpos1 = new BlockPos.MutableBlockPos();

        // func_191531_b is getAllInBoxMutable in 1.12
        Iterable<BlockPos.MutableBlockPos> iterable = BlockPos.MutableBlockPos.getAllInBoxMutable(
        		new BlockPos(MathHelper.floor_double(entity_reflected.posX - 3.0D), MathHelper.floor_double(entity_reflected.posY - 6.0D), MathHelper.floor_double(entity_reflected.posZ - 3.0D)),
        		new BlockPos(MathHelper.floor_double(entity_reflected.posX + 3.0D), MathHelper.floor_double(entity_reflected.posY + 6.0D), MathHelper.floor_double(entity_reflected.posZ + 3.0D)));
        Iterator iterator = iterable.iterator();
        BlockPos blockpos1;

        while (true)
        {
            if (!iterator.hasNext())
            {
                return null;
            }

            blockpos1 = (BlockPos)iterator.next();

            if (!blockpos.equals(blockpos1))
            {
                Block block = entity_reflected.worldObj.getBlockState(blockpos$mutableblockpos1.setPos(blockpos1).move(EnumFacing.DOWN)).getBlock();
                boolean flag = block instanceof BlockLeaves || block == Blocks.LOG || block == Blocks.LOG2;

                if (flag && entity_reflected.worldObj.isAirBlock(blockpos1) && entity_reflected.worldObj.isAirBlock(blockpos$mutableblockpos.setPos(blockpos1).move(EnumFacing.UP)))
                {
                    break;
                }
            }
        }

        return new Vec3d((double)blockpos1.getX(), (double)blockpos1.getY(), (double)blockpos1.getZ());
    }

    /*
     * Pasted in from 1.12's Entity class
     */
    public boolean isOverWater()
    {
    	EntityCreature entity_reflected = ReflectionHelper.getPrivateValue( EntityAIWander.class, this, new String[]{"entity", "field_75457_a"} );
        return entity_reflected.worldObj.handleMaterialAcceleration(entity_reflected.getEntityBoundingBox().expand(0.0D, -20.0D, 0.0D).expandXyz(-0.001D), Material.WATER, entity_reflected);
    }

}


code:
package astrotibs.notenoughpets.ai.minecraft;

import astrotibs.notenoughpets.entity.EntityParrotNEP;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.util.math.MathHelper;

/**
 * Pasted in from 1.12.2
 */
public class EntityFlyHelper extends EntityMoveHelper
{
    public EntityFlyHelper(EntityLiving entityLiving)
    {
        super(entityLiving);
    }

    @Override
    public void onUpdateMoveHelper()
    {
    	if (this.entity instanceof EntityParrotNEP)
    	{
    		//IFlyingMovement ifm = (this.entity).getCapability(FlyingMovementProvider.FLYING_MOVEMENT, null);

            if (this.action == EntityMoveHelper.Action.MOVE_TO)
            {
                this.action = EntityMoveHelper.Action.WAIT;
                ((EntityParrotNEP)this.entity).setNoGravity(true);
                double d0 = this.posX - this.entity.posX;
                double d1 = this.posY - this.entity.posY;
                double d2 = this.posZ - this.entity.posZ;
                double d3 = d0 * d0 + d1 * d1 + d2 * d2;

                if (d3 < 2.500000277905201E-7D)
                {
                	((EntityParrotNEP)this.entity).setMoveVertical(0.0F);
                    this.entity.setMoveForward(0.0F);
                    return;
                }

                float f = (float)(MathHelper.atan2(d2, d0) * (180D / Math.PI)) - 90.0F; // New direction to move towards
                this.entity.rotationYaw = this.limitAngle(this.entity.rotationYaw, f, 10.0F); // Limits yaw direction change to 10 degrees
                float f1;

                if (this.entity.onGround)
                {
                    f1 = (float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue());
                }
                else
                {
                    f1 = (float)(this.speed * ((EntityParrotNEP)this.entity).flyingSpeed);
                }

                this.entity.setAIMoveSpeed(f1);
                double d4 = (double)MathHelper.sqrt_double(d0 * d0 + d2 * d2); // Speed component parallel to the ground
                float f2 = (float)(-(MathHelper.atan2(d1, d4) * (180D / Math.PI)));
                this.entity.rotationPitch = this.limitAngle(this.entity.rotationPitch, f2, 10.0F); // Limits change to vertical direction angle to 10 degree
                //ifm.setMoveVertical(d1 > 0.0D ? f1 : -f1);
                ((EntityParrotNEP)this.entity).setMoveVertical(d1 > 0.0D ? f1 : -f1);
            }
            else
            {
            	((EntityParrotNEP)this.entity).setNoGravity(false);
                ((EntityParrotNEP)this.entity).setMoveVertical(0.0F);
                //ifm.setMoveVertical(0.0F);
                this.entity.setMoveForward(0.0F);
            }
    	}
    }
}


code:
package astrotibs.notenoughpets.capabilities;

import astrotibs.notenoughpets.capabilities.shoulderriding.ShoulderRidingProvider;
import astrotibs.notenoughpets.util.Reference;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

/**
 * Constructed following McHorse's tutorial at:
 * https://www.planetminecraft.com/blog/forge-tutorial-capability-system/
 * @author AstroTibs
 */
//Added in v2.0.0
public class CapabilityAttach
{
	public static final ResourceLocation NEC_CAPABILITIES = new ResourceLocation(Reference.MOD_ID, "capabilities");

	@SubscribeEvent
	public void attachCapability(AttachCapabilitiesEvent event)
	{
		if (event.getObject() instanceof EntityPlayer)
		{
			event.addCapability(NEC_CAPABILITIES, new ShoulderRidingProvider());
		}
		/*else if (event.getObject() instanceof EntityParrotNEC)
		{
			event.addCapability(NEC_CAPABILITIES, new FlyingMovementProvider());
		}*/
	}
}


code:
package astrotibs.notenoughpets.capabilities.shoulderriding;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;

/**
 * Constructed following McHorse's tutorial at:
 * https://www.planetminecraft.com/blog/forge-tutorial-capability-system/
 * @author AstroTibs
 */
// Added in v2.0.0
public interface IShoulderRiding
{
	public void setLeftShoulderEntity(NBTTagCompound nbttagcompound);
	public void setRightShoulderEntity(NBTTagCompound nbttagcompound);

	public boolean addShoulderEntity(EntityPlayer player, NBTTagCompound nbttagcompound);

	public NBTTagCompound getLeftShoulderEntity();
	public NBTTagCompound getRightShoulderEntity();

	// These are quick control of the bird color for quick access when rendering
	public void setRightShoulderVariant(int rightVariant);
	public void setLeftShoulderVariant(int leftVariant);
	public void setRightShoulderAge(int rightAge);
	public void setLeftShoulderAge(int leftAge);

	public int getRightShoulderVariant();
	public int getLeftShoulderVariant();
	public int getRightShoulderAge();
	public int getLeftShoulderAge();

}


code:
package astrotibs.notenoughpets.capabilities.shoulderriding;

import astrotibs.notenoughpets.config.GeneralConfig;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;

/**
 * Constructed following McHorse's tutorial at:
 * https://www.planetminecraft.com/blog/forge-tutorial-capability-system/
 * @author AstroTibs
 */
//Added in v2.0.0
public class ShoulderRiding implements IShoulderRiding
{
	private NBTTagCompound leftShoulderEntity;
	private int leftShoulderVariant;
	private int leftShoulderAge;

	private NBTTagCompound rightShoulderEntity;
	private int rightShoulderVariant;
	private int rightShoulderAge;

	@Override
	public void setLeftShoulderEntity(NBTTagCompound leftShoulderEntityNBT)
	{
		if (!GeneralConfig.enableNEPParrots)
		{
			this.leftShoulderEntity = new NBTTagCompound();
			this.leftShoulderVariant = 0;
			this.leftShoulderAge = 0;
			return;
		}

		this.leftShoulderEntity = leftShoulderEntityNBT;
		this.leftShoulderVariant = determineShoulderVariantInt(leftShoulderEntityNBT);

		if (leftShoulderEntityNBT.hasKey("Age")) {this.leftShoulderAge = leftShoulderEntityNBT.getInteger("Age");}
		else {this.leftShoulderAge = 0;}
	}

	@Override
	public void setRightShoulderEntity(NBTTagCompound rightShoulderEntityNBT)
	{
		if (!GeneralConfig.enableNEPParrots)
		{
			this.rightShoulderEntity = new NBTTagCompound();
			this.rightShoulderVariant = 0;
			this.rightShoulderAge = 0;
			return;
		}

		this.rightShoulderEntity = rightShoulderEntityNBT;
		this.rightShoulderVariant = determineShoulderVariantInt(rightShoulderEntityNBT);

		if (rightShoulderEntityNBT.hasKey("Age")) {this.rightShoulderAge = rightShoulderEntityNBT.getInteger("Age");}
		else {this.rightShoulderAge = 0;}
	}

	@Override
	public boolean addShoulderEntity(EntityPlayer player, NBTTagCompound nbttagcompound)
    {
		IShoulderRiding isr = player.getCapability(ShoulderRidingProvider.SHOULDER_RIDING, null);

        if (
        		!(isr==null)
        		&& !player.isRiding() && player.onGround && !player.isInWater()
        		)
        {
        	if (
        			!(isr.getLeftShoulderEntity()==null)
        			&& isr.getLeftShoulderEntity().hasNoTags()
        			)
            {
            	isr.setLeftShoulderEntity(nbttagcompound);
                return true;
            }
            else if (
            		!(isr.getRightShoulderEntity()==null)
        			&& isr.getRightShoulderEntity().hasNoTags()
            		)
            {
                isr.setRightShoulderEntity(nbttagcompound);
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

	public int determineShoulderVariantInt(NBTTagCompound nbttagcompound)
	{
		if (!GeneralConfig.enableNEPParrots) {return 0;}

		int variant = 0;
		if (nbttagcompound.hasKey("CustomName") && !nbttagcompound.getString("CustomName").equals(""))
		{
			if (nbttagcompound.getString("CustomName").equals("Duster")) {return 6;}
			else if (nbttagcompound.getString("CustomName").equals("Peaches")) {return 8;}
			else if (nbttagcompound.getString("CustomName").equals("Rex")) {return 12;}
		}
		// If the parrot does not have an Easter Egg name
		if (nbttagcompound.hasKey("Variant"))
		{
			variant = nbttagcompound.getInteger("Variant");
			if (variant==0) {variant = -1;} // -1 will be used for the red parrot
		}
		return variant;
	}

	@Override
	public void setLeftShoulderVariant(int variant) {this.leftShoulderVariant = variant;}

	@Override
	public void setRightShoulderVariant(int variant) {this.rightShoulderVariant = variant;}

	@Override
	public void setRightShoulderAge(int rightAge) {this.rightShoulderAge = rightAge;}

	@Override
	public void setLeftShoulderAge(int leftAge) {this.leftShoulderAge = leftAge;}

	@Override
	public int getLeftShoulderVariant() {return this.leftShoulderVariant;}

	@Override
	public int getRightShoulderVariant() {return this.rightShoulderVariant;}

	@Override
	public NBTTagCompound getLeftShoulderEntity() {return this.leftShoulderEntity;}

	@Override
	public NBTTagCompound getRightShoulderEntity() {return this.rightShoulderEntity;}

	@Override
	public int getRightShoulderAge() {return this.rightShoulderAge;}

	@Override
	public int getLeftShoulderAge() {return this.leftShoulderAge;}

}


code:
package astrotibs.notenoughpets.capabilities.shoulderriding;

import net.minecraft.nbt.NBTBase;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

/**
 * Constructed following McHorse's tutorial at:
 * https://www.planetminecraft.com/blog/forge-tutorial-capability-system/
 * @author AstroTibs
 */
//Added in v2.0.0
public class ShoulderRidingProvider implements ICapabilitySerializable<NBTBase>
{

	@CapabilityInject(IShoulderRiding.class)
	public static Capability<IShoulderRiding> SHOULDER_RIDING = null;

	private IShoulderRiding instance = SHOULDER_RIDING.getDefaultInstance();

	@Override
	public boolean hasCapability(Capability<?> capability, EnumFacing facing)
	{
		return capability == SHOULDER_RIDING;
	}

	@Override
	public <T> T getCapability(Capability<T> capability, EnumFacing facing)
	{
		return capability == SHOULDER_RIDING ? SHOULDER_RIDING.<T> cast(this.instance) : null;
	}

	@Override
	public NBTBase serializeNBT()
	{
		return SHOULDER_RIDING.getStorage().writeNBT(SHOULDER_RIDING, this.instance, null);
	}

	@Override
	public void deserializeNBT(NBTBase nbt)
	{
		SHOULDER_RIDING.getStorage().readNBT(SHOULDER_RIDING, this.instance, null, nbt);
	}

}


code:
package astrotibs.notenoughpets.capabilities.shoulderriding;

import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.Capability.IStorage;

/**
 * Constructed following McHorse's tutorial at:
 * https://www.planetminecraft.com/blog/forge-tutorial-capability-system/
 * @author AstroTibs
 */
//Added in v2.0.0
public class ShoulderRidingStorage implements IStorage<IShoulderRiding>
{
	public final static String KEY_TAGGROUPNAME = "shoulderriding";

	public final static String KEY_LEFTSHOULDERENTITY = "LeftShoulderEntity";
	public final static String KEY_LEFTSHOULDERVARIANT = "LeftShoulderVariant";
	public final static String KEY_LEFTSHOULDERAGE = "LeftShoulderAge";

	public final static String KEY_RIGHTSHOULDERENTITY = "RightShoulderEntity";
	public final static String KEY_RIGHTSHOULDERVARIANT = "RightShoulderVariant";
	public final static String KEY_RIGHTSHOULDERAGE = "RightShoulderAge";

	@Override
	public NBTBase writeNBT(Capability<IShoulderRiding> capability, IShoulderRiding instance, EnumFacing side)
	{
		NBTTagCompound nbttagcompound1 = new NBTTagCompound(); // This mod's capabilities tag

        nbttagcompound1.setTag(KEY_LEFTSHOULDERENTITY, instance.getLeftShoulderEntity()!=null ? instance.getLeftShoulderEntity() : new NBTTagCompound()); // v2.0.0a - account for null
        nbttagcompound1.setInteger(KEY_LEFTSHOULDERVARIANT, instance.getLeftShoulderVariant());
        nbttagcompound1.setInteger(KEY_LEFTSHOULDERAGE, instance.getLeftShoulderAge());

        nbttagcompound1.setTag(KEY_RIGHTSHOULDERENTITY, instance.getRightShoulderEntity()!=null ? instance.getRightShoulderEntity() : new NBTTagCompound()); // v2.0.0a - account for null
        nbttagcompound1.setInteger(KEY_RIGHTSHOULDERVARIANT, instance.getRightShoulderVariant());
        nbttagcompound1.setInteger(KEY_RIGHTSHOULDERAGE, instance.getRightShoulderAge());

		NBTTagCompound compound = new NBTTagCompound(); // The sub-category for the mod's tag
		compound.setTag(KEY_TAGGROUPNAME, nbttagcompound1);

		return compound;
	}

	@Override
	public void readNBT(Capability<IShoulderRiding> capability, IShoulderRiding instance, EnumFacing side, NBTBase nbt)
	{
		NBTTagCompound compound = ((NBTTagCompound)nbt); // All capabilities tags for this object

		NBTTagCompound nbttagcompound1 = (NBTTagCompound)compound.getTag(KEY_TAGGROUPNAME); // Tag with the ID of the mod's name

		instance.setLeftShoulderEntity(nbttagcompound1.hasKey(KEY_LEFTSHOULDERENTITY) ? (NBTTagCompound)nbttagcompound1.getTag(KEY_LEFTSHOULDERENTITY) : new NBTTagCompound());
		instance.setLeftShoulderVariant(nbttagcompound1.hasKey(KEY_LEFTSHOULDERVARIANT) ? nbttagcompound1.getInteger(KEY_LEFTSHOULDERVARIANT) : 0);
		instance.setLeftShoulderAge(nbttagcompound1.hasKey(KEY_LEFTSHOULDERAGE) ? nbttagcompound1.getInteger(KEY_LEFTSHOULDERAGE) : 0);

		instance.setRightShoulderEntity(nbttagcompound1.hasKey(KEY_RIGHTSHOULDERENTITY) ? (NBTTagCompound)nbttagcompound1.getTag(KEY_RIGHTSHOULDERENTITY) : new NBTTagCompound());
		instance.setRightShoulderVariant(nbttagcompound1.hasKey(KEY_RIGHTSHOULDERVARIANT) ? nbttagcompound1.getInteger(KEY_RIGHTSHOULDERVARIANT) : 0);
		instance.setRightShoulderAge(nbttagcompound1.hasKey(KEY_RIGHTSHOULDERAGE) ? nbttagcompound1.getInteger(KEY_RIGHTSHOULDERAGE) : 0);
	}

}