/*
* This file is part of the Illarion project.
*
* Copyright © 2015 - Illarion e.V.
*
* Illarion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Illarion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package illarion.client.graphics;
import illarion.common.graphics.CharAnimations;
import org.jetbrains.annotations.Contract;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* Additional Info for an avatar. Every avatar for every avatar gets only one Avatar info object and has to report
* all animations known for this character to the object.
*
* @author Nop
* @author Martin Karing <nitram@illarion.org>
*/
public final class AvatarInfo {
/**
* The instance of the logger for this class.
*/
@Nonnull
private static final Logger log = LoggerFactory.getLogger(AvatarInfo.class);
/**
* The buffer of constructs of this class that is generated during the creation process and stores all AvatarInfo
* constructs that were generated. This is needed to ensure that there is only one instance for each avatar
* appearance. This object is deleted after the characters are loaded completely.
*/
@Nullable
private static Map<Integer, AvatarInfo> buffer = new HashMap<>();
/**
* The list of animations known to this avatar. All animation index values marked with true need to be playable.
*/
@Nonnull
private final boolean[] animations;
/**
* The visibility modifier of the avatar. 100 means normal visibility, values greater then 100 improve the
* visibility, values below 100 lower the visibility.
*/
private final int visibility;
/**
* Default constructor of the avatar information.
*
* @param visibilityMod the visibility modifications for the avatar in percent. Values above 100 increase the
* default visibility.
*/
private AvatarInfo(int visibilityMod) {
visibility = visibilityMod;
animations = new boolean[CharAnimations.DEFINED_ANIMATIONS];
}
/**
* Clean this class up. This should be called after all avatars are loaded. It ensures that is becomes impossible
* to modify the instances of this class and the unneeded buffer table is emptied and removed.
*/
public static void cleanup() {
if (buffer != null) {
buffer.clear();
}
buffer = null;
}
/**
* Get the avatar instance for a avatar appearance with some set information about the avatar. This function
* creates a new instance of the AvatarInfo class with the parameters, or returns a already created one for this
* appearance.
*
* @param appearance the appearance this avatar information are related to
* @param visibilityMod the visibility modifications for the avatar in percent. Values above 100 increase the
* default visibility.
* @return the newly created instance of AvatarInfo or a already created one from the cache
*/
@Nonnull
public static AvatarInfo getInstance(int appearance, int visibilityMod) {
if (buffer != null) {
AvatarInfo result = buffer.get(appearance);
if (result != null) {
return result;
}
} else {
log.error("Requested new avatar information after setup was done. Efficiency degrading!");
}
AvatarInfo newInfo = new AvatarInfo(visibilityMod);
if (buffer != null) {
buffer.put(appearance, newInfo);
}
return newInfo;
}
/**
* Get the visibility modifications of the avatar. The modifications is set in percent. Use the return of this
* function in general in the following way: {@code realVisibility = defaultVisibility * functionReturn / 100}
*
* @return 100 for the normal visibility, greater values for larger visibility and lower values for less visibility
*/
@Contract(pure = true)
public int getVisibility() {
return visibility;
}
/**
* Check if a animation is set for this avatar. In case the animation is available its possible to play that
* animation.
*
* @param animationID the ID of the animation that shall be checked for availability
* @return {@code true} in case the animation is available
*/
@Contract(pure = true)
public boolean isAnimationAvailable(int animationID) {
return animations[animationID];
}
/**
* Report to this Avatar info that a particular animation is available. After reporting this it must be ensured
* that this animation is available to be shown.
*
* @param animationID the ID of the animation that is available.
*/
public void reportAnimation(int animationID) {
if (buffer == null) {
throw new IllegalStateException("Changing this construct is not allowed after the creation process.");
}
animations[animationID] = true;
}
}