/* * (c) 2000-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved. * Licencia en license/bsd.txt / License in license/bsd.txt */ package eu.irreality.age; //package AetheriaAWT; /** * Funciones �tiles en el juego. * * @author Carlos G�mez */ import java.io.*; import java.util.*; import eu.irreality.age.i18n.UIMessages; import eu.irreality.age.util.xml.DOMUtils; public class Utility { /**Constantes*/ public static final String room_preffix = "10"; public static final String mobile_preffix = "20"; public static final String item_preffix = "30"; public static final String absent_preffix = "40"; public static final String spell_preffix = "50"; public static final int room_summand = 10000000; public static final int mobile_summand = 20000000; public static final int item_summand = 30000000; public static final int absent_summand = 40000000; public static final int spell_summand = 50000000; //ej. si el n�mero es el 1000 y el stdevfactor es 0.1, nos desviar� el n�mero t�picamente 100. public static double applyGaussianVariation ( double number , java.util.Random r , double stdevFactor ) { return number + ( r.nextGaussian() * number * stdevFactor ); } /** * Nos devuelve un InputStreamReader que a ser posible lea UTF-8, para ficheros. */ public static InputStreamReader getBestInputStreamReader ( InputStream is ) { InputStreamReader isr; try { isr = new InputStreamReader ( is , "UTF-8" ); } catch ( UnsupportedEncodingException uee ) { System.out.println(UIMessages.getInstance().getMessage("iso.encoding.warning") + "\n"); isr = new InputStreamReader ( is ); } return isr; } /** * Nos devuelve un OutputStreamWriter que a ser posible escriba UTF-8, para ficheros. */ public static OutputStreamWriter getBestOutputStreamWriter ( OutputStream os ) { OutputStreamWriter osw; try { osw = new OutputStreamWriter ( os , "UTF-8" ); } catch ( UnsupportedEncodingException uee ) { System.out.println(UIMessages.getInstance().getMessage("iso.encoding.warning") + "\n"); osw = new OutputStreamWriter ( os ); } return osw; } /** * Completa una ID incompleta a roomID * * @param id la ID incompleta (ya completa tambi�n sirve) * @return La ID en formato roomID, con el prefijo correspondiente */ public static int completeRoomID ( int ID ) { return ( ID > room_summand ? ID : ID + room_summand ); } /** * Completa una ID incompleta a itemID * * @param id la ID incompleta (ya completa tambi�n sirve) * @return La ID en formato itemID, con el prefijo correspondiente */ public static int completeItemID ( int ID ) { return ( ID > item_summand ? ID : ID + item_summand ); } /** * Completa una ID incompleta a mobileID * * @param id la ID incompleta (ya completa tambi�n sirve) * @return La ID en formato mobileID, con el prefijo correspondiente */ public static int completeMobileID ( int ID ) { return ( ID > mobile_summand ? ID : ID + mobile_summand ); } /** * Completa un n�mero con ceros hasta alcanzar nzeroes cifras. * * @param n el n�mero a completar. * @param nzeroes n�mero de cifras a alcanzar. * @return Un string con el n�mero de nzeroes cifras resultante. */ public static String completeWithZeroes ( int n , int nzeroes ) { String s = String.valueOf(n); while (s.length()<nzeroes) s = "0" + s; return s; } /** * Nos da el nombre y ruta de un fichero de habitaci�n. * * @param n el n�mero de habitaci�n. * @param mundo el mundo. * @return Un string con el nombre del fichero requerido. */ public static String roomFile ( World mundo, int n ) { String s = completeWithZeroes( n,6 ); return ( mundo.getWorldPath() + "objects" + File.separatorChar + room_preffix + s + ".ae" ); } /** * Nos da el nombre y ruta de un fichero de objeto. * * @param n el n�mero de objeto (no id completa). * @param mundo el mundo. * @return Un string con el nombre del fichero requerido. */ public static String itemFile ( World mundo , int n ) { String s = completeWithZeroes( n,6 ); return ( mundo.getWorldPath() + "objects" + File.separatorChar + item_preffix + s + ".ae" ); } public static String playerFile ( World mundo ) { return ( mundo.getWorldPath() + "objects" + File.separatorChar + mobile_preffix + "000000" + ".ae" ); } /** * Nos da el nombre y ruta de un fichero de bicho. * * @param n el n�mero de bicho (no id completa). * @param mundo el mundo. * @return Un string con el nombre del fichero requerido. */ public static String mobFile ( World mundo , int n ) { String s = completeWithZeroes( n,6 ); return ( mundo.getWorldPath() + "objects" + File.separatorChar + mobile_preffix + s + ".ae" ); } /** * Carga una lista (array din�mico) de descripciones con comparando y m�scara en memoria. * * @param linea El string del fichero. * @return theList El array. */ public static Description[] loadDescriptionListFromString ( String linea ) { if ( linea == null ) return new Description[0]; if ( linea.indexOf('&') < 0 ) { //si no hay &'s, se supone que es una sola descripci�n para todos los estados: //equivale a 0&0&... Description[] theList = new Description[1]; theList[0] = new Description ( linea,0,0 ); return theList; } else { Description[] theList = new Description[ StringMethods.numToks(linea,'&')/3 ]; for ( int i = 0 ; i+3 <= StringMethods.numToks(linea,'&') ; i+=3 ) { String text = StringMethods.getTok( linea,i+3,'&' ); long comp = Long.valueOf(StringMethods.getTok( linea,i+1,'&' )).longValue(); long mask = Long.valueOf(StringMethods.getTok( linea,i+2,'&' )).longValue(); theList[i/3] = new Description ( StringMethods.textualSubstitution( text, "\\n" , "\n" ) , comp , mask ) ; //comparando:token i+1 //mascara:token i+2 //texto:token i+3 } return theList; } } //devuelve un List cuyo primer elemento es un List of String[] y el segundo un List of Description[] (con nombres correspondientes) public static List loadExtraDescriptionsFromXML ( World mundo , org.w3c.dom.Element e , String tagName , boolean nullifyIfNotFound ) throws XMLtoWorldException { org.w3c.dom.NodeList interestingNodes = e.getElementsByTagName(tagName); if ( interestingNodes.getLength() > 0 ) { //nos interesa solo el primero org.w3c.dom.Element interestingNode = (org.w3c.dom.Element)interestingNodes.item(0); try { return Utility.loadExtraDescriptionsFromXML ( mundo , interestingNode ); } catch ( XMLtoWorldException ex ) { throw ( new XMLtoWorldException ( "When parsing " + tagName + ": " + ex.getMessage() ) ); } } else { return new ArrayList(); } } /** * save extra descriptions. Other objects have getXMLRepresentation() methods in their class, but there's no specific class for * extra descriptions since their storage is distributed in two different lists of arrays. * @param nameArrays List of arrays of names for the extra descriptions. * @param descArrays List of arrays of descriptions. * @doc XML document in which to create the new XML element. * @return */ public static org.w3c.dom.Element getExtraDescriptionXMLRepresentation ( List /*of String[]*/ nameArrays , List /*of Description[]*/ descArrays , org.w3c.dom.Document doc ) { if ( nameArrays == null || descArrays == null ) return null; org.w3c.dom.Element extraDesList = doc.createElement("ExtraDescriptionList"); for ( int i = 0 ; i < nameArrays.size() ; i++ ) //assertion: nameArrays has same size as descArrays { org.w3c.dom.Element extraDes = doc.createElement("ExtraDescription"); String[] theNames = (String[]) nameArrays.get(i); for ( int j = 0 ; j < theNames.length ; j++ ) { String aName = theNames[j]; org.w3c.dom.Element nameElement = doc.createElement("Name"); org.w3c.dom.Text nameTextNode = doc.createTextNode(aName); nameElement.appendChild(nameTextNode); extraDes.appendChild(nameElement); } org.w3c.dom.Element desList = doc.createElement("DescriptionList"); Description[] theDescriptions = (Description[]) descArrays.get(i); for ( int j = 0 ; j < theDescriptions.length ; j++ ) { org.w3c.dom.Node descriptionElement = theDescriptions[j].getXMLRepresentation(doc); desList.appendChild(descriptionElement); } extraDes.appendChild(desList); extraDesList.appendChild(extraDes); } return extraDesList; } //continuacion del anterior public static List loadExtraDescriptionsFromXML ( World mundo , org.w3c.dom.Element exDesListNode ) throws XMLtoWorldException { List laLista = new ArrayList(); List listaArraysNombres = new ArrayList(); List listaArraysDescripciones = new ArrayList(); laLista.add ( listaArraysNombres ); laLista.add ( listaArraysDescripciones ); org.w3c.dom.NodeList exDesNodes = exDesListNode.getElementsByTagName("ExtraDescription"); if ( exDesNodes.getLength() > 0 ) { for ( int i = 0 ; i < exDesNodes.getLength() ; i++ ) { org.w3c.dom.Element currentExDes = (org.w3c.dom.Element)exDesNodes.item(i); //load names org.w3c.dom.NodeList nameNodes = currentExDes.getElementsByTagName("Name"); String[] nameArray = new String[nameNodes.getLength()]; for ( int j = 0 ; j < nameNodes.getLength() ; j++ ) { org.w3c.dom.Element hijo = (org.w3c.dom.Element)nameNodes.item(j); org.w3c.dom.Node nieto = hijo.getFirstChild(); //buscar primer Text (deberia haber solo un hijo y Text) while ( !(nieto instanceof org.w3c.dom.Text ) ) { nieto = nieto.getNextSibling(); } nameArray[j]=(nieto.getNodeValue()); } //names loaded //load descriptions represented as DescriptionList elements Description[] desArray = Utility.loadDescriptionListFromXML ( mundo , currentExDes , "DescriptionList" , false ); if ( nameArray.length > 0 && desArray.length > 0 ) { listaArraysNombres.add ( nameArray ); listaArraysDescripciones.add ( desArray ); } else { //no "serious" descriptions, watch for text nodes //search first text node System.err.println("No serious descriptions: " + currentExDes + DOMUtils.nodeToString(currentExDes) ); org.w3c.dom.Node hijo = currentExDes.getFirstChild(); while ( !(hijo instanceof org.w3c.dom.Text ) || hijo.getNodeValue().trim().length()==0 ) { hijo = hijo.getNextSibling(); } if ( hijo != null && nameArray.length > 0 ) { listaArraysNombres.add ( nameArray ); listaArraysDescripciones.add ( new Description[] { new Description(hijo.getNodeValue().trim(),0,0) } ); } } } //foreach <ExtraDescription> node [tries to add an element to both lists] } //if there are <ExtraDescription> nodes return laLista; } //toma el Node correspondiente a la entidad completa, busca el de descripciones de ese tipo si lo hay, //y llama a su funcion hermana en Utility para construir las descripciones //(es decir, busca un nodo etiquetado con tagName dado que dentro a su vez tenga un nodo <Description>) public static Description[] loadDescriptionListFromXML ( World mundo , org.w3c.dom.Element e , String tagName , boolean nullifyIfNotFound ) throws XMLtoWorldException { org.w3c.dom.NodeList interestingNodes = e.getElementsByTagName(tagName); if ( interestingNodes.getLength() > 0 ) { //nos interesa solo el primero org.w3c.dom.Element interestingNode = (org.w3c.dom.Element)interestingNodes.item(0); try { return Utility.loadDescriptionListFromXML ( mundo , interestingNode ); } catch ( XMLtoWorldException ex ) { throw ( new XMLtoWorldException ( "When parsing " + tagName + ": " + ex.getMessage() ) ); } } else { if ( nullifyIfNotFound ) return null; else return new Description[0]; } } //carga una Description[] de los nodos etiquetado <Description> que haya dentro del nodo que le pasamos. public static Description[] loadDescriptionListFromXML ( World mundo , org.w3c.dom.Element descrListNode ) throws XMLtoWorldException { org.w3c.dom.NodeList descrNodes = descrListNode.getElementsByTagName ( "Description" ); Description[] ourArray = new Description[descrNodes.getLength()]; for ( int i = 0 ; i < descrNodes.getLength() ; i++ ) { org.w3c.dom.Element descrNode = (org.w3c.dom.Element) descrNodes.item(i); try { ourArray[i] = new Description(mundo,descrNode); } catch ( XMLtoWorldException xe ) { throw ( new XMLtoWorldException ( "Error at description: " + xe.getMessage() ) ); } } return ourArray; } private static List loadNameListFromXML ( World mundo , org.w3c.dom.Element namesNode ) throws XMLtoWorldException { //an example of this is singular reference names (respondToSing), XML format is: //<SingularReferenceNames><Name>nombre1</Name><Name>nombre2</Name>...</SingularReferenceNames> //while internal format is //nombre1$nombre2 /*Do this to get the node in which to call this function: org.w3c.dom.NodeList singRefNamesNodes = e.getElementsByTagName("SingularReferenceNames" ); if ( singRefNamesNodes.getLength() > 0 ) { org.w3c.dom.Element singRefNamesNode = (org.w3c.dom.Element)singRefNamesNodes.item(0); } */ org.w3c.dom.NodeList nameNodes = namesNode.getElementsByTagName("Name"); /* * legacy reference name list: support removed 2014-01-07 * //init ourString String ourString = ""; for ( int i = 0 ; i < nameNodes.getLength() ; i++ ) { //get this name node org.w3c.dom.Element nameNode = (org.w3c.dom.Element) nameNodes.item(i); //get first text node in this name node -- WE ASSUME THERE IS ONE!! org.w3c.dom.Node hijo = nameNode.getFirstChild(); while ( !( hijo instanceof org.w3c.dom.Text ) ) hijo = hijo.getNextSibling(); //{hijo is an org.w3c.dom.Text} ourString += ( hijo.getNodeValue() ); if ( i < nameNodes.getLength()-1 ) //i.e. not last ourString += "$"; } return ourString; */ //init ourList List ourList = new ArrayList(); for ( int i = 0 ; i < nameNodes.getLength() ; i++ ) { //get this name node org.w3c.dom.Element nameNode = (org.w3c.dom.Element) nameNodes.item(i); //get first text node in this name node -- WE ASSUME THERE IS ONE!! org.w3c.dom.Node hijo = nameNode.getFirstChild(); while ( !( hijo instanceof org.w3c.dom.Text ) ) hijo = hijo.getNextSibling(); //{hijo is an org.w3c.dom.Text} ourList.add( hijo.getNodeValue() ); } return ourList; } //e: entity Element public static List loadNameListFromXML ( World mundo , org.w3c.dom.Element e , String tagName , boolean nullifyIfNotFound ) throws XMLtoWorldException { org.w3c.dom.NodeList singRefNamesNodes = e.getElementsByTagName ( tagName ); if ( singRefNamesNodes.getLength() > 0 ) { org.w3c.dom.Element singRefNamesNode = (org.w3c.dom.Element)singRefNamesNodes.item(0); return loadNameListFromXML ( mundo , singRefNamesNode ); } else { if ( nullifyIfNotFound ) return null; else return new ArrayList(); } } //obsolete! public static String loadExtraDescriptionsFromXML ( org.w3c.dom.Element e , String tagName , boolean nullifyIfNotFound ) throws XMLtoWorldException { org.w3c.dom.NodeList extraDesListNodes = e.getElementsByTagName( tagName ); if ( extraDesListNodes.getLength() > 0 ) { org.w3c.dom.Element theExtraDescriptionListNode = (org.w3c.dom.Element)extraDesListNodes.item(0); //build extra descriptions from the node return loadExtraDescriptionsFromXML ( theExtraDescriptionListNode ); } else { if ( nullifyIfNotFound ) return null; else return ""; } } //obsolete! private static String loadExtraDescriptionsFromXML ( org.w3c.dom.Element extraDesElement ) throws XMLtoWorldException { String extraDescriptions=""; org.w3c.dom.NodeList extraDesNodes = extraDesElement.getElementsByTagName("ExtraDescription"); for ( int i = 0 ; i < extraDesNodes.getLength() ; i++ ) { org.w3c.dom.Element extraDesNode = (org.w3c.dom.Element) extraDesNodes.item(i); org.w3c.dom.Node hijo = extraDesNode.getFirstChild(); while ( !( hijo instanceof org.w3c.dom.Text ) ) { //nodos Element con un nombre (Name), si no cambia el formato. if ( ((org.w3c.dom.Element)hijo).getTagName().equalsIgnoreCase("Name") ) { org.w3c.dom.Node nieto = hijo.getFirstChild(); //buscar primer Text (deberia haber solo un hijo y Text) while ( !(nieto instanceof org.w3c.dom.Text ) ) { nieto = nieto.getNextSibling(); } extraDescriptions+=nieto.getNodeValue(); extraDescriptions+="$"; } hijo = hijo.getNextSibling(); } //hijo is now a Text: the extra des text. extraDescriptions+=hijo.getNodeValue(); if ( i < extraDesNodes.getLength() - 1 ) //i.e. not last extraDescriptions+="@"; } return extraDescriptions; } }