From 66270715acfe41bb108ad85e8df8e526abbcd799 Mon Sep 17 00:00:00 2001 From: KAMKEEL Date: Tue, 4 May 2021 03:52:44 -0400 Subject: [PATCH] Updating Texture Sizes Attempting to implement a selective renderer to allow for 64x64 Skin Url type for mobs. --- src/main/java/noppes/npcs/DataDisplay.java | 6 +- .../noppes/npcs/client/ImageDownloadAlt.java | 4 +- .../npcs/client/ImageDownloadAlt32.java | 175 ++++++++++++++++++ .../client/gui/mainmenu/GuiNpcDisplay.java | 10 +- .../client/gui/model/GuiCreationScreen.java | 6 + .../npcs/client/gui/model/GuiModelBody.java | 22 ++- .../noppes/npcs/client/model/ModelMPM.java | 97 +++++++++- .../npcs/client/model/part/ModelHeadwear.java | 45 +++++ .../npcs/client/model/part/ModelLegs.java | 12 +- .../model/part/legs/ModelMermaidLegs.java | 5 + .../model/part/legs/ModelMermaidLegs2.java | 8 + .../client/model/part/legs/ModelNagaLegs.java | 6 + .../model/part/tails/ModelDragonTail.java | 1 + .../model/part/tails/ModelSquirrelTail.java | 5 + .../renderer/ImageBufferDownload32.java | 63 +++++++ .../npcs/client/renderer/RenderCustomNpc.java | 2 +- .../client/renderer/RenderNPCHumanMale.java | 4 +- .../client/renderer/RenderNPCInterface.java | 32 +++- .../npcs/entity/EntityNPCInterface.java | 2 - .../textures/parts/legs/mermaid1.png | Bin 481 -> 464 bytes .../customnpcs/textures/parts/legs/naga1.png | Bin 735 -> 709 bytes .../textures/parts/legs/spider1.png | Bin 1993 -> 1963 bytes .../textures/parts/particle/type1.png | Bin 430 -> 238 bytes .../textures/parts/particle/type2.png | Bin 433 -> 230 bytes .../textures/parts/particle/type3.png | Bin 0 -> 234 bytes .../textures/parts/particle/type4.png | Bin 0 -> 231 bytes .../textures/parts/particle/type5.png | Bin 0 -> 234 bytes .../textures/parts/particle/type6.png | Bin 0 -> 229 bytes .../textures/parts/particle/type7.png | Bin 0 -> 213 bytes .../customnpcs/textures/parts/snout/beak1.png | Bin 264 -> 251 bytes .../textures/parts/snout/bunny1.png | Bin 238 -> 226 bytes .../textures/parts/snout/large1.png | Bin 367 -> 354 bytes .../textures/parts/snout/medium1.png | Bin 302 -> 279 bytes .../textures/parts/snout/small1.png | Bin 325 -> 284 bytes .../textures/parts/tail/dragon1.png | Bin 242 -> 190 bytes .../textures/parts/tail/feather1.png | Bin 451 -> 289 bytes .../customnpcs/textures/parts/tail/fin1.png | Bin 384 -> 369 bytes .../textures/parts/tail/rodent1.png | Bin 273 -> 225 bytes .../textures/parts/tail/squirrel1.png | Bin 2886 -> 2794 bytes .../customnpcs/textures/parts/tail/tail1.png | Bin 315 -> 276 bytes .../customnpcs/textures/parts/tail/tail2.png | Bin 424 -> 407 bytes 41 files changed, 487 insertions(+), 18 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/ImageDownloadAlt32.java create mode 100644 src/main/java/noppes/npcs/client/renderer/ImageBufferDownload32.java create mode 100644 src/main/resources/assets/customnpcs/textures/parts/particle/type3.png create mode 100644 src/main/resources/assets/customnpcs/textures/parts/particle/type4.png create mode 100644 src/main/resources/assets/customnpcs/textures/parts/particle/type5.png create mode 100644 src/main/resources/assets/customnpcs/textures/parts/particle/type6.png create mode 100644 src/main/resources/assets/customnpcs/textures/parts/particle/type7.png diff --git a/src/main/java/noppes/npcs/DataDisplay.java b/src/main/java/noppes/npcs/DataDisplay.java index 9fc3c878a..b020de2b5 100644 --- a/src/main/java/noppes/npcs/DataDisplay.java +++ b/src/main/java/noppes/npcs/DataDisplay.java @@ -19,14 +19,14 @@ public class DataDisplay { public String name; public String title = ""; - public byte skinType = 0; //0:normal, 1:player, 2:url + public byte skinType = 0; //0:normal, 1:player, 2:url, 3:url64 public String url = ""; public GameProfile playerProfile; public String texture = "customnpcs:textures/entity/humanmale/Steve.png";; public String cloakTexture = ""; public String glowTexture = ""; - public int visible = 0;//0:visible 1:Invisible 2:semi-invisible + public int visible = 0; //0:visible 1:Invisible 2:semi-invisible public int modelSize = 5; @@ -89,7 +89,6 @@ public class DataDisplay { nbttagcompound.setBoolean("NoLivingAnimation", disableLivingAnimation); nbttagcompound.setByte("BossBar", showBossBar); - // nbttagcompound.setByte("SquareTexture", squareTexture); return nbttagcompound; } @@ -126,7 +125,6 @@ public class DataDisplay { disableLivingAnimation = nbttagcompound.getBoolean("NoLivingAnimation"); showBossBar = nbttagcompound.getByte("BossBar"); - // squareTexture = nbttagcompound.getByte("SquareTexture"); if(prevSkinType != skinType || !texture.equals(prevTexture)) npc.textureLocation = null; diff --git a/src/main/java/noppes/npcs/client/ImageDownloadAlt.java b/src/main/java/noppes/npcs/client/ImageDownloadAlt.java index f32e81c3b..7db25132e 100644 --- a/src/main/java/noppes/npcs/client/ImageDownloadAlt.java +++ b/src/main/java/noppes/npcs/client/ImageDownloadAlt.java @@ -24,7 +24,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) -public class ImageDownloadAlt extends SimpleTexture +public class ImageDownloadAlt32 extends SimpleTexture { private static final Logger logger = LogManager.getLogger(); private static final AtomicInteger threadDownloadCounter = new AtomicInteger(0); @@ -35,7 +35,7 @@ public class ImageDownloadAlt extends SimpleTexture private Thread imageThread; private boolean textureUploaded; - public ImageDownloadAlt(File file, String url, ResourceLocation resource, IImageBuffer buffer) + public ImageDownloadAlt32(File file, String url, ResourceLocation resource, IImageBuffer buffer) { super(resource); this.cacheFile = file; diff --git a/src/main/java/noppes/npcs/client/ImageDownloadAlt32.java b/src/main/java/noppes/npcs/client/ImageDownloadAlt32.java new file mode 100644 index 000000000..f32e81c3b --- /dev/null +++ b/src/main/java/noppes/npcs/client/ImageDownloadAlt32.java @@ -0,0 +1,175 @@ +package noppes.npcs.client; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.imageio.ImageIO; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IImageBuffer; +import net.minecraft.client.renderer.texture.SimpleTexture; +import net.minecraft.client.renderer.texture.TextureUtil; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; + +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class ImageDownloadAlt extends SimpleTexture +{ + private static final Logger logger = LogManager.getLogger(); + private static final AtomicInteger threadDownloadCounter = new AtomicInteger(0); + private final File cacheFile; + private final String imageUrl; + private final IImageBuffer imageBuffer; + private BufferedImage bufferedImage; + private Thread imageThread; + private boolean textureUploaded; + + public ImageDownloadAlt(File file, String url, ResourceLocation resource, IImageBuffer buffer) + { + super(resource); + this.cacheFile = file; + this.imageUrl = url; + this.imageBuffer = buffer; + } + + private void checkTextureUploaded() + { + if (!this.textureUploaded) + { + if (this.bufferedImage != null) + { + if (this.textureLocation != null) + { + this.deleteGlTexture(); + } + + TextureUtil.uploadTextureImage(super.getGlTextureId(), this.bufferedImage); + this.textureUploaded = true; + } + } + } + + public int getGlTextureId() + { + this.checkTextureUploaded(); + return super.getGlTextureId(); + } + + public void setBufferedImage(BufferedImage p_147641_1_) + { + this.bufferedImage = p_147641_1_; + + if (this.imageBuffer != null) + { + this.imageBuffer.func_152634_a(); + } + } + + public void loadTexture(IResourceManager resourceManager) throws IOException + { + if (this.bufferedImage == null && this.textureLocation != null) + { + super.loadTexture(resourceManager); + } + + if (this.imageThread == null) + { + if (this.cacheFile != null && this.cacheFile.isFile()) + { + logger.debug("Loading http texture from local cache ({})", new Object[] {this.cacheFile}); + + try + { + this.bufferedImage = ImageIO.read(this.cacheFile); + + if (this.imageBuffer != null) + { + this.setBufferedImage(this.imageBuffer.parseUserSkin(this.bufferedImage)); + } + } + catch (IOException ioexception) + { + logger.error("Couldn\'t load skin " + this.cacheFile, ioexception); + this.loadTextureFromServer(); + } + } + else + { + this.loadTextureFromServer(); + } + } + } + + protected void loadTextureFromServer() + { + this.imageThread = new Thread("Texture Downloader #" + threadDownloadCounter.incrementAndGet()) + { + private static final String __OBFID = "CL_00001050"; + public void run() + { + HttpURLConnection connection = null; + ImageDownloadAlt.logger.debug("Downloading http texture from {} to {}", new Object[] {ImageDownloadAlt.this.imageUrl, ImageDownloadAlt.this.cacheFile}); + + try + { + connection = (HttpURLConnection)(new URL(ImageDownloadAlt.this.imageUrl)).openConnection(Minecraft.getMinecraft().getProxy()); + connection.setDoInput(true); + connection.setDoOutput(false); + connection.setRequestProperty("Content-Type", "image/png"); + connection.setRequestProperty("Expect", "100-continue"); + //connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0"); + connection.setRequestProperty("User-Agent", "Mozilla/5.0"); + connection.connect(); + + if (connection.getResponseCode() / 100 != 2) + { + return; + } + + BufferedImage bufferedimage; + + if (ImageDownloadAlt.this.cacheFile != null) + { + FileUtils.copyInputStreamToFile(connection.getInputStream(), ImageDownloadAlt.this.cacheFile); + bufferedimage = ImageIO.read(ImageDownloadAlt.this.cacheFile); + } + else + { + bufferedimage = ImageIO.read(connection.getInputStream()); + } + + if (ImageDownloadAlt.this.imageBuffer != null) + { + bufferedimage = ImageDownloadAlt.this.imageBuffer.parseUserSkin(bufferedimage); + } + + ImageDownloadAlt.this.setBufferedImage(bufferedimage); + } + catch (Exception exception) + { + ImageDownloadAlt.logger.error("Couldn\'t download http texture", exception); + } + finally + { + if (connection != null) + { + connection.disconnect(); + } + } + } + }; + this.imageThread.setDaemon(true); + this.imageThread.start(); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/mainmenu/GuiNpcDisplay.java b/src/main/java/noppes/npcs/client/gui/mainmenu/GuiNpcDisplay.java index 8d13ed31b..53a766190 100644 --- a/src/main/java/noppes/npcs/client/gui/mainmenu/GuiNpcDisplay.java +++ b/src/main/java/noppes/npcs/client/gui/mainmenu/GuiNpcDisplay.java @@ -56,7 +56,7 @@ public class GuiNpcDisplay extends GuiNPCInterface2 implements ITextfieldListene addLabel(new GuiNpcLabel(4,"display.texture", guiLeft + 5, y + 5)); addTextField(new GuiNpcTextField(3,this, fontRendererObj, guiLeft + 80, y, 200, 20, display.skinType == 0?display.texture:display.url)); this.addButton(new GuiNpcButton(3, guiLeft + 325, y, 38, 20, "mco.template.button.select")); - this.addButton(new GuiNpcButton(2, guiLeft + 283, y, 40, 20, new String[]{"display.texture","display.player", "display.url"},display.skinType)); + this.addButton(new GuiNpcButton(2, guiLeft + 283, y, 40, 20, new String[]{"display.texture","display.player", "display.url", "display.url64"},display.skinType)); getButton(3).setEnabled(display.skinType == 0); if(display.skinType == 1 && display.playerProfile != null) getTextField(3).setText(display.playerProfile.getName()); @@ -102,7 +102,8 @@ public class GuiNpcDisplay extends GuiNPCInterface2 implements ITextfieldListene display.modelSize = textfield.getInteger(); } else if(textfield.id == 3){ - if(display.skinType == 2) + // SKIN CHANGE + if(display.skinType == 2 || display.skinType == 3) display.url = textfield.getText(); else if(display.skinType == 1){ if(!textfield.isEmpty()){ @@ -137,7 +138,10 @@ public class GuiNpcDisplay extends GuiNPCInterface2 implements ITextfieldListene } if(button.id == 2){ display.skinType = (byte) button.getValue(); - display.url = ""; + // SKIN CHANGE + if (display.skinType != 3){ + display.url = ""; + } display.playerProfile = null; initGui(); } diff --git a/src/main/java/noppes/npcs/client/gui/model/GuiCreationScreen.java b/src/main/java/noppes/npcs/client/gui/model/GuiCreationScreen.java index a4ef5c218..d51f8bcbb 100644 --- a/src/main/java/noppes/npcs/client/gui/model/GuiCreationScreen.java +++ b/src/main/java/noppes/npcs/client/gui/model/GuiCreationScreen.java @@ -270,6 +270,9 @@ public class GuiCreationScreen extends GuiModelInterface implements ICustomScrol // New Button for Changing Models if(button.id == 250){ if(npc.display.modelType == 0){ + if (npc.display.skinType == 2){ + npc.display.skinType = 3; + } npc.display.modelType = 1; } else if(npc.display.modelType == 1){ @@ -277,6 +280,9 @@ public class GuiCreationScreen extends GuiModelInterface implements ICustomScrol } else { npc.display.modelType = 0; + if (npc.display.skinType == 3){ + npc.display.skinType = 2; + } } } diff --git a/src/main/java/noppes/npcs/client/gui/model/GuiModelBody.java b/src/main/java/noppes/npcs/client/gui/model/GuiModelBody.java index 932dce7ba..a1f22ea7c 100644 --- a/src/main/java/noppes/npcs/client/gui/model/GuiModelBody.java +++ b/src/main/java/noppes/npcs/client/gui/model/GuiModelBody.java @@ -15,7 +15,7 @@ public class GuiModelBody extends GuiModelInterface{ private final String[] arrWing = new String[]{"gui.no","Player","Type1","Type2","Type3","Type4","Type5","Type6","Type7","Type8","Type9", "Type10","Type11","Type12","Type13"}; private final String[] arrBreasts = new String[]{"gui.no","Type1","Type2","Type3"}; - private final String[] arrParticles = new String[]{"gui.no","Player","Type1","Type2", "Rainbow"}; + private final String[] arrParticles = new String[]{"gui.no","Player","Type1", "Type2", "Rainbow", "Type3", "Type4", "Type5", "Type6", "Type7"}; private final String[] arrfins = new String[]{"gui.no","Player","Type1","Type2","Type3","Type4","Type5","Type6"}; private final String[] arrskirt = new String[]{"gui.no","Player","Type1"}; @@ -109,6 +109,16 @@ public class GuiModelBody extends GuiModelInterface{ return 2; if(particles.texture.contains("2")) return 3; + if(particles.texture.contains("3")) + return 5; + if(particles.texture.contains("4")) + return 6; + if(particles.texture.contains("5")) + return 7; + if(particles.texture.contains("6")) + return 8; + if(particles.texture.contains("7")) + return 9; } if(particles.type == 1){ return 4; @@ -149,6 +159,16 @@ public class GuiModelBody extends GuiModelInterface{ particles.setTexture("particle/type2", 0); if(value == 4) particles.setTexture("", 1); + if(value == 5) + particles.setTexture("particle/type3", 0); + if(value == 6) + particles.setTexture("particle/type4", 0); + if(value == 7) + particles.setTexture("particle/type5", 0); + if(value == 8) + particles.setTexture("particle/type6", 0); + if(value == 9) + particles.setTexture("particle/type7", 0); } initGui(); } diff --git a/src/main/java/noppes/npcs/client/model/ModelMPM.java b/src/main/java/noppes/npcs/client/model/ModelMPM.java index ef1d22359..dca765973 100644 --- a/src/main/java/noppes/npcs/client/model/ModelMPM.java +++ b/src/main/java/noppes/npcs/client/model/ModelMPM.java @@ -207,7 +207,7 @@ public class ModelMPM extends ModelNPCMale{ } headwear = new ModelHeadwear(this); - legs = new ModelLegs(this, (ModelScaleRenderer)bipedRightLeg, (ModelScaleRenderer)bipedLeftLeg); + legs = new ModelLegs(this, (ModelScaleRenderer)bipedRightLeg, (ModelScaleRenderer)bipedLeftLeg, 64, 64); // bodywear = new ModelBodywear(this); this.bipedBody.addChild(breasts = new ModelBreasts(this)); @@ -234,6 +234,101 @@ public class ModelMPM extends ModelNPCMale{ } } + // Steve 64x32 + public ModelMPM(float par1) { + + super(par1); + isArmor = par1 > 0; + float par2 = 0; + + this.bipedCloak = new ModelRenderer(this, 0, 0); + this.bipedCloak.addBox(-5.0F, 0.0F, -1.0F, 10, 16, 1, par1); + + this.bipedEars = new ModelRenderer(this, 24, 0); + this.bipedEars.addBox(-3.0F, -6.0F, -1.0F, 6, 6, 1, par1); + + this.bipedHead = (new ModelScaleRenderer(this, 0, 0)); + this.bipedHead.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, par1); + this.bipedHead.setRotationPoint(0.0F, 0.0F + par2, 0.0F); + + this.bipedHeadwear = (new ModelScaleRenderer(this, 32, 0)); + this.bipedHeadwear.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, par1 + 0.5F); + this.bipedHeadwear.setRotationPoint(0.0F, 0.0F + par2, 0.0F); + + this.bipedBody = (new ModelScaleRenderer(this, 16, 16)); + this.bipedBody.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, par1); + this.bipedBody.setRotationPoint(0.0F, 0.0F + par2, 0.0F); + + // New Extension + this.bipedBodywear = (new ModelScaleRenderer(this, 16, 32)); + this.bipedBodywear.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, par1 + 0.5F); + this.bipedBody.addChild(this.bipedBodywear); + + this.bipedRightArm = new ModelScaleRenderer(this, 40, 16); + this.bipedRightArm.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, par1); + this.bipedRightArm.setRotationPoint(-5.0F, 2.0F + par2, 0.0F); + + this.bipedLeftArm = new ModelScaleRenderer(this, 40, 16); + this.bipedLeftArm.mirror = true; + this.bipedLeftArm.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, par1); + this.bipedLeftArm.setRotationPoint(5.0F, 2.0F + par2, 0.0F); + + // Arms + this.bipedRightArmwear = (new ModelScaleRenderer(this, 40, 16)); + this.bipedRightArmwear.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, par1 + 0.25F); + this.bipedRightArm.addChild(this.bipedRightArmwear); + + this.bipedLeftArmwear = new ModelScaleRenderer(this, 40, 16); + this.bipedLeftArmwear.mirror = true; + this.bipedLeftArmwear.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, par1 + 0.25F); + this.bipedLeftArm.addChild(this.bipedLeftArmwear); + + this.bipedRightLeg = new ModelScaleRenderer(this, 0, 16); + this.bipedRightLeg.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, par1); + this.bipedRightLeg.setRotationPoint(-1.9F, 12.0F + par2, 0.0F); + + // Legs + this.bipedLeftLeg = new ModelScaleRenderer(this, 0, 16); + this.bipedLeftLeg.mirror = true; + this.bipedLeftLeg.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, par1); + this.bipedLeftLeg.setRotationPoint(1.9F, 12.0F + par2, 0.0F); + + this.bipedRightLegWear = (new ModelScaleRenderer(this, 0, 16)); + this.bipedRightLegWear.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, par1 + 0.25F); + this.bipedRightLeg.addChild(this.bipedRightLegWear); + + this.bipedLeftLegWear = new ModelScaleRenderer(this, 0, 16); + this.bipedLeftArmwear.mirror = true; + this.bipedLeftLegWear.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, par1 + 0.25F); + this.bipedLeftLeg.addChild(this.bipedLeftLegWear); + + headwear = new ModelHeadwear(this, true); + legs = new ModelLegs(this, (ModelScaleRenderer)bipedRightLeg, (ModelScaleRenderer)bipedLeftLeg, 64, 32); + + this.bipedBody.addChild(breasts = new ModelBreasts(this)); + if(!isArmor){ + this.bipedHead.addChild(ears = new ModelEars(this)); + this.bipedHead.addChild(mohawk = new ModelMohawk(this)); + this.bipedHead.addChild(hair = new ModelHair(this)); + this.bipedHead.addChild(beard = new ModelBeard(this)); + + // Completed + this.bipedHead.addChild(snout = new ModelSnout(this)); + this.bipedHead.addChild(horns = new ModelHorns(this)); + + // Completed + tail = new ModelTail(this); + + this.bipedBody.addChild(wings = new ModelWings(this)); + this.bipedBody.addChild(fin = new ModelFin(this)); + + // Fix This + this.bipedBody.addChild(skirt = new ModelSkirt(this)); + this.bipedLeftArm.addChild(clawsL = new ModelClaws(this, false)); + this.bipedRightArm.addChild(clawsR = new ModelClaws(this, true)); + } + } + private void setPlayerData(EntityCustomNpc entity){ if(!isArmor){ mohawk.setData(entity.modelData, entity); diff --git a/src/main/java/noppes/npcs/client/model/part/ModelHeadwear.java b/src/main/java/noppes/npcs/client/model/part/ModelHeadwear.java index fe3c55358..bed9137a8 100644 --- a/src/main/java/noppes/npcs/client/model/part/ModelHeadwear.java +++ b/src/main/java/noppes/npcs/client/model/part/ModelHeadwear.java @@ -52,6 +52,51 @@ public class ModelHeadwear extends ModelScaleRenderer{ this.addChild(bottom); } + public ModelHeadwear(ModelBase base, boolean steve32) { + super(base); + Model2DRenderer right = new Model2DRenderer(base, 32, 8, 8, 8, 64, 32); + right.setRotationPoint(-4.641F, .8f, 4.64f); + right.setScale(0.58f); + right.setThickness(0.65f); + setRotation(right, 0, (float)(Math.PI/2f), 0); + this.addChild(right); + + Model2DRenderer left = new Model2DRenderer(base, 48, 8, 8, 8, 64, 32); + left.setRotationPoint(4.639F, .8f, -4.64f); + left.setScale(0.58f); + left.setThickness(0.65f); + setRotation(left, 0, (float)(Math.PI/-2f), 0); + this.addChild(left); + + Model2DRenderer front = new Model2DRenderer(base, 40, 8, 8, 8, 64, 32); + front.setRotationPoint(-4.64F, .801f, -4.641f); + front.setScale(0.58f); + front.setThickness(0.65f); + setRotation(front, 0, 0, 0); + this.addChild(front); + + Model2DRenderer back = new Model2DRenderer(base, 56, 8, 8, 8, 64, 32); + back.setRotationPoint(4.64F, .801f, 4.639f); + back.setScale(0.58f); + back.setThickness(0.65f); + setRotation(back, 0, (float)(Math.PI), 0); + this.addChild(back); + + Model2DRenderer top = new Model2DRenderer(base, 40, 0, 8, 8, 64, 32); + top.setRotationPoint(-4.64F, -8.5f, -4.64f); + top.setScale(0.5799f); + top.setThickness(0.65f); + setRotation(top, (float)(Math.PI / -2), 0, 0); + this.addChild(top); + + Model2DRenderer bottom = new Model2DRenderer(base, 48, 0, 8, 8, 64, 32); + bottom.setRotationPoint(-4.64F, 0f, -4.64f); + bottom.setScale(0.5799f); + bottom.setThickness(0.65f); + setRotation(bottom, (float)(Math.PI / -2), 0, 0); + this.addChild(bottom); + } + public void setRotation(ModelRenderer model, float x, float y, float z) { model.rotateAngleX = x; model.rotateAngleY = y; diff --git a/src/main/java/noppes/npcs/client/model/part/ModelLegs.java b/src/main/java/noppes/npcs/client/model/part/ModelLegs.java index e72cb6a25..5383015b1 100644 --- a/src/main/java/noppes/npcs/client/model/part/ModelLegs.java +++ b/src/main/java/noppes/npcs/client/model/part/ModelLegs.java @@ -59,7 +59,7 @@ public class ModelLegs extends ModelScaleRenderer{ private ModelMPM base; - public ModelLegs(ModelMPM base, ModelScaleRenderer leg1, ModelScaleRenderer leg2) { + public ModelLegs(ModelMPM base, ModelScaleRenderer leg1, ModelScaleRenderer leg2, int textWidth, int textHeight) { super(base); this.base = base; this.leg1 = leg1; @@ -73,51 +73,61 @@ public class ModelLegs extends ModelScaleRenderer{ float var1 = 0.0F; byte var2 = 15; spiderNeck = new ModelRenderer(base, 0, 0); + spiderNeck.setTextureSize(64,32); spiderNeck.addBox(-3.0F, -3.0F, -3.0F, 6, 6, 6, var1); spiderNeck.setRotationPoint(0.0F, (float)var2, 2.0F); spider.addChild(spiderNeck); spiderBody = new ModelRenderer(base, 0, 12); + spiderBody.setTextureSize(64,32); spiderBody.addBox(-5.0F, -4.0F, -6.0F, 10, 8, 12, var1); spiderBody.setRotationPoint(0.0F, (float)var2, 11.0F); spider.addChild(spiderBody); this.spiderLeg1 = new ModelRenderer(base, 18, 0); + this.spiderLeg1.setTextureSize(64,32); this.spiderLeg1.addBox(-15.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg1.setRotationPoint(-4.0F, (float)var2, 4.0F); spider.addChild(spiderLeg1); this.spiderLeg2 = new ModelRenderer(base, 18, 0); + this.spiderLeg2.setTextureSize(64,32); this.spiderLeg2.addBox(-1.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg2.setRotationPoint(4.0F, (float)var2, 4.0F); spider.addChild(spiderLeg2); this.spiderLeg3 = new ModelRenderer(base, 18, 0); + this.spiderLeg3.setTextureSize(64,32); this.spiderLeg3.addBox(-15.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg3.setRotationPoint(-4.0F, (float)var2, 3.0F); spider.addChild(spiderLeg3); this.spiderLeg4 = new ModelRenderer(base, 18, 0); + this.spiderLeg4.setTextureSize(64,32); this.spiderLeg4.addBox(-1.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg4.setRotationPoint(4.0F, (float)var2, 3.0F); spider.addChild(spiderLeg4); this.spiderLeg5 = new ModelRenderer(base, 18, 0); + this.spiderLeg5.setTextureSize(64,32); this.spiderLeg5.addBox(-15.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg5.setRotationPoint(-4.0F, (float)var2, 2.0F); spider.addChild(spiderLeg5); this.spiderLeg6 = new ModelRenderer(base, 18, 0); + this.spiderLeg6.setTextureSize(64,32); this.spiderLeg6.addBox(-1.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg6.setRotationPoint(4.0F, (float)var2, 2.0F); spider.addChild(spiderLeg6); this.spiderLeg7 = new ModelRenderer(base, 18, 0); + this.spiderLeg7.setTextureSize(64,32); this.spiderLeg7.addBox(-15.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg7.setRotationPoint(-4.0F, (float)var2, 1.0F); spider.addChild(spiderLeg7); this.spiderLeg8 = new ModelRenderer(base, 18, 0); + this.spiderLeg8.setTextureSize(64,32); this.spiderLeg8.addBox(-1.0F, -1.0F, -1.0F, 16, 2, 2, var1); this.spiderLeg8.setRotationPoint(4.0F, (float)var2, 1.0F); spider.addChild(spiderLeg8); diff --git a/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs.java b/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs.java index 75dd2e915..9de42c1a7 100644 --- a/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs.java +++ b/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs.java @@ -29,29 +29,34 @@ public class ModelMermaidLegs extends ModelRenderer { textureHeight = 32; top = new ModelRenderer(base, 0, 16); + top.setTextureSize(64,32); top.addBox(-2F, -2.5F, -2F, 8, 9, 4); top.setRotationPoint(-2F, 14F, 1F); setRotation(top, 0.26F, 0F, 0F); middle = new ModelRenderer(base, 28, 0); + middle.setTextureSize(64,32); middle.addBox(0F, 0F, 0F, 7, 6, 4); middle.setRotationPoint(-1.5F, 6.5F, -1F); setRotation(middle, 0.86f, 0F, 0F); top.addChild(middle); bottom = new ModelRenderer(base, 24, 16); + bottom.setTextureSize(64,32); bottom.addBox(0F, 0F, 0F, 6, 7, 3); bottom.setRotationPoint(0.5F, 6F, 0.5f); setRotation(bottom, 0.15f, 0F, 0F); middle.addChild(bottom); fin1 = new ModelRenderer(base, 0, 0); + fin1.setTextureSize(64,32); fin1.addBox(0F, 0F, 0F, 5, 9, 1); fin1.setRotationPoint(0F, 4.5F, 1F); setRotation(fin1, 0.05f, 0, 0.5911399F); bottom.addChild(fin1); fin2 = new ModelRenderer(base, 0, 0); + fin2.setTextureSize(64,32); fin2.mirror = true; fin2.addBox(-5F, 0F, 0F, 5, 9, 1); fin2.setRotationPoint(6F, 4.5F, 1F); diff --git a/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs2.java b/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs2.java index 6af4e1fee..ed1ea7b16 100644 --- a/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs2.java +++ b/src/main/java/noppes/npcs/client/model/part/legs/ModelMermaidLegs2.java @@ -29,47 +29,55 @@ public class ModelMermaidLegs2 extends ModelRenderer { textureHeight = 32; Tail1 = new ModelRenderer(base, 0, 18); + Tail1.setTextureSize(64,32); Tail1.addBox(0F, 0F, 0F, 8, 6, 4); Tail1.setRotationPoint(-4F, 12F, -2F); setRotation(Tail1, 0.075F, 0F, 0F); Tail2 = new ModelRenderer(base, 0, 18); + Tail2.setTextureSize(64,32); Tail2.addBox(0F, 0F, 0F, 6, 5, 3); Tail2.setRotationPoint(1F, 5.5F, 0.3F); setRotation(Tail2, 0.56F, 0F, 0F); Tail1.addChild(Tail2); Tail3 = new ModelRenderer(base, 0, 18); + Tail3.setTextureSize(64,32); Tail3.addBox(0F, 0F, 0F, 5, 5, 2); Tail3.setRotationPoint(5.5F, 4F, 2.5F); setRotation(Tail3, -0.37818F, 3.141593F, 0F); Tail2.addChild(Tail3); Tail4 = new ModelRenderer(base, 0, 20); + Tail4.setTextureSize(64,32); Tail4.addBox(0F, 0F, 0F, 4, 3, 1); Tail4.setRotationPoint(0.5F, 4.5F, 0.5F); setRotation(Tail4, -0.1f, 0, 0F); Tail3.addChild(Tail4); Tail5 = new ModelRenderer(base, 0, 20); + Tail5.setTextureSize(64,32); Tail5.addBox(0F, 0F, 0F, 1, 3, 1); Tail5.setRotationPoint(-1F, 1.5F, 0F); setRotation(Tail5, 0, 0, 0F); Tail4.addChild(Tail5); Tail6 = new ModelRenderer(base, 0, 20); + Tail6.setTextureSize(64,32); Tail6.addBox(0F, 0F, 0F, 1, 3, 1); Tail6.setRotationPoint(-2F, 3F, 0F); setRotation(Tail6, 0, 0, 0F); Tail4.addChild(Tail6); Tail7 = new ModelRenderer(base, 0, 20); + Tail7.setTextureSize(64,32); Tail7.addBox(0F, 0F, 0F, 1, 3, 1); Tail7.setRotationPoint(4F, 1.5F, 0F); setRotation(Tail7, 0, 0, 0F); Tail4.addChild(Tail7); Tail8 = new ModelRenderer(base, 0, 20); + Tail8.setTextureSize(64,32); Tail8.addBox(0F, 0F, 0F, 1, 3, 1); Tail8.setRotationPoint(5F, 3F, 0F); setRotation(Tail8, 0, 0, 0F); diff --git a/src/main/java/noppes/npcs/client/model/part/legs/ModelNagaLegs.java b/src/main/java/noppes/npcs/client/model/part/legs/ModelNagaLegs.java index 238971fd5..8d23ef5af 100644 --- a/src/main/java/noppes/npcs/client/model/part/legs/ModelNagaLegs.java +++ b/src/main/java/noppes/npcs/client/model/part/legs/ModelNagaLegs.java @@ -25,8 +25,10 @@ public class ModelNagaLegs extends ModelRenderer{ super(base); nagaPart1 = new ModelRenderer(base,0,0); + nagaPart1.setTextureSize(64,32); ModelRenderer legPart = new ModelRenderer(base,0,16); + legPart.addBox(0, -2, -2, 4, 4, 4); legPart.setRotationPoint(-4, 0, 0); nagaPart1.addChild(legPart); @@ -36,9 +38,11 @@ public class ModelNagaLegs extends ModelRenderer{ nagaPart1.addChild(legPart); nagaPart2 = new ModelRenderer(base,0,0); + nagaPart2.setTextureSize(64,32); nagaPart2.childModels = nagaPart1.childModels; nagaPart3 = new ModelRenderer(base,0,0); + nagaPart3.setTextureSize(64,32); ModelPlaneRenderer plane = new ModelPlaneRenderer(base, 4, 24); plane.addBackPlane(0,-2, 0, 4, 4); @@ -89,9 +93,11 @@ public class ModelNagaLegs extends ModelRenderer{ nagaPart3.addChild(plane); nagaPart4 = new ModelRenderer(base,0,0); + nagaPart4.setTextureSize(64,32); nagaPart4.childModels = nagaPart3.childModels; nagaPart5 = new ModelRenderer(base,0,0); + nagaPart5.setTextureSize(64,32); legPart = new ModelRenderer(base,56,20); legPart.addBox(0, 0, -2, 2, 5, 2); diff --git a/src/main/java/noppes/npcs/client/model/part/tails/ModelDragonTail.java b/src/main/java/noppes/npcs/client/model/part/tails/ModelDragonTail.java index ee356aaba..09b4c86e3 100644 --- a/src/main/java/noppes/npcs/client/model/part/tails/ModelDragonTail.java +++ b/src/main/java/noppes/npcs/client/model/part/tails/ModelDragonTail.java @@ -14,6 +14,7 @@ public class ModelDragonTail extends ModelRenderer { int y = 16; ModelRenderer dragon = new ModelRenderer(base, x, y); + dragon.setTextureSize(64,32); dragon.setRotationPoint(0F, 0F, 3F); this.addChild(dragon); diff --git a/src/main/java/noppes/npcs/client/model/part/tails/ModelSquirrelTail.java b/src/main/java/noppes/npcs/client/model/part/tails/ModelSquirrelTail.java index fbd72b42d..bfce7c823 100644 --- a/src/main/java/noppes/npcs/client/model/part/tails/ModelSquirrelTail.java +++ b/src/main/java/noppes/npcs/client/model/part/tails/ModelSquirrelTail.java @@ -16,30 +16,35 @@ public class ModelSquirrelTail extends ModelRenderer { textureHeight = 32; ModelRenderer Shape1 = new ModelRenderer(base, 0, 0); + Shape1.setTextureSize(64,32); Shape1.addBox(-1F, -1F, -1F, 2, 2, 3); Shape1.setRotationPoint(0F, -1F, 3F); setRotation(Shape1, 0F, 0F, 0F); this.addChild(Shape1); ModelRenderer Shape2 = new ModelRenderer(base, 0, 9); + Shape2.setTextureSize(64,32); Shape2.addBox(-2F, -5F, -1F, 4, 5, 3); Shape2.setRotationPoint(0F, 0F, 1F); setRotation(Shape2, -0.37F, 0F, 0F); Shape1.addChild(Shape2); ModelRenderer Shape3 = new ModelRenderer(base, 0, 18); + Shape3.setTextureSize(64,32); Shape3.addBox(-2.466667F, -6F, -1F, 5, 7, 3); Shape3.setRotationPoint(0F, -5F, 0F); setRotation(Shape3, 0.3f, 0F, 0F); Shape2.addChild(Shape3); ModelRenderer Shape4 = new ModelRenderer(base, 25, 0); + Shape4.setTextureSize(64,32); Shape4.addBox(-3F, -0.6F, -1F, 6, 5, 3); Shape4.setRotationPoint(0F, -5F, 1F); setRotation(Shape4, 2.5F, 0F, 0F); Shape3.addChild(Shape4); ModelRenderer Shape5 = new ModelRenderer(base, 25, 10); + Shape5.setTextureSize(64,32); Shape5.addBox(-3F, -2F, -1F, 6, 3, 5); Shape5.setRotationPoint(0F, 3.5F, 0F); setRotation(Shape5, -2.5F, 0F, 0F); diff --git a/src/main/java/noppes/npcs/client/renderer/ImageBufferDownload32.java b/src/main/java/noppes/npcs/client/renderer/ImageBufferDownload32.java new file mode 100644 index 000000000..c8765baee --- /dev/null +++ b/src/main/java/noppes/npcs/client/renderer/ImageBufferDownload32.java @@ -0,0 +1,63 @@ +package noppes.npcs.client.renderer; + +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.awt.image.ImageObserver; + +import net.minecraft.client.renderer.ImageBufferDownload; + +public class ImageBufferDownload32 extends ImageBufferDownload { + private int imageData[]; + private int imageWidth; + private int imageHeight; + + @Override + public BufferedImage parseUserSkin(BufferedImage bufferedimage) { + + imageWidth = bufferedimage.getWidth(null); + imageHeight = imageWidth/2; + + BufferedImage bufferedimage1 = new BufferedImage(imageWidth, imageHeight, 2); + Graphics g = bufferedimage1.getGraphics(); + g.drawImage(bufferedimage, 0, 0, null); + g.dispose(); + imageData = ((DataBufferInt) bufferedimage1.getRaster().getDataBuffer()).getData(); + + setAreaTransparent(imageWidth / 2, 0, imageWidth, imageHeight / 2); + + return bufferedimage1; + } + + /** + * Makes the given area of the image transparent if it was previously completely opaque (used to remove the outer + * layer of a skin around the head if it was saved all opaque; this would be redundant so it's assumed that the skin + * maker is just using an image editor without an alpha channel) + */ + private void setAreaTransparent(int par1, int par2, int par3, int par4) { + if (!this.hasTransparency(par1, par2, par3, par4)) { + for (int i1 = par1; i1 < par3; ++i1) { + for (int j1 = par2; j1 < par4; ++j1) { + this.imageData[i1 + j1 * this.imageWidth] &= 16777215; + } + } + } + } + + /** + * Returns true if the given area of the image contains transparent pixels + */ + private boolean hasTransparency(int par1, int par2, int par3, int par4) { + for (int i1 = par1; i1 < par3; ++i1) { + for (int j1 = par2; j1 < par4; ++j1) { + int k1 = this.imageData[i1 + j1 * this.imageWidth]; + + if ((k1 >> 24 & 255) < 128) { + return true; + } + } + } + + return false; + } +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/client/renderer/RenderCustomNpc.java b/src/main/java/noppes/npcs/client/renderer/RenderCustomNpc.java index e962de122..57e9dd460 100644 --- a/src/main/java/noppes/npcs/client/renderer/RenderCustomNpc.java +++ b/src/main/java/noppes/npcs/client/renderer/RenderCustomNpc.java @@ -29,7 +29,7 @@ public class RenderCustomNpc extends RenderNPCHumanMale{ // Default Renderer public RenderCustomNpc() { - super(new ModelMPM(0, false, false), new ModelMPM(1,false, false), new ModelMPM(0.5f, false, false)); + super(new ModelMPM(0), new ModelMPM(1), new ModelMPM(0.5f)); } @Override diff --git a/src/main/java/noppes/npcs/client/renderer/RenderNPCHumanMale.java b/src/main/java/noppes/npcs/client/renderer/RenderNPCHumanMale.java index 5676e7a50..1675cd566 100644 --- a/src/main/java/noppes/npcs/client/renderer/RenderNPCHumanMale.java +++ b/src/main/java/noppes/npcs/client/renderer/RenderNPCHumanMale.java @@ -38,8 +38,8 @@ public class RenderNPCHumanMale extends RenderNPCInterface protected ModelNPCMale modelArmorChestplate; protected ModelNPCMale modelArmor; - protected final ModelNPCMale OGmodelArmorChestplate = new ModelMPM(1, false, false); - protected final ModelNPCMale OGmodelArmor = new ModelMPM(0.5f, false, false); + protected final ModelNPCMale OGmodelArmorChestplate = new ModelMPM(1); + protected final ModelNPCMale OGmodelArmor = new ModelMPM(0.5f); protected final ModelMPM steve = new ModelMPM(0, true, false); protected final ModelMPM steveArmorChestplate = new ModelMPM(1, true, false); diff --git a/src/main/java/noppes/npcs/client/renderer/RenderNPCInterface.java b/src/main/java/noppes/npcs/client/renderer/RenderNPCInterface.java index a3b27f81d..73a73db52 100644 --- a/src/main/java/noppes/npcs/client/renderer/RenderNPCInterface.java +++ b/src/main/java/noppes/npcs/client/renderer/RenderNPCInterface.java @@ -20,6 +20,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.boss.BossStatus; import net.minecraft.util.ResourceLocation; import noppes.npcs.client.ImageDownloadAlt; +import noppes.npcs.client.ImageDownloadAlt32; import noppes.npcs.client.model.ModelMPM; import noppes.npcs.constants.EnumAnimation; import noppes.npcs.constants.EnumStandingType; @@ -289,7 +290,29 @@ public class RenderNPCInterface extends RenderLiving{ sb.append(String.format("%02x", b&0xff)); } npc.textureLocation = new ResourceLocation("skins/" + sb.toString()); + + loadSkin32(null, npc.textureLocation, npc.display.url); + + LastTextureTick = 0; + } + catch(Exception ex){ + + } + } + // SKIN CHANGE + // For 64 x 64 Textures + else if(npc.display.skinType == 3){ + try{ + MessageDigest digestion = MessageDigest.getInstance("MD5"); + byte[] hash = digestion.digest(npc.display.url.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(2*hash.length); + for(byte b : hash){ + sb.append(String.format("%02x", b&0xff)); + } + npc.textureLocation = new ResourceLocation("skins/" + sb.toString()); + loadSkin(null, npc.textureLocation, npc.display.url); + LastTextureTick = 0; } catch(Exception ex){ @@ -302,11 +325,18 @@ public class RenderNPCInterface extends RenderLiving{ return npc.textureLocation; } - // True = 64x64 Skin + // 64x64 Skin private void loadSkin(File file, ResourceLocation resource, String par1Str){ TextureManager texturemanager = Minecraft.getMinecraft().getTextureManager(); ITextureObject object = new ImageDownloadAlt(file, par1Str, SkinManager.field_152793_a, new ImageBufferDownloadAlt()); texturemanager.loadTexture(resource, object); } + // SORT OF WORKS + private void loadSkin32(File file, ResourceLocation resource, String par1Str){ + TextureManager texturemanager = Minecraft.getMinecraft().getTextureManager(); + ITextureObject object = new ImageDownloadAlt32(file, par1Str, SkinManager.field_152793_a, new ImageBufferDownload32()); + texturemanager.loadTexture(resource, object); + } + } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index 32b1107d3..d3a2ddcb2 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -167,8 +167,6 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti private int taskCount = 1; public int lastInteract = 0; - public int animationStart = 0; - public Faction faction; //should only be used server side private EntityAIRangedAttack aiRange; diff --git a/src/main/resources/assets/customnpcs/textures/parts/legs/mermaid1.png b/src/main/resources/assets/customnpcs/textures/parts/legs/mermaid1.png index 4fcc9080c9a52f14104f6c9e991351ae1cb9036b..48ad62dca675e3ab452b9fc35ee76fdbd59a55fa 100644 GIT binary patch delta 297 zcmV+^0oMNE1JDDI7YZN<0{{R3l|zoUks*kG!T4!K~zXf?UUPX z!axi}N3?~MCR_6VKa1@>EY1aSmC8epw23vAXHBq`8CM_$hzV))@%gpYZr61k+5{>A zF(G;Vx55E!0+oQ6kZOH6piPLn24X_0_0a=bL;D}?)%U$U&ml>WqW}6tYYft$p_F0* z&vTP20UCd|FI<~Kl2GfrIt^%zLn#NYO(98Gw0$rC2Cp*kY05-qDkCjD0TxL_K~z{r?UUPX z!axi}N4=5KWJ~`4XKQ;8i*u=6HIG`tjZ-Nnu1z6H*tGpqy1`!=_%vlAvy_pxJg|YyuI-QQ zPzzk$A|G;JH9tAF*|q(#9clp;D`Lof)%@i6Av!QSw>$?_tcY9pj+vRATb=_dRzwGT z$4s!gvjg&1`L+Y{SNVMhyzizPbOWawbOWawbOWay8*~HbzYXU33xcZi%Wws=fdBvi M07*qoM6N<$f{w3;+W-In diff --git a/src/main/resources/assets/customnpcs/textures/parts/legs/naga1.png b/src/main/resources/assets/customnpcs/textures/parts/legs/naga1.png index cb7e853a636e290e87b7cb162bdfeda9520fd341..21f4c0f2444f81f92e1145630e6440b2cae3ea49 100644 GIT binary patch delta 360 zcmV-u0hj*Y1;quB7YZN<0{{R3l|zoUu_06ef5HF&4#EKyC`y0;00AyZL_t(YOYM%? zQiCu6Mbi+9HEI?KG>}-tB2brFcU#-K@c-W=OMC{#H;40h?#!7Bia#<0hCsy-_&#bw3eTU`rYAtkAglsNA%QG7GQI;^ ze@ayb2oXZ_vzZ_GOhxv&SvwFb9hL!~Y71Yu^Mq0+F}yTuD=E(Mg-mf3D6jCV>(rkT z3*MN$6&522a~6X%tghT9!l7v>W5?{RP!fdkk`mBdxmyttXv8@(dn-&x5k^da=F0tw zNsI7@M{f33qAW&g8D*fk^7KrU@LrOnQgh%J&|GrMYabLHK2(8Awt`ONsv zfZcw#%;3jJE6dsNPi%Z=0Q{Qd!uy_Uoq7o$+s1dKD1HFO0rHYA4GS&+0000Xgb7YaZK0{{R3owtGPu_06ef5QL(4#NS*Z>VGd00BrzL_t(oN9~kb zPlGTRhPzURvubHwVTINq4q@{!=h@B8)BgW&l0v-(G7}Ti=kocIC-2nUzv_n0dH^M?w3@iBUJz&93Elf)5>(DUciorJP1dX=?D-aigf@<#E}Dg zf5x{!2_ee>A)G6AG7h7V%EUc2*A}Ew#bqG$m4nZQlg#(2!0_B$8_97oorxUlKskk7 zT;}13IPl8c8=)x@a7t5<$9l?j#yvleMe3P*BR+}ZbnX*SPq|qT9x22aGWSL(7d%cV z2lbTO1r-iqclXTP8%c^3$$3(MddkBiY>_;8%CgphA3#0j`9%sZTP|1K1ND^Gp@(MS zdd156_y7O^ diff --git a/src/main/resources/assets/customnpcs/textures/parts/legs/spider1.png b/src/main/resources/assets/customnpcs/textures/parts/legs/spider1.png index b7f5d7dcb4e4b5ad098c2e873f9ea517c2276acb..8d4d88a678e81dc7d740b236c9cbb5e9dba65f49 100644 GIT binary patch delta 1410 zcmV-|1%3L-533K57YZN<0{{R3l|zoUu^}h|f5HF&4#EKyC`y0;00lrvL_t(YOLdg} zU)n|-#}P=uw2k3_5RZ%aNPrwk%0uFYQPj+~=p?1K%V2d0hxh=}*={TR_d6>-z3Se- z@pVV*^z;n~^Agnb@({^BLa&har2Pb7tuI1gc(LsBxqqlL`k ze@*6wsUQ*zEiE(5Y?O^KlSwMGl3HC^n`5){GD^rfAzx4wtQ6I}Cgm3N+)d_&so)hG zEiFf9nGh9(=A?3^3bdpl#A8BoesygwWO56s#X#semwK5=y-a0qQrFy8u)bW1GE6i` z1#_WHb|v%E%8M77#h){aE2&y&&Xf~Le|g@NWwe0e8>V%Wx@Ica3^S$Z3=<44zoKXG z6iR-pzMYig^_^WC;Dmeot@on-imMK-`GHXD@}(dfktB~ zyw2{0*(GK#TxzVXt?eIdmKb(Ae+MXn`md6lEGpY}ey4t40gY2Zq_MQL|C(W#e|;vz zFngtg9|VWZnDed$->b%vtsH*17p$}EY;bv|5f1N1m}gOzrT1ZueM0b2bLtWgRO2^S z%iC}|JPAa8k3=>jvn48+Sq`y5Hb@2GgYb0z4z-Otog`l_m;Z1+mFxEcHcWT0e$ZgA zD+mQC%Re+BU8y&x21>9YG&5REL;HZsu=vl)!8Pv`GY?W$ch zpaGO48yFvw)8X4T-e7u$ZsvSBg}MZKJIBAo~g@705MHa%4e#5+R673D8Dx}O(}!-#gn>ne+;URE9jkT z*wWD|f!#KSL^OS5lrcU7;G%EWPr#vc(Fcl(F$Qt9=%`zG>ybb#I2teNek~~vT+K{c zy4aKF(;IQY=${^6^e_5+|FnACX;xfY+A2DgCVpIjhzyJOMVu0RIE4Bo-VjGX`#?U5E-bf(Aw_+bqQJNKt49zFZZJqpym5^|uNFS4#O%0m$yy z>M_`PB;W@~BtDX}M3xkugPvx!&dz8X1BPP!^HphG{i}59U*3M(e}3}~ez0v-&F=&d zqDPHT*BiwN?;(rO4?PZ{@0+G2W>bwNL4~H@6J=w}$3{e(sWy2MZ3uH3Bu9Q^um0 zt)>Fg5dZ)H delta 1441 zcmV;S1z!5A56KUZ7YaZK0{{R3owtGPu^}h|f5QL(4#NS*Z>VGd00mx2L_t(oN9~l` zd)hV_hY8?9+}1Gyj3eZbBL*yNmxG;+kdV|%TapErrkw|CW+Orl5W2M63jh6-h8%dB z-RyEt-aAXr@6{)LvV7xj%=iOAhItYS2WMx;WA>@<>9gk?JI6;rG!_>U;yi>&4oUGC ze~%VYi`SWJCW4SZu(ZrDvtc&GjK_)8N@8_oZH`UP%P1yigltYxu##7^nv_}4GuN4G zCW04ixUd|aWdc+Xn3Ia7GSK3N5RC}&`PH?#fXOW+7JY%IT;h2u@jQ{fPF-6O$EE6<*#7Jp1Ft|Tgfe>qc*#pQWZmeB%=ZkW~U)D;uKW{@d_XBfYK z`2{_LhfuOxwe7eZt?j(DK=vnoGJGT04f+d#kl!B+y!sab*x7lx%~zva+1D0O-$;|; zv9DfV3a+!eL3WAR4HoKaYioP^n+1lQ%-;g?p!TyQ$MedzmEEb`RY2oZ5UMXNf9<_u z7-o+NFwAaY|2x4!BVxa8!gs21XekHp?*!}YI_qDasRx65A?8V#W$AsGV;>NF(CnJT z1J(G&(Xtkt43B-GUqhkI&}@MUW|jl2pY>Bga6dSizeR1~c00}&i^bpUkHy-ZfDO_e ztnb&^s|o^s3NyRQGT#ZZdG)9qe}{?z4lM!vekTa{S-R{V6@){}w2e$Sz-;=%>y!Cg zRI6;24QK%6&;rK$_+^`PM{8fZrAlh=t%-F;)Zf?+_S7QI4K?+PTJWX0>yWRrYS}6e=dJqQ;tA+ zx`OVRhO0VSC9u=Nkcg&-j3UOT0G#)%+A%ng&U-*nF~%UO=52KgZ%qlroUQSq?p5M) z-_gu?RTsPRd~zcy7`>CD^WJ%n@12y7+KrN9Nn3fl)WFjfh{&k&o`@5I2M18Uz#HNa zXrJQEXj}m0-bwF-r<)gee?AEz-)g zY9=o!>gC~qit}yRqI=4LX#sL2u>(=ALQvmmrW?5k9x4j$z~{@nari}%FaK15?@}oq zC;(Y)OFaTRQv$w^MB*ViO=L;oIp}KD=IJSIqt8%`zrHBV%fFR&f9>;|uiLM`!uOV? zs@WYMLiDH+>bS!w;ayZE^h1wA=y|4D71N3OlAuD<>x!~5;^fIn_weOP4MOOhfgM7k z5LZc+DjnLWjOodqCz~Qr5hp?p8IbcPseAZh8xhSz{BTH!~|pSH>DC01RK*ax*ykjNB}O3i?cI_3|*MB5v~xZ z;fyj8#dIaHma5n5DS9-}L}*kUcn=+7l#qtgDnXbrxib$|e}=G%A)p5niEx#Qo=$V5 z33(H_Ro(IKJ?A(05{YCoHlO?`in^{sROuoaNych27K?1?bm68ebW07>lSZ2DJ=6s* zebok;cHct^auW{rphU#V#)dgU2=YTR=r){B9Y>4U=%Fo0UFf=mNRXn8Nb&=1KtBpQ zu-~Vb0b^Mwf2h>ZT}RW-(CtHZhfl9mR@0owahzDaFzr}tWMVupMS2lONW&U}-3(7S zT7j80Zy)nJe1ZTj=r2l!P#zf>J0{6qUlTff2g%TF4m-$`I5;#t;+ZN(CaHT&{Y?Lb vN5P}uibuht;EG4Vqu`21!T&%o9{&Tet@@ctK-<^=3jhEBNkvXXu0mjf9j~;VwT!Eq;9UYf1Uj{Pv z#$Iv(QY6$|7UQ}TKNUY=PdAuEM{Qf+Y7>s?!PCj1qw!cx;Tb-c)y+CD8``3 z;pD#O|6Jxc^$D)s7rny%O;~?8>Ht#+_Yd<0>(0o|2sp{5@gd)z4*}Q$iB} DO0P$x literal 430 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DkxK$!8B)5ZfpL8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3Q$0figD*u385kI~ zJY5_^D&n3_cI<055McSNT6gk)g}~{G+-?WgedSw2xI|t#_fI)rIWH?8F_rK2%&$tid$ox7{65_R}sQ0gx zlkN0upt9l@Q|!|iRo<=5jEw2A)}cq=_^(uzCm-p0E}u80_id z7~Vz>b02fR2sq%>YgMRNAd%L{I)zm%fUQyMzFB~M@d5Ekio5J? zHN8^5?&0Jw&!EF1>%nlV;q-m^QU%2sjs8~-?ta30+DUxP;Rlm5f#x%Ky85}Sb4q9e E0H5YbY5)KL literal 433 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=3dtTpz6=aistgPb%?u1b{{!il z3=E|P3=FRl7#OT(FffScPl`Y422{&g;1OBOz`(Z;gc)BsZ9D)JlqzwJC<)F_D=AMb zN@WO0%*-p%^K%VRC^ObG)iX3O_)@fxfq_xb)5S5QBJSy=i(H2c7>@j@zhQp9benVR zjlJbP3}+q5poCF%Cq7^9M$aM1!mbKn5HfhW L`njxgN@xNA)o7mt diff --git a/src/main/resources/assets/customnpcs/textures/parts/particle/type3.png b/src/main/resources/assets/customnpcs/textures/parts/particle/type3.png new file mode 100644 index 0000000000000000000000000000000000000000..17b7ed53e68d750a875dd21a1facc8c74b5b3694 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`c>;VwT!C~)N5|#Mmw}AEv6oyx>PmwAg8%>j&)}f7@(Ym9S>O>_%)r36 z7lawze@|Eo6b$!taSZYBetXeTj6s0M*)jKBeY%kOhv`xCV%@F^tzl#<;Qe47@N_am zx}d_(D)x7OwHTgMuOJX;GE+r&1WKh UMm=QTX`mGhp00i_>zopr0EU!EO#lD@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/customnpcs/textures/parts/particle/type4.png b/src/main/resources/assets/customnpcs/textures/parts/particle/type4.png new file mode 100644 index 0000000000000000000000000000000000000000..fa8feedd636de78933f46535e72f9cfac8b2fdba GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`c>;VwT!C~)N5|#Mmw}AEv6oyx>PmwAg8%>j&)}f7@(Ym9S>O>_%)r36 z7lawze@|Eo6b$inaSZYBetXeTj6s0IHSp{A{ptJrL@St?Ths0y5$a)NTOskFTHz2U zV;swhUknc4!vz*hY*(J6$Z_F+M*|nj5`IP_U4{cs?|paJT3%Jb{EtmcC70v6_))Q< S_(eeT89ZJ6T-G@yGywqaQb?Qt literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/customnpcs/textures/parts/particle/type5.png b/src/main/resources/assets/customnpcs/textures/parts/particle/type5.png new file mode 100644 index 0000000000000000000000000000000000000000..43cc1f96328fe2ed56fe05e8ff8181c5452071a8 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`c>;VwT!C~)N5|#Mmw}AEv6oyx>PmwAg8%>j&)}f7@(Ym9S>O>_%)r36 z7lawze@|Eo6b$!taSZYBetU7FAka$Zz{bDjW(Rryw6?mOKUeM;evrqY!T7*;hZa7D zA67DoTh=kge&b+l5PR47Zv6st14o8mz3TdnSNvEsa#~6_S#~f<9aQyTUYfNn{1`c>;VwT!C~)N5|#Mmw}AEv6oyx>PmwAg8%>j&)}f7@(Ym9S>O>_%)r36 z7lawze@|Eo6b$loaSZYBemh|!FM|TlVTHf{(=Qb?v9o2Z%-QG^=ICb7l*Y23dz)gD z-|vP8b}7y8J_I%FZ*VW!C7aUR!1773(Mzf6NuvX!X#wjN$4?n9!KDlz%fK1sg~ PG@ZfI)z4*}Q$iB}1ZqoR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/customnpcs/textures/parts/particle/type7.png b/src/main/resources/assets/customnpcs/textures/parts/particle/type7.png new file mode 100644 index 0000000000000000000000000000000000000000..a794ed6e654db79061f64d6baca5fd13dd1830dd GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`c>;VwT!C~)N5|#Mmw}AEv6oyx>PmwAg8%>j&)}f7@(Ym9S>O>_%)r36 z7lawze@|Eo6m;@*aSZYBPEJ@R&?9A##lQg}C*(6ID@*V%;db~I{D`TGx1njFOh;am_;OXk;vd$@?2>@$@Id1>} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/customnpcs/textures/parts/snout/beak1.png b/src/main/resources/assets/customnpcs/textures/parts/snout/beak1.png index 2bbaeda2e67e14a3ab8234832fcc131c2b4670aa..c150af24e9fb0338d0b7d2b2f9b2269c222a1a1e 100644 GIT binary patch delta 152 zcmV;J0B8S*0{a1w7YZN<0{{R3l|zoUks(-r!T;Uz!A5j1R002ovPDHK) GLSTZiQa0EC delta 165 zcmey(*ugYGoXdfOnSp^}?)Jtv6BQ%s4>K_E9cDb9zaj-FnCt1{7!u+B_Tp)-1_cq< zi$?GN|1XlWWl>#tWdU2YZ_O0x#i~kS+Lw1_B~PBDUS22gA@O$K!Sm^P0ryYtT)RGv zdFO||rN-~S{o$-ln8qAuyMZUqV#)mmdKI;Vst078I4TmS$7 diff --git a/src/main/resources/assets/customnpcs/textures/parts/snout/bunny1.png b/src/main/resources/assets/customnpcs/textures/parts/snout/bunny1.png index a0d78e8a282809b361936e72dd27509206691d82..98a1af74599877faa2a8ea6d6f7d1fc29cb976d5 100644 GIT binary patch delta 122 zcmaFI_=s_WIF|wkGXn#|ROh~J6BT1p4>2(C9by#K@M-`GI(xb}hIn|tJ?F^9pupjB zan7mV@;iAl(^-UapS?eJ^zb6bO`n|uI2g7vaXQ@6`Ro|~)8Y%?j$Q`FZZLXnzQBs% YRKI@lvlZv9fyOa-y85}Sb4q9e0QJ=?oB#j- delta 134 zcmV;10D1r70qy~i7YaZK0{{R3owtGPks(}h!vFvd!vV){sAK>D08dFoK~z{r?ana@ zz%UF1!AN%W|0l<1L^=h7F==+YQ!(g@B74h2Q3<%W=Dq<~AMJc_&vJZp4ppSI4;bN}ITo(uO|axf{Oz85|W2-R?K(k;g`L> WX5R;gi~E2MVeoYIb6Mw<&;$U%^+SjN diff --git a/src/main/resources/assets/customnpcs/textures/parts/snout/medium1.png b/src/main/resources/assets/customnpcs/textures/parts/snout/medium1.png index c7aa53b0151bac4140692e86ae4c5787214ac9d0..06bbfb749c54bb6a0ecbd0840a9990058b19bb0d 100644 GIT binary patch delta 236 zcmZ3-G@WUJIF|wk8v_HwqPcY~6BQNeISV`@iy0XB4uLSEsD@VqP;!l@i(^QJ^V`d3 zIa>?_+8*j_b5!}s%h^x!i}>*ZyHWx!K+~_{Z#Zpk&kvcu_#Ia{Z}qy@ h?$$sjLctI2OVZ9xMi18N;(-GP&YnH%=;-L;;^OS=?BL)4)N;NhH55n*l?3?(|3?Q5kM{2u z0?Kk0ctjR6Fz_7)VaDV6D^h@h$(}BbArbCxFIeXBH5l-)2AZ+YX;J;YUuWZ#Yl2Np zY0G|}-TY+Xj^4|AJl6Uy=M%W5Tf-1y>NfStvf11!7pr3LGe>@VyhmmG%WFRmZf0Q6 oVPN29IKafP0ml3#t?`u2>j&S|knOuIf%Y+Yy85}Sb4q9e03Dlgpa1{> diff --git a/src/main/resources/assets/customnpcs/textures/parts/snout/small1.png b/src/main/resources/assets/customnpcs/textures/parts/snout/small1.png index e5ddf74a3fc5c453428564696ece732c2cbaf983..152d1437252d3f349bbf702d1c577434b64441f2 100644 GIT binary patch delta 241 zcmX@gG>2(|IF|wk8v_HwqPcY~6BQNeISV`@iy0XB4uLSEsD@VqP;#TEi(^QJ^V>_h ze1{waSRZWPtvTC_(b2<;qp|pkkO|-MQVYiI513lG6RH_lm>Ly2!X`{h-91H%Wn1f# z_r}I~b*xewV)f^I3z@2|DzMh<#HT%HL|X(n+$X#J`myZWq3NGb?oIx_qkX;gju^jm z4kr1%bw4&Qw7+`qi0#guD!vQ1woTczYlk6Q^TQpo+!5!Lr`z)E`E-~2`G+lH*Tinf jKH49_AczdMGJasH+p59(pG#yd(De+Su6{1-oD!M<4cT2x delta 283 zcmbQkbd+g=IF|zlGXn#|-0h8TCMqh_dk6T0xB~gBTKzV51#amLdi(O}(?|DSJbn1` z*`w!=?|<1h z$`EKyYOtUskdiD3@(cct128a}aBT-F;w}Fmrt1#Oa2<%@_51&JY#z4 z=7}d*zdhdb?zo%M|K@&11`P%VR)z%(3?d8-Obh`G46nXB^yu64*ByJeLYNO|6N9HK Lo1e=%r-UW|w*ZFr diff --git a/src/main/resources/assets/customnpcs/textures/parts/tail/dragon1.png b/src/main/resources/assets/customnpcs/textures/parts/tail/dragon1.png index 4406f7c7aa8e4d44eb1ead98cb50b80d4d72e58b..df11b0b09a58cbedf582a0443a957787e96a4bbd 100644 GIT binary patch delta 146 zcmeywxQ}syIF|wk8v_HwqPcY~6BQL|ISV`@iy0XB4uLSEsD@VqP%_xl#W5tq`RxTo zz5@y(E(hmp`87QI=ia2ez*9iw$^xxdx6jP*op%SQlHtd$Yq#F*eINDO?&a0eZ|2vc v43Blp`Kzopr0JhCgrT_o{ diff --git a/src/main/resources/assets/customnpcs/textures/parts/tail/feather1.png b/src/main/resources/assets/customnpcs/textures/parts/tail/feather1.png index 3787065415d0ee2a60a69f442c9130a45bfad878..b8a9973d0219f7c93eef2fc403805af7c05ae463 100644 GIT binary patch delta 259 zcmX@iypU;vxVQobGXn#|ROh~JK#H+A$lZxy-8q?;6BUK)EdzW)T!Eth|NZ;;=I#IA zzyJUL|Mla?ukSxxzjXP{v*&+*{P^?Z=lhp0Up;yH|L>o_KfXV{fB(z-_g_DJ1nOdY zD4qqRgiC__f`J;*0K=x*I~+i1&H|6fVg?4jLmZ~f zz&TLTm2Kj_|B1TF>K)cEbN;;xO`Y5y?9iCbwT4&Xb%4}|gNscBzPDUz*vx(^{simN s##>5W%<20Bq$Yf9V}B;{gHfS~IcQ72BIgJ87@+YCp00i_>zopr0K%|;p#T5? literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DkxL735kHCP2GC{f}XQ4*Y=R#Ki=l*&+$n3-3imzP?iV4`QBXPVk-l*+)s=;-O< z7*Y}U_Nuq{VFwY1hk2hav;6(NtKepi>S?c+;L3^Q@9fwCnB%*|%AtdY6If_So-tc~c%J*Lpf~qEqg- z!{Ii%(?8za_Soor@QT3wKP$N(@SwQhhq#HaapyPxgBIZ>5l-Lzp!B3o;_Stxl^3#K z{G0r_c1Pm6bM+O4x##n%xy+EAe(>ei4(H~gAG>eQ{_oC!Vlal+kOXX#3R!eFdnk02 S=V${1oWax8&t;ucLK6Uc1+@79 diff --git a/src/main/resources/assets/customnpcs/textures/parts/tail/fin1.png b/src/main/resources/assets/customnpcs/textures/parts/tail/fin1.png index 3b3bbc515f6ddcc1e0974e4c50197e9a05bfed03..04898e5e0ba65623c95e7188ea815fe22f02c80f 100644 GIT binary patch delta 234 zcmVYum z9K$Kh8ptu6LJLrCVZDKJ3-bn^$oC7=Pcb+JN86LS^=%@>;1p&Jrr;mEjv%Vu1_F*% z5JlD7KtPB|RJ{!Z#FRzV+dx3dEUMlH0y49x`o{2rFl#vOz(gL==!sy~K!YJ`4e%Xt kxxo^5z#Z`B?*mFX0Y1uQdZ))qNdN!<07*qoM6N<$f`mq5-T(jq delta 249 zcmVD0KrK_K~z{r?ULIH z!yphuv)!0B-v0k{yVk)zsF)@6p|FPy86zBq=#~LJn0CTKK@&JW962l$Gy&gjaQvu& zd`6nEY9ODHCN#n16s|XzoWi<+BXa$N-A^&32^;NC>Yi^CDTXv*)nEz!!Rz!gHS2(6 z;PgSJW*rdt5M^rC0YQjKre+-w#KbZ+>wq9J%hcQ$9uW2#8+TwwF45?UV6TA&L#{Qz zd&KPqmoR||3MMc?!2~8Kn7{-D6PTdz_kx_?2@2JEp3pipAxnA|G#_XddDi}cD_+v^YF~gKN*TZ d+aN&V@g2q`TV2hp*tPsYBA%{(F6*2UngG=tOkn^3 delta 230 zcmaFJIFV_BIF|zlGXn#|-0h8TCMqh_s|WamxB~hA{{8>^_wUy)U*Es~@cqZnKY#xG z{PE-a_wRrH{QmO!%fEmBfNESX75)KIyd^~L}{rmTq@87>K)^Fat+1Ja<%f7#L>(;Wfv$MQ^ zd-ra6@ZdrF-@SWx`Sa&bKt<~N&-@o+CTF7DIJ8JjQM<<+ZK%dcO*I=<#A_S2_N8yi<~#j>VvEVy~}=uroE z|M~OhWp{VC9VCYE`}gnrinKX)>~$D_defxG-(HI7Dc2RK~2#aftZv@tG;%}V~QP((sJ%<;Y z4CM113z>B?deAsw;+LD1L0> zCl(yGtMEe{KJ0MdXAJA($B!*6@wfe~M4K!B17FtqH30tK_F$0LyuQL{1VBPA|V%#i;4o@!`5ge97{U7<{eaq#zQ_5n)46 z^Mp75?c2BJ!e;x*#Tgi{aTXC=B5`+&sh1Be51vZ~}njJ^1larHWLnY*YJSl-2BSR$s zIsi5VAQl_ysbGW=I9u7hCTQ?sJM(2Th({!L;_zduN)oGhp8UglD$OSG6;0B76w5k3 za3hR(d=-oje`2MeY&;iQP6UsSj~h@Bq+BD0T>*GK&kc^O>H$i{*$b*6A3rUX69a*I z z*;xbV)B`FoK)%`b5+{QBZ097X>NV#fI#kyYsP$1qyO$VcI!47E#lc?f`NAKC>n+eb z0;WbN{3PKj5pi@4CtNk02*Ot`ILkpkef$_uMa8SlTJ%sP?f@x+#D@8oclc8`QVlUSl0=nN!~p^ zV)9WO+}O+6d7P5YCno?+AmpgT84v&o5v52w*ZpA04lyQws4b5i|9tHs$zO$5l2=7U zYeMh|<=8nQWiwJy$rs^%d$7?J2p6J892nU>3d0_@T(+^Y3;Ln!MnJDLO)?atER`e_ zm7hI();k1{&J&}mIu?#pj%VyDxHWqj~yUGgsC3X6X5f<3*%aU zZ8Ee7NMQG=uC}VF0u6|u#E`Si{HWqbuxv#{%n9t+xFQJ`35gi9bB$P;lZ3`kT(SKB z`26|v6y!QNd=x-V#yF%feA%+m<>ndCA41;6sfI)l0HiU_nHL-|do~5qe_E;ln}{V4 z!mfg+T70t=CCbKnb^rmz!+|}LlFKiDx%fy*^UU($W!}1mj{>MXEaULn{^Awa5%6QD zK}+rar>6Qq#ysLc09Z$;$ni z1cL=9!k81ol}&KPmMq=`Vq=aEJM)eqQ8y+9lQ_i+p#S?5L^2$J0MHTC5k^pdAf1hl z0AK47K{bsL6^lPyLWzZlHC4ffEgN5ZY&1Cfy6gHr+ZvXg=|2J$HkJ3Ih6!9hHKyd(-gI|v5;VtEMm|8LHqq!|m21P6+$w15a$7Zh*< zRAa9K#%!#y*J6hNLY~-KDrqeO@-b z8E@adohA|Pi2`t+DjFjT+&XgRja@5w@9GZ3mY+3a70N?Xcce6x+D=}70^8f)oL#p4 zyvTOOfgc}p;qIys*0b9pta+Tm18@AgkQQU8Gt3j%y#!P(I|2#B1hCF0@7Sm>2_!Ur zzBV)VB_4H3SfHP9LPy3uN>s8hafVqU%zg<5ceJ8=Qeu@!MCj?%r43E z6(>iQKM}(*$+5NLJcG2v@1!dSS2+C;+}=uzB!LVk^AvQ|*&~R6d%*?FmKRv3wsi?- z-48GGgy9e0m5q-YR|4=i?T#|R(eJ_1yF z^X5&1OA<+oablwhD0zVGTtLLL&5f-gqX{4(zUKI-9+8Z#@exl;br4KdB>)=+d-I+Z zup;1#7cZIzTfT$|hr~%sA;rr41|bv9V0M6>WCc+XLCq7zoON9gW46diiu&wB+?wG0 zVZkuYPh_MekR&}eu_LN6TjM0EPy`}^nAyQ>;MpxO6UUs`xXPC;j+d90%ReaY&vG+U R!x8`h002ovPDHLkV1jTA8#Mp` delta 2856 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