001package net.tnemc.item.component.impl; 002/* 003 * The New Item Library 004 * Copyright (C) 2022 - 2025 Daniel "creatorfromhell" Vidmar 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020 021import net.tnemc.item.AbstractItemStack; 022import net.tnemc.item.JSONHelper; 023import net.tnemc.item.component.SerialComponent; 024import net.tnemc.item.component.helper.effect.ComponentEffect; 025import net.tnemc.item.platform.ItemPlatform; 026import org.json.simple.JSONArray; 027import org.json.simple.JSONObject; 028 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.List; 032import java.util.Objects; 033 034/** 035 * ConsumableComponent 036 * 037 * @author creatorfromhell 038 * @see <a href="https://minecraft.wiki/w/Data_component_format#">Reference</a> 039 * <p> 040 * @since 0.2.0.0 041 */ 042public abstract class ConsumableComponent<I extends AbstractItemStack<T>, T> implements SerialComponent<I, T> { 043 044 protected float consumeSeconds = 1.6f; // Default to 1.6 seconds 045 protected String animation = "eat"; // Default animation 046 protected String sound = "entity.generic.eat"; // Default sound 047 protected boolean hasConsumeParticles = true; // Default true 048 protected final List<ComponentEffect> effects = new ArrayList<>(); 049 050 public ConsumableComponent() { 051 052 } 053 public ConsumableComponent(final List<ComponentEffect> effects) { 054 055 this.effects.addAll(effects); 056 } 057 058 public ConsumableComponent(final float consumeSeconds) { 059 060 this.consumeSeconds = consumeSeconds; 061 } 062 063 public ConsumableComponent(final float consumeSeconds, final String animation) { 064 065 this.consumeSeconds = consumeSeconds; 066 this.animation = animation; 067 } 068 069 public ConsumableComponent(final float consumeSeconds, final String animation, final String sound) { 070 071 this.consumeSeconds = consumeSeconds; 072 this.animation = animation; 073 this.sound = sound; 074 } 075 076 public ConsumableComponent(final float consumeSeconds, final String animation, final String sound, final boolean hasConsumeParticles) { 077 078 this.consumeSeconds = consumeSeconds; 079 this.animation = animation; 080 this.sound = sound; 081 this.hasConsumeParticles = hasConsumeParticles; 082 } 083 084 public ConsumableComponent(final float consumeSeconds, final String animation, final String sound, final boolean hasConsumeParticles, final List<ComponentEffect> effects) { 085 086 this.consumeSeconds = consumeSeconds; 087 this.animation = animation; 088 this.sound = sound; 089 this.hasConsumeParticles = hasConsumeParticles; 090 this.effects.addAll(effects); 091 } 092 093 @Override 094 public String identifier() { 095 return "consumable"; 096 } 097 098 @Override 099 public JSONObject toJSON() { 100 final JSONObject json = new JSONObject(); 101 json.put("consume_seconds", consumeSeconds); 102 json.put("animation", animation); 103 json.put("sound", sound); 104 json.put("has_consume_particles", hasConsumeParticles); 105 106 final JSONArray effectsArray = new JSONArray(); 107 for (final ComponentEffect effect : effects) { 108 effectsArray.add(effect.toJSON()); 109 } 110 json.put("on_consume_effects", effectsArray); 111 112 return json; 113 } 114 115 @Override 116 public void readJSON(final JSONHelper json, final ItemPlatform<I, T, ?> platform) { 117 consumeSeconds = json.getFloat("consume_seconds"); 118 animation = json.getString("animation"); 119 sound = json.getString("sound"); 120 hasConsumeParticles = json.getBoolean("has_consume_particles"); 121 122 effects.clear(); 123 if(json.has("on_consume_effects")) { 124 125 final JSONArray effectsArray = (JSONArray) json.getObject().get("on_consume_effects"); 126 for (final Object obj : effectsArray) { 127 final JSONObject effectJson = (JSONObject) obj; 128 final String type = effectJson.get("type").toString(); 129 130 // Get the effect class from the platform's reviveEffects map 131 final Class<? extends ComponentEffect> effectClass = platform.effects().get(type); 132 133 if(effectClass != null) { 134 try { 135 // Instantiate the effect dynamically 136 final ComponentEffect effect = effectClass.getDeclaredConstructor().newInstance(); 137 effect.readJSON(new JSONHelper(effectJson)); 138 effects.add(effect); 139 } catch (final ReflectiveOperationException e) { 140 throw new RuntimeException("Failed to instantiate ComponentEffect for type: " + type, e); 141 } 142 } 143 } 144 } 145 } 146 147 @Override 148 public boolean similar(final SerialComponent<?, ?> component) { 149 if(!(component instanceof final ConsumableComponent<?, ?> other)) return false; 150 return Float.compare(this.consumeSeconds, other.consumeSeconds) == 0 && 151 Objects.equals(this.animation, other.animation) && 152 Objects.equals(this.sound, other.sound) && 153 this.hasConsumeParticles == other.hasConsumeParticles && 154 Objects.equals(this.effects, other.effects); 155 } 156 157 @Override 158 public int hashCode() { 159 return Objects.hash(consumeSeconds, animation, sound, hasConsumeParticles, effects); 160 } 161 162 public float consumeSeconds() { 163 164 return consumeSeconds; 165 } 166 167 public void consumeSeconds(final float consumeSeconds) { 168 169 this.consumeSeconds = consumeSeconds; 170 } 171 172 public String animation() { 173 174 return animation; 175 } 176 177 public void animation(final String animation) { 178 179 this.animation = animation; 180 } 181 182 public String sound() { 183 184 return sound; 185 } 186 187 public void sound(final String sound) { 188 189 this.sound = sound; 190 } 191 192 public boolean hasConsumeParticles() { 193 194 return hasConsumeParticles; 195 } 196 197 public void hasConsumeParticles(final boolean hasConsumeParticles) { 198 199 this.hasConsumeParticles = hasConsumeParticles; 200 } 201 202 public List<ComponentEffect> effects() { 203 204 return effects; 205 } 206 207 public void effects(final ComponentEffect... effects) { 208 this.effects.addAll(Arrays.asList(effects)); 209 } 210 211 public void effects(final List<ComponentEffect> effects) { 212 this.effects.clear(); 213 this.effects.addAll(effects); 214 } 215}