Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clothing update #507

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
18d4526
Add ColorSet to Sheep.java
BenCheung0422 Mar 4, 2023
16f51aa
Update Sheep.java
BenCheung0422 Mar 4, 2023
4b2b471
Add dye items
BenCheung0422 Apr 5, 2023
a7b92cc
Fix sheep dying not working
BenCheung0422 Apr 5, 2023
552bb6d
Add dye item recipes
BenCheung0422 Apr 6, 2023
0fa5d7a
Merge branch 'farming' into color
BenCheung0422 Apr 6, 2023
a234983
Update recipes.json for dye recipes
BenCheung0422 Apr 6, 2023
d8e1289
Natural spawned colored sheep implementation
BenCheung0422 Apr 12, 2023
6a265f2
Wool implementation by color system update
BenCheung0422 Apr 13, 2023
1c583ce
Merge branch 'farming' into color
BenCheung0422 Apr 14, 2023
87ec11a
Resolve problem by merging
BenCheung0422 Apr 14, 2023
f04df2d
Changed wool into white wool in chestloot table
BenCheung0422 Apr 14, 2023
616d2ab
Complement of recipes of dye composites
BenCheung0422 Apr 14, 2023
1bdf159
Complement of wool recipes
BenCheung0422 Apr 14, 2023
4f9430f
Add string to white wool recipe
BenCheung0422 Apr 14, 2023
9b546e1
Colored bed implementation by color system update
BenCheung0422 Apr 14, 2023
b603f51
Fix invalid wool request into white wool
BenCheung0422 Apr 15, 2023
d11f373
Complementation on bed recipes
BenCheung0422 Apr 15, 2023
f761754
Add recipe unlocking advancement generator
BenCheung0422 Apr 16, 2023
e57757e
Update ChangeLog.md
BenCheung0422 May 14, 2023
415ad61
Merge branch 'main' into color
BenCheung0422 May 14, 2023
13be533
Create Cauldron.java
BenCheung0422 Jun 21, 2023
60ca6c0
Update clothing
BenCheung0422 Jun 21, 2023
6cbb22a
Remove old clothing recipes and make load
BenCheung0422 Jun 21, 2023
91f449a
Update Player.java
BenCheung0422 Jun 21, 2023
8550fa8
Add clothes textures and change white tinting
BenCheung0422 Jun 21, 2023
e930648
Add cauldron textures
BenCheung0422 Jun 21, 2023
e1d8fe5
Update Cauldron.java
BenCheung0422 Jun 21, 2023
39b1e91
Update recipes.json
BenCheung0422 Jun 21, 2023
029e98f
Fix small problems
BenCheung0422 Jun 21, 2023
3a4c882
Update recipes.json
BenCheung0422 Jun 21, 2023
319e788
Merge branch 'farming' into color
BenCheung0422 Jun 23, 2023
4933667
Merge branch 'color' into clothing
BenCheung0422 Jun 23, 2023
3d97ce9
Add more flowers
BenCheung0422 Jul 10, 2023
8550872
Merge branch 'farming' into color
BenCheung0422 Jul 10, 2023
f16516b
Update tile IDs
BenCheung0422 Jul 10, 2023
467dbb4
Add recipes for more flowers
BenCheung0422 Jul 10, 2023
f558d20
Combine flower tiles into tile data
BenCheung0422 Jul 13, 2023
9bab402
Revert changes related to #574
BenCheung0422 Oct 10, 2023
62bfed2
Merge remote-tracking branch 'upstream/main' into color
BenCheung0422 Dec 30, 2023
6756836
Delete bed.png
BenCheung0422 Jan 10, 2024
c82a951
Fix spacings in Tiles.java
BenCheung0422 Jan 20, 2024
258bb72
Merge branch 'main' into color
Litorom Feb 3, 2024
4176b7c
Merge remote-tracking branch 'upstream/main' into color
BenCheung0422 Mar 28, 2024
1d9ba22
World generation for new flower variants
BenCheung0422 Mar 28, 2024
94035da
Merge remote-tracking branch 'upstream/main' into color
BenCheung0422 Apr 25, 2024
4ff39c3
Fix flower problems
BenCheung0422 Apr 26, 2024
34ee623
Merge branch 'main' into color
Litorom May 21, 2024
f720e23
Update texture of colored beds
BenCheung0422 May 24, 2024
f23afea
Merge branch 'main' into color
Litorom May 24, 2024
e847c0f
Fix tile IDs for wool tiles
BenCheung0422 May 25, 2024
6e6f668
Merge branch 'main' into color
Litorom Jun 25, 2024
4b32616
Update FlowerTile.java
BenCheung0422 Jun 25, 2024
cccb95b
Merge branch 'color' into clothing
BenCheung0422 Aug 3, 2024
cd6daa8
Added Item for the cauldron
Litorom Aug 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/client/java/minicraft/entity/furniture/Bed.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,44 @@
import minicraft.core.Updater;
import minicraft.core.io.Localization;
import minicraft.entity.mob.Player;
import minicraft.gfx.SpriteAnimation;
import minicraft.gfx.SpriteLinker.LinkedSprite;
import minicraft.gfx.SpriteLinker.SpriteType;
import minicraft.item.DyeItem;
import minicraft.level.Level;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;

public class Bed extends Furniture {

private static final HashMap<DyeItem.DyeColor, LinkedSprite> sprites = new HashMap<>();
private static final HashMap<DyeItem.DyeColor, LinkedSprite> itemSprites = new HashMap<>();

@Override
public @NotNull Furniture copy() {
return new Bed(color);
}

static {
for (DyeItem.DyeColor color : DyeItem.DyeColor.values()) {
sprites.put(color, new LinkedSprite(SpriteType.Entity, color.toString().toLowerCase() + "_bed"));
itemSprites.put(color, new LinkedSprite(SpriteType.Item, color.toString().toLowerCase() + "_bed"));
}
}

private static int playersAwake = 1;
private static final HashMap<Player, Bed> sleepingPlayers = new HashMap<>();

public final DyeItem.DyeColor color;

/**
* Creates a new furniture with the name Bed and the bed sprite and color.
*/
public Bed() {
super("Bed", new LinkedSprite(SpriteType.Entity, "bed"), new LinkedSprite(SpriteType.Item, "bed"), 3, 2);
public Bed() { this(DyeItem.DyeColor.WHITE); }
public Bed(DyeItem.DyeColor color) {
super(color.toString().replace('_', ' ') + " Bed", sprites.get(color), itemSprites.get(color), 3, 2);
this.color = color;
}

/**
Expand Down
110 changes: 110 additions & 0 deletions src/client/java/minicraft/entity/furniture/Cauldron.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package minicraft.entity.furniture;

import minicraft.entity.Direction;
import minicraft.entity.mob.Player;
import minicraft.gfx.Screen;
import minicraft.gfx.SpriteLinker;
import minicraft.item.BucketItem;
import minicraft.item.ClothingItem;
import minicraft.item.DyeItem;
import minicraft.item.Item;
import minicraft.item.Items;
import org.jetbrains.annotations.Nullable;

public class Cauldron extends Furniture {
private static final SpriteLinker.LinkedSprite sprite = new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Entity, "cauldron");
private static final SpriteLinker.LinkedSprite spriteFilled = new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Entity, "cauldron_filled");
private static final SpriteLinker.LinkedSprite spriteColored = new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Entity, "cauldron_colored");
private static final SpriteLinker.LinkedSprite itemSprite = new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Item, "cauldron");
private static final int BACKGROUND_COLOR = 0x424242; // Used for dynamical rendering with transparent colors

public Cauldron() {
super("Cauldron", sprite, itemSprite);
}

private boolean filled = false; // whether the cauldron is filled with water or not
private int color = -1; // -1 if transparent, 24-bit RGB value otherwise

@Override
public boolean interact(Player player, @Nullable Item item, Direction attackDir) {
if (item != null) {
if (item instanceof BucketItem) {
if (item.getName().equals("Water Bucket")) {
if (!filled) {
filled = true;
color = -1;
return true;
}
} else if (item.getName().equals("Empty Bucket")) {
if (color == -1 && filled) {
player.activeItem = Items.get("Water Bucket").copy();
return true;
}
}
} else if (item instanceof DyeItem) {
((DyeItem) item).count--;
if (color == -1) { // Transparent; initialize color with original colors
color = ((DyeItem) item).color.color & 0xFFFFFF; // Converting to a 24-bit RGB value
} else { // Already dyed
color = combineColors(color, ((DyeItem) item).color.color);
}
return true;
} else if (item instanceof ClothingItem) {
if (filled) {
if (color == -1) {
((ClothingItem) item).setColor(0); // Clearing the dyeing
} else {
((ClothingItem) item).setColor(color);
}
}
}
}

return false;
}

@Override
public void render(Screen screen) {
if (!filled) screen.render(x-8, y-8, sprite);
else if (color == -1) screen.render(x-8, y-8, spriteFilled);
else screen.render(x-8, y-8, spriteColored.setColor(combineTransparentColor(0.6, color, BACKGROUND_COLOR)));
}

/**
* Combines 2 colors and calculates the resultant color by using the algorithm used in Minecraft.
* @param color0 a valid 24-bit RGB value
* @param color1 a valid 24-bit RGB value; might be a dye color
* @return the resultant 24-bit RGB value after the combination
*/
public static int combineColors(int color0, int color1) {
int totalRed = (color0 >> 16) + (color1 >> 16);
int totalGreen = ((color0 >> 8) & 0xFF) + ((color1 >> 8) & 0xFF);
int totalBlue = (color0 & 0xFF) + (color1 & 0xFF);
int totalMaximum = Math.max(Math.max(color0 >> 16, (color0 >> 8) & 0xFF), color0 & 0xFF)
+ Math.max(Math.max(color1 >> 16, (color1 >> 8) & 0xFF), color1 & 0xFF);

double averageRed = totalRed / 2.0;
double averageGreen = totalGreen / 2.0;
double averageBlue = totalBlue / 2.0;
double averageMaximum = totalMaximum / 2.0;

double maximumOfAverage = Math.max(Math.max(averageRed, averageGreen), averageBlue);
double gainFactor = averageMaximum / maximumOfAverage;

return ((int) (averageRed * gainFactor) << 16) + ((int) (averageGreen * gainFactor) << 8) + (int) (averageBlue * gainFactor);
}

/**
* Calculates the resultant color by a color with transparency covering on an opaque color.
* Reference: https://stackoverflow.com/a/3506190
* @param alpha alpha value [0-1] of {@code color0}
* @param color0 24-bit RGB value sticking with the alpha value
* @param color1 24-bit RGB value with opaque color
* @return the resultant 24-bit RGB value
*/
public static int combineTransparentColor(double alpha, int color0, int color1) {
return ((int) (Math.ceil((color0 >> 16) * alpha) + Math.ceil((color1 >> 16) * (1 - alpha)))) +
((int) (Math.ceil(((color0 >> 8) & 0xFF) * alpha) + Math.ceil(((color1 >> 8) & 0xFF) * (1 - alpha)))) +
((int) (Math.ceil((color0 & 0xFF) * alpha) + Math.ceil((color1 & 0xFF) * (1 - alpha))));
}
}
2 changes: 1 addition & 1 deletion src/client/java/minicraft/entity/mob/Mob.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public static LinkedSprite[][] compileMobSpriteAnimations(int sheetX, int sheetY
private boolean isWooling() { // supposed to walk at half speed on wool
if (level == null) return false;
Tile tile = level.getTile(x >> 4, y >> 4);
return tile == Tiles.get("wool");
return tile == Tiles.get("white wool");
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/client/java/minicraft/entity/mob/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public class Player extends Mob implements ItemHolder, ClientTickable {
private int cooldowninfo; // Prevents you from toggling the info pane on and off super fast.
private int regentick; // Counts time between each time the regen potion effect heals you.

public int shirtColor = Color.get(1, 51, 51, 0); // Player shirt color.
public int shirtColor = 0; // Player shirt color.

public boolean isFishing = false;
public int maxFishingTicks = 120;
Expand Down Expand Up @@ -921,16 +921,16 @@ public void render(Screen screen) {
// This makes falling look really cool.
int spriteToUse = Math.round(onFallDelay / 2f) % carrySprites.length;
curSprite = carrySprites[spriteToUse][(walkDist >> 3) & 1];
screen.render(xo, yo - 4 * onFallDelay, curSprite.setColor(shirtColor));
screen.render(xo, yo - 4 * onFallDelay, curSprite.setColor(shirtColor == 0 ? 0x1EFEFEF : shirtColor));
} else {
curSprite = spriteSet[dir.getDir()][(walkDist >> 3) & 1]; // Gets the correct sprite to render.
// Render each corner of the sprite
if (isSwimming()) {
Sprite sprite = curSprite.getSprite();
screen.render(xo, yo, sprite.spritePixels[0][0], shirtColor);
screen.render(xo + 8, yo, sprite.spritePixels[0][1], shirtColor);
screen.render(xo, yo, sprite.spritePixels[0][0], shirtColor == 0 ? 0x1EFEFEF : shirtColor);
screen.render(xo + 8, yo, sprite.spritePixels[0][1], shirtColor == 0 ? 0x1EFEFEF : shirtColor);
} else { // Don't render the bottom half if swimming.
screen.render(xo, yo - 4 * onFallDelay, curSprite.setColor(shirtColor));
screen.render(xo, yo - 4 * onFallDelay, curSprite.setColor(shirtColor == 0 ? 0x1EFEFEF : shirtColor));
}
}

Expand Down
50 changes: 39 additions & 11 deletions src/client/java/minicraft/entity/mob/Sheep.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package minicraft.entity.mob;

import minicraft.item.DyeItem;
import org.jetbrains.annotations.Nullable;

import minicraft.core.io.Settings;
import minicraft.entity.Direction;
import minicraft.gfx.Screen;
Expand All @@ -11,27 +14,50 @@
import minicraft.level.tile.GrassTile;
import minicraft.level.tile.Tile;
import minicraft.level.tile.Tiles;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;

public class Sheep extends PassiveMob {
private static final LinkedSprite[][] sprites = Mob.compileMobSpriteAnimations(0, 0, "sheep");
private static final LinkedSprite[][] cutSprites = Mob.compileMobSpriteAnimations(0, 2, "sheep");
private static final HashMap<DyeItem.DyeColor, LinkedSprite[][]> sprites = new HashMap<>();
private static final HashMap<DyeItem.DyeColor, LinkedSprite[][]> cutSprites = new HashMap<>();

static {
for (DyeItem.DyeColor color : DyeItem.DyeColor.values()) {
LinkedSprite[][] mobSprites = Mob.compileMobSpriteAnimations(0, 0, "sheep");
for (LinkedSprite[] mobSprite : mobSprites) {
for (LinkedSprite linkedSprite : mobSprite) {
linkedSprite.setColor(color.color);
}
}
sprites.put(color, mobSprites);
mobSprites = Mob.compileMobSpriteAnimations(0, 2, "sheep");
for (LinkedSprite[] mobSprite : mobSprites) {
for (LinkedSprite linkedSprite : mobSprite) {
linkedSprite.setColor(color.color);
}
}
cutSprites.put(color, mobSprites);
}
}

public boolean cut = false;
public DyeItem.DyeColor color;

/**
* Creates a sheep entity.
*/
public Sheep() {
super(sprites);
public Sheep() { this(DyeItem.DyeColor.WHITE); }
public Sheep(DyeItem.DyeColor color) {
super(null);
this.color = color;
}

@Override
public void render(Screen screen) {
int xo = x - 8;
int yo = y - 11;

LinkedSprite[][] curAnim = cut ? cutSprites : sprites;
LinkedSprite[][] curAnim = cut ? cutSprites.get(color) : sprites.get(color);

LinkedSprite curSprite = curAnim[dir.getDir()][(walkDist >> 3) % curAnim[dir.getDir()].length];
if (hurtTime > 0) {
Expand All @@ -52,15 +78,17 @@ public void tick() {
}

public boolean interact(Player player, @Nullable Item item, Direction attackDir) {
if (cut) return false;

if (item instanceof ToolItem) {
if (((ToolItem) item).type == ToolType.Shears) {
if (!cut && ((ToolItem) item).type == ToolType.Shears) {
cut = true;
dropItem(1, 3, Items.get("Wool"));
dropItem(1, 3, Items.get(color.toString().replace('_', ' ') + " Wool"));
((ToolItem) item).payDurability();
return true;
}
} else if (item instanceof DyeItem) {
color = ((DyeItem) item).color;
((DyeItem) item).count--;
return true;
}
return false;
}
Expand All @@ -80,7 +108,7 @@ public void die() {
max = 2;
}

if (!cut) dropItem(min, max, Items.get("wool"));
if (!cut) dropItem(min, max, Items.get(color.toString().replace('_', ' ') + " Wool"));
dropItem(min, max, Items.get("Raw Beef"));

super.die();
Expand Down
6 changes: 4 additions & 2 deletions src/client/java/minicraft/gfx/Screen.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import minicraft.core.Renderer;
import minicraft.core.Updater;
import minicraft.entity.furniture.Cauldron;
import minicraft.gfx.SpriteLinker.LinkedSprite;
import minicraft.gfx.SpriteLinker.SpriteType;
import org.intellij.lang.annotations.MagicConstant;
Expand Down Expand Up @@ -126,9 +127,10 @@ public void render(Graphics2D graphics) {
int col = sheet.pixels[toffs + sx + sy * sheet.width]; // Gets the color of the current pixel from the value stored in the sheet.
if (col >> 24 != 0) { // if not transparent
int index = (xp + x) + (yp + y) * w;
if (whiteTint != -1 && col == 0x1FFFFFF) {
boolean whiteTintAva = (col >> 24) == 1 && ((col >> 16) & 0xFF) == ((col >> 8) & 0xFF) && ((col >> 8) & 0xFF) == (col & 0xFF);
if (whiteTint != -1 && whiteTintAva) {
// If this is white, write the whiteTint over it
pixels[index] = Color.upgrade(whiteTint);
pixels[index] = Cauldron.combineTransparentColor((col & 0xFF) / 255D, whiteTint, 0);
} else {
// Inserts the colors into the image
if (fullBright) {
Expand Down
47 changes: 15 additions & 32 deletions src/client/java/minicraft/item/ClothingItem.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package minicraft.item;

import minicraft.core.Game;
import minicraft.entity.Direction;
import minicraft.entity.mob.Player;
import minicraft.gfx.Color;
Expand All @@ -13,51 +12,35 @@
import java.util.ArrayList;

public class ClothingItem extends StackableItem {
private static final int DEFAULT_COLOR = Color.get(1, 51, 51, 0); // Dark Green

protected static ArrayList<Item> getAllInstances() {
ArrayList<Item> items = new ArrayList<>();

items.add(new ClothingItem("Red Clothes", new LinkedSprite(SpriteType.Item, "red_clothes"), Color.get(1, 204, 0, 0)));
items.add(new ClothingItem("Blue Clothes", new LinkedSprite(SpriteType.Item, "blue_clothes"), Color.get(1, 0, 0, 204)));
items.add(new ClothingItem("Green Clothes", new LinkedSprite(SpriteType.Item, "green_clothes"), Color.get(1, 0, 204, 0)));
items.add(new ClothingItem("Yellow Clothes", new LinkedSprite(SpriteType.Item, "yellow_clothes"), Color.get(1, 204, 204, 0)));
items.add(new ClothingItem("Black Clothes", new LinkedSprite(SpriteType.Item, "black_clothes"), Color.get(1, 51)));
items.add(new ClothingItem("Orange Clothes", new LinkedSprite(SpriteType.Item, "orange_clothes"), Color.get(1, 255, 102, 0)));
items.add(new ClothingItem("Purple Clothes", new LinkedSprite(SpriteType.Item, "purple_clothes"), Color.get(1, 102, 0, 153)));
items.add(new ClothingItem("Cyan Clothes", new LinkedSprite(SpriteType.Item, "cyan_clothes"), Color.get(1, 0, 102, 153)));
items.add(new ClothingItem("Reg Clothes", new LinkedSprite(SpriteType.Item, "reg_clothes"), Color.get(1, 51, 51, 0)));
items.add(new ClothingItem("Clothes", 0));

return items;
}

private int playerCol;
private int color;

private ClothingItem(String name, LinkedSprite sprite, int pcol) {
this(name, 1, sprite, pcol);
private ClothingItem(String name, int color) {
super(name, new LinkedSprite(SpriteType.Item, "clothes").setColor(color == 0 ? DEFAULT_COLOR : color));
this.color = color;
}

private ClothingItem(String name, int count, LinkedSprite sprite, int pcol) {
super(name, sprite, count);
playerCol = pcol;
public void setColor(int color) {
sprite.setColor((this.color = color) == 0 ? DEFAULT_COLOR : color);
}

// Put on clothes
public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, Direction attackDir) {
if (player.shirtColor == playerCol) {
return false;
} else {
if (!Game.isMode("minicraft.settings.mode.creative")) {
ClothingItem lastClothing = (ClothingItem) getAllInstances().stream().filter(i -> i instanceof ClothingItem && ((ClothingItem) i).playerCol == player.shirtColor)
.findAny().orElse(null);
if (lastClothing == null)
lastClothing = (ClothingItem) Items.get("Reg Clothes");
lastClothing = lastClothing.copy();
lastClothing.count = 1;
player.tryAddToInvOrDrop(lastClothing);
}
player.shirtColor = playerCol;
return super.interactOn(true);
}
ClothingItem lastClothing = (ClothingItem) Items.get("Clothes").copy();
lastClothing.count = 1;
lastClothing.setColor(player.shirtColor);
player.tryAddToInvOrDrop(lastClothing);
player.shirtColor = color;
return super.interactOn(true);
}

@Override
Expand All @@ -66,6 +49,6 @@ public boolean interactsWithWorld() {
}

public @NotNull ClothingItem copy() {
return new ClothingItem(getName(), count, sprite, playerCol);
return new ClothingItem(getName(), color);
}
}
Loading
Loading