It is currently 22 May 2025, 08:55
   
Text Size

myk's code contributions

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Re: myk's code contributions

Postby Max mtg » 27 Feb 2013, 04:21

Thanks!
To my mind r19900 is enough to fix the problem, isn't it?

The only thing that is quite annoying - that confirmation to overwrite deck, because there is already one named '%deckname%'
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: myk's code contributions

Postby friarsol » 27 Feb 2013, 04:46

Max mtg wrote:The only thing that is quite annoying - that confirmation to overwrite deck, because there is already one named '%deckname%'
As someone who plays quest a lot, yes this is extremely annoying.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: myk's code contributions

Postby Max mtg » 27 Feb 2013, 05:09

Yes, then let's carve it out... r19903
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: myk's code contributions

Postby myk » 27 Feb 2013, 07:22

/much/ better. Thanks, Max!
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby myk » 28 Feb 2013, 18:19

I created a branch so I could start experimenting with moving writable data out of the program dir so our code tree can stay clean and we would have an obvious separation of "official" data and user-generated/downloaded data (e.g. user-created worlds). My hope is that everything can be migrated over to the new locations automatically, just showing a popup explaining the move and requesting permission to move the files. I'll try to make this as non-disruptive as possible.

Data directory roots would be in standard locations for each OS:
  • Linux: $HOME/.forge/
  • Windows: $HOME/My Documents/My Games/Forge/ (localized for OS language, of course)
  • OSX: $HOME/Library/Forge/ (localization?)
with all writable data uniformly organized underneath. I'll work on it for a while and report on my progress.
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby friarsol » 28 Feb 2013, 18:39

myk wrote:I created a branch so I could start experimenting with moving writable data out of the program dir so our code tree can stay clean and we would have an obvious separation of "official" data and user-generated/downloaded data (e.g. user-created worlds). My hope is that everything can be migrated over to the new locations automatically, just showing a popup explaining the move and requesting permission to move the files. I'll try to make this as non-disruptive as possible.

Data directory roots would be in standard locations for each OS:
  • Linux: $HOME/.forge/
  • Windows: $HOME/My Documents/My Games/Forge/ (localized for OS language, of course)
  • OSX: $HOME/Library/Forge/ (localization?)
with all writable data uniformly organized underneath. I'll work on it for a while and report on my progress.
Just so you know, in recent versions of Windows (Vista+) MS no longer uses the addage "My" it's just Documents. I can see where my saves go for Dragon Age when I get home.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: myk's code contributions

Postby myk » 28 Feb 2013, 18:53

yeah, I might have to wrap SHGetSpecialFolderPath (or SHGetKnownFolderPath on Vista+) with JNI for windows, which might be a pain. I'd certainly prefer it if there were a pure java way to do it. It looks like there is no localization for 'Library' on OSX, though. The OSX UI just changes the filenames displayed to the user in the file manager (which sounds kinda hacky to me, but it does make it easier to get the path on OSX : )

edit: I found these little tidbits that avoid JNI, JNA, or any huge registry-accessing dependencies that would bloat our distributable:
cscript-based | Open
Code: Select all
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;

public class VBSUtils {
 
  public static String SF_ALLUSERSDESKTOP    = "AllUsersDesktop";
  public static String SF_ALLUSERSSTARTMENU  = "AllUsersStartMenu";
  public static String SF_ALLUSERSPROGRAMS   = "AllUsersPrograms";
  public static String SF_ALLUSERSSTARTUP    = "AllUsersStartup";
  public static String SF_DESKTOP            = "Desktop";
  public static String SF_FAVORITES          = "Favorites";
  public static String SF_MYDOCUMENT         = "MyDocuments";
  public static String SF_PROGRAMS           = "Programs";
  public static String SF_RECENT             = "Recent";
  public static String SF_SENDTO             = "SendTo";
  public static String SF_STARTMENU          = "StartMenu";
  public static String SF_STARTUP            = "Startup";
 
  private VBSUtils() {  }

  public static String getSpecialFolder(String folder) {
    String result = "";
    try {
        File file = File.createTempFile("realhowto",".vbs");
        file.deleteOnExit();
        FileWriter fw = new java.io.FileWriter(file);

        String vbs = "Set WshShell = WScript.CreateObject(\"WScript.Shell\")\n"
                     + "wscript.echo WshShell.SpecialFolders(\"" + folder + "\")\n"           
                     + "Set WSHShell = Nothing\n";

        fw.write(vbs);
        fw.close();
        Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
        BufferedReader input =
            new BufferedReader
              (new InputStreamReader(p.getInputStream()));
        result = input.readLine();
        input.close();
    }
    catch(Exception e){
        e.printStackTrace();
    }
    return result;
  }

  public static void main(String[] args){
    System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_ALLUSERSDESKTOP));
    System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_DESKTOP));
    System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_PROGRAMS));
  }
}
reg query-based | Open
Code: Select all
import java.io.*; 
   
public class RegQuery { 
   
private static final String REGQUERY_UTIL = "reg query "; 
private static final String REGSTR_TOKEN = "REG_SZ"; 
private static final String COMPUTER_WINDOWS_FAVORITES_FOLDER = REGQUERY_UTIL + 
"\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\" /v Favorites"; 
   
public static String getCurrentPCFavorites() 

try { 
Process process = Runtime.getRuntime().exec(COMPUTER_WINDOWS_FAVORITES_FOLDER); 
StreamReader reader = new StreamReader(process.getInputStream()); 
reader.start(); 
process.waitFor(); 
reader.join(); 
String result = reader.getResult(); 
int p = result.indexOf(REGSTR_TOKEN); 
if (p == -1) 
return null; 
return result.substring(p + REGSTR_TOKEN.length()).trim(); 

catch (Exception e) { 
return null; 


   
static class StreamReader extends Thread { 
private InputStream is; 
private StringWriter sw; 
   
StreamReader(InputStream is) { 
this.is = is; 
sw = new StringWriter(); 

   
public void run() { 
try { 
int c; 
while ((c = is.read()) != -1) 
sw.write(c); 

catch (IOException e) { ; } 

   
String getResult() { 
return sw.toString(); 


   
public static void main(String s[]) { 
System.out.println("Personal directory : " + getCurrentUserPersonalFolderPath()); 

}
I'd have to modify them a bit to get the right folder and make the code a little more "production ready", but they look like viable techniques.
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby moomarc » 28 Feb 2013, 19:36

Is there no way to have the user select the location. I keep my work and personal files very separate and my OS drive is a separate drive altogether that I try keep clear of all extraeneous data to improve scratch performance for my graphics programs.

If it's not a viable option it's fine though, so don't let it cause too many hassles.
-Marc
User avatar
moomarc
Pixel Commander
 
Posts: 2091
Joined: 04 Jun 2010, 15:22
Location: Johannesburg, South Africa
Has thanked: 371 times
Been thanked: 372 times

Re: myk's code contributions

Postby myk » 28 Feb 2013, 19:51

I plan to make it configurable, yeah. these will just be the defaults.
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby Max mtg » 28 Feb 2013, 20:00

friarsol wrote:Just so you know, in recent versions of Windows (Vista+) MS no longer uses the addage "My" it's just Documents. I can see where my saves go for Dragon Age when I get home.
Why would you do that? There's much simplier solution:

Code: Select all
File myDir = new File( System.getProperty("user.home"), ".forge" );
That returns C:\Users\Max\.forge on my Windows 7 station.

I already see here similiar folders from netbeans, m2, towns game, intellij-idea


And with those vbs we'll get falsely detected by antimalware tools.

There's also an environment variable in windows - APPDATA=C:\Users\Max\AppData\Roaming
This is where most apps store their settings & saves
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: myk's code contributions

Postby myk » 28 Feb 2013, 20:09

that's true, but those programs do it because they are unix-centric, and largely targeted at developers, who are more likely to know about dot files. Normal windows users don't expect their data to be there. Windows has standard directories that games are supposed to use for this kind of stuff, and I'd rather use them if possible.

edit: that's a potential point with the malware detection. I'll have to run some tests to see if that is an issue.
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby Max mtg » 28 Feb 2013, 20:17

Is there's any problem for Forge in being unix-centric as well?
Windows users see their home folder at very rare ocasions. They have shortcuts to subfolders of their home dir, downloads, whatever... but they never come to their home directory. May also use envirionment variable 'APPDATA'

See screenshots: http://techhamlet.com/wp-content/upload ... plorer.jpg or http://3.bp.blogspot.com/-nWYx2XWTqh4/U ... er-wac.png
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: myk's code contributions

Postby myk » 28 Feb 2013, 20:37

Max mtg wrote:Is there's any problem for Forge in being unix-centric as well?
That's a valid question. I am basing my proposal for the default path on what I have seen Windows games doing (Command and Conquer Generals, Elder Scrolls Oblivion, etc.) and the principle that when running on a particular platform, it is better to respect the standards of that platform so users intuitively know what to expect (the "principle of least astonishment"). From the posted bug reports, I know that a good percentage of our userbase uses Windows, so the directory we choose will affect quite a few people. If it takes a little more work to get the directory "right", I think it's worth it.

The reason I was going with My Games (or Games, or Juegos, or whatever it is called in the current version of windows in the current locale) instead of %APPDATA% is because %APPDATA% is a hidden directory and I wanted to keep these files accessible. It is an option, though, and has the advantage of roaming with you in a networked workstation environment. edit: another thought, I was mainly concerned with users not being able to get to their saved deck files, but users can always 'export' a deck to a file of their choice if they want to. %APPDATA% is looking a little better to me. Can anyone else think of any other factors to consider?
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

Re: myk's code contributions

Postby Max mtg » 28 Feb 2013, 21:56

The major titles you've named were developed for windows first, and then probably were ported to other os'es. Forge is different - it is platform independent, so we don't have to give that much honor to windows user home directory structure.

Yet, speaking of usability and ease of use and directory location, yoiu are right - my games is best. I've searched the net and found this method to obtain home directory: http://stackoverflow.com/questions/5855 ... ry-in-java
Still wondering how to reliably get 'my games' subfolder
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: myk's code contributions

Postby myk » 04 Mar 2013, 23:27

After some more research, I think following the example set by netbeans 7.2 will be easy to implement as a first approach, so I'll start with that. Their scheme also clued me into the OSX designated cache dir. I'm still waffling between using APPDATA and My Games for user data, though. APPDATA provides roaming and is consistent across windows versions, but My Games is easier to access and is a better choice if we want to make it easy for users to browse to a deck directory and decompress a bunch of decks into it. APPDATA, being a hidden directory, would make file browsing access more cumbersome. We could work around this with a 'import decks' UI that handles archives, but that would be additional work.

So, notwithstanding the final definition of userDir, here's my current plan:
  • if forge.profile.preferences exists in the root of the program dir, read it. it can contain overrides for the user and cache dirs. I'll add a forge.profile.preferences.example file as a template for how to use it. This will appease people who don't want forge data stored in standard OS locations. This will also make it easy for devs to have different data dirs for different branch checkouts but share a cache dir among all instances.
  • if there is data in the old directories, pop up a dialog explaining why we're moving the data (enable separation of 'official' and 'unofficial' content, hassle-free upgrades, etc.) and the user's options:
    1. have forge move data to new default dir and continue loading
    2. input a target directory and have forge autocreate a forge.profile.preferences file, then have forge move data to that dir and continue loading
    3. exit application
  • file moves:
    • res/decks/{constructed,draft,plane,scheme,sealed} -> userDir/decks/
    • res/gauntlet/*dat (except for LOCKED_*dat) -> userDir/gauntlet/
    • res/quest/data/* -> userDir/quest/
    • res/layouts/{editor,match}_preferred.xml -> userDir/layouts/
    • res/preferences/{editor,forge}.preferences -> userDir/preferences/
    • res/pics/* -> cacheDir/cache/pics/ (the extra 'cache' level is necessary since on some versions of Windows, userDir and cacheDir are the same directory; plus users may override the two dirs to be the same)
    • anything else?
  • organization is based on current layout. does anyone want to see any changes?

edit: the more research I do, the more applications I find that use APPDATA. people are instructed to type %appdata% into windows explorer to get to the folder and manage their saved games. If this is the "standard" solution, maybe we wouldn't need extra UI to make it easier to access.
myk
 
Posts: 439
Joined: 17 Jan 2013, 02:39
Location: California
Has thanked: 38 times
Been thanked: 57 times

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 7 guests


Who is online

In total there are 7 users online :: 0 registered, 0 hidden and 7 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 7 guests

Login Form