Eve Online is a space-based MMO that I have played it for several years.
One of the hallmarks of Eve Online is freedom. You are free to be just about as good or as evil as you want to be. In some ways, the game encourages you to be evil. In all cases the denizens of the game punish naivete with impunity, and the game encourages cut-throat capitalism.
The major draw of the game is purportedly PvP combat (even though only 19% of the game's population actually visit lawless space, according to CCP) -- blowing up other players for the sheer enjoyment of it. However, unlike other games, loss of a ship or death of your character has a potentially significant cost in the form of your time. In most PvP games, the death of one's character carries a negligible penalty. In Eve, you have to replace that ship, that clone, those enhancements. And that costs money (in-game), potentially a lot of money, which represents a significant time investment in the game. Smaller ships cost maybe a few hours of your time to earn back the money and buy and refit the ships. Larger ships can cost weeks or months of your time to recoup a loss. The largest of ships can take the efforts of an entire corporation or alliance many months to recoup. Character enhancements can potentially take weeks of effort to recoup a loss on top of ship loss.
Outsiders might wonder why you would play a game where one's time was wasted so wholesale. Well, Eve does have some less risky areas known as "high security space" (hi-sec). Anyone who attacks your ship unprovoked in hi-sec will quickly get their ship blown up by the police. It seems that most of the Eve Universe stays in hi-sec according to the same report from CCP.
However, hi-sec is not without risk. You are liable to be openly attacked if you carry very valuable cargo in an indefensible ship. The attackers will lose their ship, but you will likely lose your cargo to other players that scavenge your ships remains. They can scan your cargo hold before hand to make sure they will gain more than they lose. Hi-sec is also subject to corporate wars. Essentially a corporation or alliance may pay off the police to look the other way while you fight each other. The vast majority of hi-sec corp wars are started by small mercenary corps who are paid to do so or think your corp is a juicy enough target to profit from. Essentially corp wars are a version of police bribery and gangster-style "protection". Also, hi-sec is subject to scams of various kinds. Sometimes CCP (the makers of the game) punishes scams, but often times not. There are a lot of "scams" on the market where people count on your ignorance or mistakes (e.g. in one click, you've sold something for 500 thousand that you meant to or could have sold for 500 million). More often than not, the scams involve other people blowing up your ship. Either by using the market to lure you to low security space, or convoluted methods using the poor or non-existent warning indicators to mask a war that other people in a gang are involved in, making you also a valid target of their war (and said war was contrived only to enable the scam in the first place). [Edit: After many years of people being taken advantage of by poor gang mechanics, CCP finally decided to fix it with a recent patch.] There are also internal threats, corporate espionage, etc. If you make someone a director of a corp, and that person leaves the corp, taking every corporate asset with them, the GMs standard response is a politely-worded "Sucks to be you."
Eve is a very cold place. Being naive is the quickest path to losing something. Trust is never assumed. The game publishers seem to thrive on the whines of the swindled. Being cruel can be a profitable business. The worst parts of the real world are the worst parts of Eve, but in Eve they seem to be more pronounced because the game allows it, the consequences are light, and the people less inhibited.
Eve Online is a game that I hate to love. I hate the fact that Eve enables people to try to wreck the gameplay of others like no other game that I've played. The popular excuse for this is: "Eve is a pvp game". In reality, this sentiment should read "Eve is a griefer's game". Despite itself, Eve still manages to have a draw on non-maligned people. Maybe it's the market, or the skill system, or the open-ended nature of the game, or the free expansions, or the fact that you can play for free using in-game money, or the friends. Whatever it is, it's a fragile balance, and I hope one day the game moves further away from being a griefer's game.
28 February 2008
04 December 2007
PNGs - One Image To Rule The Navbar
Graphics for the navigation bar take up 181 bytes of space
A realization struck me today. With PNG files, I can create one tiny image for an entire navigation bar, including mouseovers. Specifically, I was thinking how often I only want to change a color on mouse-over, which has normally meant a separate image, but no more. And it gets better... using this one image method, I can even dynamically change the color of the "image" with CSS or Javascript if I need to. Did I mention it's cross-browser compatible?The One Image Way
A lot of folks tired of dealing with the tedium of image-based navigation buttons are probably already using the tileable background approach. This is where you create a small sliver of a background and repeat it in the x direction (for horizontal navigation bars), and place your text-based links on top. One Image takes that a step further.
Create the tileable background, but design the image with a solid background color and layer your effects on top of it rather than integrating blends and gloss into the background. Then delete the background color and save only the effects. (This takes some practice if you're not used to it.) Then, in the CSS background property, specify the image as well as the background color, like so:
...
background: #000 url(menu-fx.png) repeat-x ;
...
Now, if you want to change the hover, use the same background image, but only change the color:
...
background: #025 url(menu-fx.png) repeat-x ;
...
Working Example
To see an example of this in action, check out this page. The total amount of space taken up by graphics for this navigation bar is 181 bytes! And I can change the color at design time without saving out a new image (by specifying a different color in the CSS). And I can even change it dynamically with client-side script. If I do have to make changes to the shading or lighting, I only have to save down 1 file, not one file for every color.
Why It Works
This works with PNG files, but not GIFs, because PNG saves partial-transparencies. Those partial transparencies will be blended at run time with whatever color is behind it. So, in our case, the light effects blend at run time with the background color we specify. Contrast with GIFs, which saves transparent or not transparent, but no in-between. So, you have to know ahead of time the color of the background. If you later change background colors, you have to re-save the image with the proper blending around the edges or it will have noticeable distortions around the transparent parts.
Small Caveat
PNGs do not render transparency correctly by default in IE 6 and below. However, there's a fairly easy fix for this. If you follow that site's directions for inserting the script it will only run on browsers that need it. It won't even get loaded on the others! The script essentially invokes a Microsoft proprietary transform (filter:progid:DXImageTransform.Microsoft.AlphaImageLoader, for the twisted among you that has to know) which correctly renders the image.
There are other scripts out there that accomplish this same thing, but this is the first one I ran across, and it has worked like a charm for me.
What's Next
One day, I'd like to see a cross between a programming API and an image format where I can store all my variations of a graphic in one file and change attributes of it at run time (like background color, or size) as needed for the task at hand through client-side code or CSS. It will require some intelligent design and layering on the part of the graphic artist, but it's reuse value will be extremely high.
29 November 2007
ASP .NET 2.0 User Controls
I'm struggling to find a good use for User Controls.
All I wanted to do was wrap some standard web controls (like a login box) in a pretty container. .NET's default theming is insufficient for this, as it allows you to theme certain properties, but doesn't allow you to customize the control to any large degree. For instance, what I wanted to do was create a pretty table-based box, which is about 19 lines of normal HTML/ASP:
And be able to specify them like so:
or even:
I was able to get the latter to work to a very limited degree, but it had enough limits that it wouldn't work for me.
First, I looked at a templated control from MSDN. Unfortunately, Microsoft's idea of a templated user control revolves more around the data than the UI, so this example is no help.
Another way is found here, and it correctly renders the controls inside the PlaceHolder, but in VS 2005, the designer refuses to keep tabs on any controls inside my user control, so without some manual accounting on my part (i.e. declaring the controls as page variables manually), I lose programmatic access to any controls inside the user control, which is unacceptable.
I found that I could user Mr. Seder's code and make the code designer behave correctly by putting these lines over the class declaration of the user control:
But this caused the ContentTemplate to be completely ignored, so all the controls inside my user control would render after the pretty box rather than inside it's PlaceHolder.
The closest working thing I found was this, but that was a lot more hassle than I wanted just to save myself 15-17 lines of code for each box, and all the controls were created dynamically. It's essentially a server control, which defeats the whole point of a user control that you can see more easily from a visual design standpoint.
I find it very frustrating that I can't make a simple user control that wraps HTML around other controls in ASP .NET 2.0. Probably what I'll end up resorting to is making two user controls, one called prettyBoxStart with a title attribute, and one called prettyBoxEnd, both of them being unary tags:
It's pretty lame, and it's barely better than an include, but at least it works, unlike all that user control junk.
All I wanted to do was wrap some standard web controls (like a login box) in a pretty container. .NET's default theming is insufficient for this, as it allows you to theme certain properties, but doesn't allow you to customize the control to any large degree. For instance, what I wanted to do was create a pretty table-based box, which is about 19 lines of normal HTML/ASP:
<table class="prettyBox" cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="nw"><br /></td>
<th class="n"><asp:Label ID="title" runat="server" Text="Label"></asp:Label></th>
<td class="ne"><br /></td>
</tr>
<tr>
<td class="w"><br /></td>
<td class="contents">
<asp:PlaceHolder ID="content" runat="server"></asp:PlaceHolder>
</td>
<td class="e"><br /></td>
</tr>
<tr>
<td class="sw"><span></span></td>
<td class="s"><span></span></td>
<td class="se"><span></span></td>
</tr>
</table>
And be able to specify them like so:
<uc:prettyBox ID="pb1" runat="server" Title="Log In">
<asp:Login ID="login1" runat="server"></asp:LoginControl>
</uc:prettyBox>
or even:
<uc:prettyBox ID="pb1" runat="server" Title="Log In">
<ContentTemplate>
<asp:Login ID="login1" runat="server"></asp:LoginControl>
</ContentTemplate>
</uc:prettyBox>
I was able to get the latter to work to a very limited degree, but it had enough limits that it wouldn't work for me.
First, I looked at a templated control from MSDN. Unfortunately, Microsoft's idea of a templated user control revolves more around the data than the UI, so this example is no help.
Another way is found here, and it correctly renders the controls inside the PlaceHolder, but in VS 2005, the designer refuses to keep tabs on any controls inside my user control, so without some manual accounting on my part (i.e. declaring the controls as page variables manually), I lose programmatic access to any controls inside the user control, which is unacceptable.
I found that I could user Mr. Seder's code and make the code designer behave correctly by putting these lines over the class declaration of the user control:
[Designer("ContainerControlDesigner")]
[ParseChildren(false)]
But this caused the ContentTemplate to be completely ignored, so all the controls inside my user control would render after the pretty box rather than inside it's PlaceHolder.
The closest working thing I found was this, but that was a lot more hassle than I wanted just to save myself 15-17 lines of code for each box, and all the controls were created dynamically. It's essentially a server control, which defeats the whole point of a user control that you can see more easily from a visual design standpoint.
I find it very frustrating that I can't make a simple user control that wraps HTML around other controls in ASP .NET 2.0. Probably what I'll end up resorting to is making two user controls, one called prettyBoxStart with a title attribute, and one called prettyBoxEnd, both of them being unary tags:
<uc:prettyBoxStart ID="pbs1" runat="server" Title="Log In" />
<asp:Login ID="login1" runat="server"></asp:LoginControl>
<uc:prettyBoxEnd ID="pbe1" runat="server />
It's pretty lame, and it's barely better than an include, but at least it works, unlike all that user control junk.
26 November 2007
Leopard Tricks and Changes
I've installed Leopard a few times now. (2 home machines and 1 work machine twice). Here are some tips from my experience.
P.S. ps is different
[Edit: As of 10.5.1 or 10.5.2, they changed it back to the BSD style command-line arguments.]
Those of you who do linux system admin probably know the ps command. In Tiger, the ps command used BSD syntax (e.g. ps -aux to get all processes, with -e not working), but in Leopard, it seems that the Linux syntax is now favored (e.g. ps -ef to get all processes). The -u flag of ps no longer works and will give a warning.
Build a New Firewall
When I was restoring my laptop, one of the things that did not translate over (probably because it didn't translate from the upgrade) was my firewall. I had to reconfigure the firewall in Leopard. Fortunately, I only had one custom entry, but still...
Restoring From an Unsupported Drive
You may or may not have seen the nice little command that lets Time Machine backup to SMB shares:
defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1
Well, one of the things that was sketchy about the whole thing (aside from backing up over wireless) was how you're going to restore that backup. I did this and I'll tell you how.
Note: I used the User Migration Assistant, not the Leopard DVD to restore the backup. I played at using the DVD, but couldn't get the defaults write command to work (read-only filesystem of the DVD, I guess), so I figured it was pointless. However, I didn't actually try to mount_smb the filesystem, hoping that Time Machine would already be able see it.
Assumptions:
You used the defaults write command to allow Time Machine to backup to unsupported network drives (e.g. SMB share).
You successfully made a recent backup to the SMB share.
Firstly, you need to do a fresh install of Leopard on the target machine. When you get to the point where it asks you for a username, make sure the new username is different from the other usernames on the old system. I'd do something like tmpadmin (Temp Admin).
Secondly, log in and run the defaults write command to get Time Machine cooperative.
Thirdly, mount the SMB share you want to restore from and double-click the .sparsebundle inside the SMB share to mount it. Then start the User Migration Assistant (under Applications -> Utilities). Select the option to use a Time Machine backup. It may take it a while to pop up the SMB share as an option. Afterwards, select what you want to restore. I selected everything I could check.
Lastly, log out and back in as your normal user (assuming it's an Admin account also). Then delete the temporary account, so you don't have an extra admin account floating around.
I was actually really impressed with this. It even restored a custom /etc/hosts.allow that I created!
P.S. ps is different
[Edit: As of 10.5.1 or 10.5.2, they changed it back to the BSD style command-line arguments.]
Those of you who do linux system admin probably know the ps command. In Tiger, the ps command used BSD syntax (e.g. ps -aux to get all processes, with -e not working), but in Leopard, it seems that the Linux syntax is now favored (e.g. ps -ef to get all processes). The -u flag of ps no longer works and will give a warning.
Build a New Firewall
When I was restoring my laptop, one of the things that did not translate over (probably because it didn't translate from the upgrade) was my firewall. I had to reconfigure the firewall in Leopard. Fortunately, I only had one custom entry, but still...
Restoring From an Unsupported Drive
You may or may not have seen the nice little command that lets Time Machine backup to SMB shares:
defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1
Well, one of the things that was sketchy about the whole thing (aside from backing up over wireless) was how you're going to restore that backup. I did this and I'll tell you how.
Note: I used the User Migration Assistant, not the Leopard DVD to restore the backup. I played at using the DVD, but couldn't get the defaults write command to work (read-only filesystem of the DVD, I guess), so I figured it was pointless. However, I didn't actually try to mount_smb the filesystem, hoping that Time Machine would already be able see it.
Assumptions:
You used the defaults write command to allow Time Machine to backup to unsupported network drives (e.g. SMB share).
You successfully made a recent backup to the SMB share.
Firstly, you need to do a fresh install of Leopard on the target machine. When you get to the point where it asks you for a username, make sure the new username is different from the other usernames on the old system. I'd do something like tmpadmin (Temp Admin).
Secondly, log in and run the defaults write command to get Time Machine cooperative.
Thirdly, mount the SMB share you want to restore from and double-click the .sparsebundle inside the SMB share to mount it. Then start the User Migration Assistant (under Applications -> Utilities). Select the option to use a Time Machine backup. It may take it a while to pop up the SMB share as an option. Afterwards, select what you want to restore. I selected everything I could check.
Lastly, log out and back in as your normal user (assuming it's an Admin account also). Then delete the temporary account, so you don't have an extra admin account floating around.
I was actually really impressed with this. It even restored a custom /etc/hosts.allow that I created!
15 October 2007
ASP .NET 2.0 Data Woes
As I write this, I have come to the realization that there are two sure ways to drive yourself insane when doing ASP .NET 2.0 programming involving a database.
1) Use no keys in a table.
2) Try to use an SqlDataSource with a run-time-provided table name.
No Keys, No Functionality
The first one may seem fairly obvious. However, we have a database that does not have keys, because it has simply not needed them until I came along to program a front end for it. Any time you try to take advantage of some of those shiny new objects like SqlDataSource or even a GridView bound to a DataTable, the lack of keys will bite you every time you attempt an update or delete. If you have to go keyless for some strange reason, you will have to write your own event handlers and run the queries manually. You might as well go back to .NET 1.1 and handle it all yourself. SqlDataSource comes closest to working without keys, so long as you specify custom update and delete statements, and the delete statement doesn't depend on using a parameterized WHERE clause. You see, .NET 2.0 won't pass the parameters unless they are keys... even if you specify those column names as parameters.
Gotta Know Up Front
The second one was a little more elusive. The first thing I tried was to use a parameter for the table name. Essentially, you can't do that. This is because the parameter would have to be of type string (because nothing else makes sense), and .NET wraps string parameters in single quotes before executing the query. As of this writing, I have not found a way to prevent it from doing this, and your SQL server sees anything with quotes around it as a string value, rather than a database object. Also string-based functions like REPLACE or SUBSTRING return strings, not database objects, so you can't run that quoted string through them to fix it either. Perhaps it would be possible with stored procedures. How about writing new database stored procedures to work around the inflexibility of your shiny new .NET 2.0 object? Yeah, that sounds pretty lame to me too.
So after giving up on using a parameter for a table name, my next step was to try to dynamically generate SqlDataSource properties each time a different table was chosen. After all, I couldn't be sure when new tables were added, so I didn't want to create one for each table and then later go back to create more as they were added. Well, let me just say again: You might as well go back to .NET 1.1 and handle the queries yourself. You see, even if you declaratively (i.e. with a asp:SqlDataSource tag in your .aspx page) create an SqlDataSource, any properties that you assign to it programmatically are lost between trips to the server. At first I tried just changing the SelectCommand programmatically (i.e. in the codebehind page) to select from a different table, but when the user goes to page through or sort the data, the SelectCommand reverts back to it's original statement as written in the asp:SqlDataSource tag. So then in order for you to show the user the data they expect, you have to setup a page variable to store the data for those properties, and use handlers to fix the SqlDataSource after every trip to the server, like so:
Oh, but it gets worse. When you change tables, the GridView still remembers the user's last sorting and page index, so you have to reset those when you change tables.
Then there's the "what if" of wanting the user to be able to actually edit the data in the GridView.
But wait, there's more:
So in the end, I'm left with a "What's the point?" mentality. Dynamically picking your table to select from at run time is for the hard core, not for me.
Why is that a problem? After all isn't it "job security" since they have to depend on me to update the code with a new declarative SqlDataSource when a new table is added to the database.
Well honestly Microsoft, I'd rather be less annoyed with trivial code updates. How about a way to pick the table to select from at run-time in 3.0?
1) Use no keys in a table.
2) Try to use an SqlDataSource with a run-time-provided table name.
No Keys, No Functionality
The first one may seem fairly obvious. However, we have a database that does not have keys, because it has simply not needed them until I came along to program a front end for it. Any time you try to take advantage of some of those shiny new objects like SqlDataSource or even a GridView bound to a DataTable, the lack of keys will bite you every time you attempt an update or delete. If you have to go keyless for some strange reason, you will have to write your own event handlers and run the queries manually. You might as well go back to .NET 1.1 and handle it all yourself. SqlDataSource comes closest to working without keys, so long as you specify custom update and delete statements, and the delete statement doesn't depend on using a parameterized WHERE clause. You see, .NET 2.0 won't pass the parameters unless they are keys... even if you specify those column names as parameters.
Gotta Know Up Front
The second one was a little more elusive. The first thing I tried was to use a parameter for the table name. Essentially, you can't do that. This is because the parameter would have to be of type string (because nothing else makes sense), and .NET wraps string parameters in single quotes before executing the query. As of this writing, I have not found a way to prevent it from doing this, and your SQL server sees anything with quotes around it as a string value, rather than a database object. Also string-based functions like REPLACE or SUBSTRING return strings, not database objects, so you can't run that quoted string through them to fix it either. Perhaps it would be possible with stored procedures. How about writing new database stored procedures to work around the inflexibility of your shiny new .NET 2.0 object? Yeah, that sounds pretty lame to me too.
So after giving up on using a parameter for a table name, my next step was to try to dynamically generate SqlDataSource properties each time a different table was chosen. After all, I couldn't be sure when new tables were added, so I didn't want to create one for each table and then later go back to create more as they were added. Well, let me just say again: You might as well go back to .NET 1.1 and handle the queries yourself. You see, even if you declaratively (i.e. with a asp:SqlDataSource tag in your .aspx page) create an SqlDataSource, any properties that you assign to it programmatically are lost between trips to the server. At first I tried just changing the SelectCommand programmatically (i.e. in the codebehind page) to select from a different table, but when the user goes to page through or sort the data, the SelectCommand reverts back to it's original statement as written in the asp:SqlDataSource tag. So then in order for you to show the user the data they expect, you have to setup a page variable to store the data for those properties, and use handlers to fix the SqlDataSource after every trip to the server, like so:
<asp:GridView ID="GridView1"
...
OnPageIndexChanging="fixDataSource"
OnSorting="fixDataSource"
...
Oh, but it gets worse. When you change tables, the GridView still remembers the user's last sorting and page index, so you have to reset those when you change tables.
// remember these will also call fixDataSource as well
GridView.Sort("", SortDirection.Ascending);
GridView.PageIndex = 0;
Then there's the "what if" of wanting the user to be able to actually edit the data in the GridView.
<asp:GridView ID="GridView1"
...
OnPageIndexChanging="fixDataSource"
OnSorting="fixDataSource"
OnRowCancelingEdit="fixDataSource"
OnRowDeleting="fixDataSource"
OnRowEditing="fixDataSource"
OnRowUpdating="fixDataSource"
...
But wait, there's more:
<asp:SqlDataSource ID="SqlDataSource1"
...
OnDeleting="fixDataSource"
OnUpdating="fixDataSource"
...
So in the end, I'm left with a "What's the point?" mentality. Dynamically picking your table to select from at run time is for the hard core, not for me.
Why is that a problem? After all isn't it "job security" since they have to depend on me to update the code with a new declarative SqlDataSource when a new table is added to the database.
Well honestly Microsoft, I'd rather be less annoyed with trivial code updates. How about a way to pick the table to select from at run-time in 3.0?
27 August 2007
More on Synergy
I setup Synergy again. This time with my Mac Laptop as the server, and then my Windows desktop as the client. The Mac being the server made it where I still had my nice input device functionality in OS X and also now in Windows! It also avoided some Synergy client bugs like my screen saver Hot Corner ceasing to work, and the screen savers not syncronizing. They still don't synchronize unlocking, but at least the Windows screen saver starts when I start the OS X one.
There are various obstacles to overcome with this setup, however:
Problem 1: Synergy is not secure. All traffic is passed in plain text, so if I needed to type a password on the client, it would go across the network in plain text. This is not acceptable for my setup.
Solution 1: Setup an SSH tunnel between my desktop and my laptop. The MacBook laptop is the SSH server, and the Windows Desktop is the SSH client. After getting the initial setup working, I then took extra security hardening steps to make sure no one else could connect. These included turning off passworded logins (using only key-based logins), and creating an /etc/hosts.allow that denied all ssh connections except from my Windows desktop. (Yes, you can do it all just from hosts.allow.)
Problem 2: I need to be able to disconnect my laptop and take it somewhere else, then have it automatically reconnect when I hook it back up in my office. While the Synergy client keeps trying to reconnect, SSH tunnels may not. Also, SSH tunnels typically don't start until you log into Windows. That would mean I'd have to hook the keyboard up to the Windows desktop, log in, then hook the keyboard up to the Mac to use synergy. That kind of keyboard swapping is not acceptable either.
Solution 2: This is a fairly complicated setup, and not for the faint of heart. The use of plink from the PuTTY ssh programs in combination with the a program from the Windows 2003 Resource Kit (my desktop is running XP Pro) called AutoExNT allows me to start an SSH tunnel when Windows starts. Using an infinite loop and a sleep inside the batch file that starts the connection, I can have it retry the connection every so often so that if I take my laptop (and break the connection) and bring it back, it will automatically reconnect the SSH tunnel. You have to also set Synergy up to connect at system startup rather than at login, but that part is just a few clicks. Using this setup, I can reboot the Windows machine and move the mouse over to the Windows screen and hit Ctrl-Alt-Delete to log in over Synergy. I can also take my laptop home and bring it back, and Synergy automatically reconnects securely!
All in all, this is a lot of work to setup, but after the initial pain of setup, it's nice to be able to just plug everything up and it just works. :)
There are various obstacles to overcome with this setup, however:
Problem 1: Synergy is not secure. All traffic is passed in plain text, so if I needed to type a password on the client, it would go across the network in plain text. This is not acceptable for my setup.
Solution 1: Setup an SSH tunnel between my desktop and my laptop. The MacBook laptop is the SSH server, and the Windows Desktop is the SSH client. After getting the initial setup working, I then took extra security hardening steps to make sure no one else could connect. These included turning off passworded logins (using only key-based logins), and creating an /etc/hosts.allow that denied all ssh connections except from my Windows desktop. (Yes, you can do it all just from hosts.allow.)
Problem 2: I need to be able to disconnect my laptop and take it somewhere else, then have it automatically reconnect when I hook it back up in my office. While the Synergy client keeps trying to reconnect, SSH tunnels may not. Also, SSH tunnels typically don't start until you log into Windows. That would mean I'd have to hook the keyboard up to the Windows desktop, log in, then hook the keyboard up to the Mac to use synergy. That kind of keyboard swapping is not acceptable either.
Solution 2: This is a fairly complicated setup, and not for the faint of heart. The use of plink from the PuTTY ssh programs in combination with the a program from the Windows 2003 Resource Kit (my desktop is running XP Pro) called AutoExNT allows me to start an SSH tunnel when Windows starts. Using an infinite loop and a sleep inside the batch file that starts the connection, I can have it retry the connection every so often so that if I take my laptop (and break the connection) and bring it back, it will automatically reconnect the SSH tunnel. You have to also set Synergy up to connect at system startup rather than at login, but that part is just a few clicks. Using this setup, I can reboot the Windows machine and move the mouse over to the Windows screen and hit Ctrl-Alt-Delete to log in over Synergy. I can also take my laptop home and bring it back, and Synergy automatically reconnects securely!
All in all, this is a lot of work to setup, but after the initial pain of setup, it's nice to be able to just plug everything up and it just works. :)
02 July 2007
Synergy showed me how great OS X is...
This is a followup to my article about switching from Windows to the Mac.
I was playing around with a really cool, open-source product called Synergy. Synergy allows you to use one mouse and keyboard across multiple computers, even computers with different operating systems. I'm using the mouse and keyboard from my Ubuntu box to type this article on my Mac. This kind of setup is very handy for system administrators, since I can have documentation open on one screen and perform commands on the other without a lot of tedious switching back and forth. Synergy even allows them to share a clipboard!
What this has to do with switching to the Mac. Well, Synergy uses the keyboard and mouse settings from the Synergy server, which in my case is Ubuntu Linux. I'm just now noticing some of the subtle features that I now don't have in OS X through Synergy keyboard and mouse emulation. For instance, mouse wheel scrolling acceleration. If you scroll the wheel really slowly in OS X, it only scrolls 1/2 or 1/4 lines, and the faster you scroll the wheel, the more lines it scrolls at a time. I use this all the time, and I only now realized it because it's missing! In Linux, the number of scroll lines is fixed for each scroll, so even if I scroll slowly, it still does the same number of lines as when I scroll quickly.
It's the little things like this that are hard to define when you're using a Mac that make it much nicer to use than pretty much anything else out there.
I was playing around with a really cool, open-source product called Synergy. Synergy allows you to use one mouse and keyboard across multiple computers, even computers with different operating systems. I'm using the mouse and keyboard from my Ubuntu box to type this article on my Mac. This kind of setup is very handy for system administrators, since I can have documentation open on one screen and perform commands on the other without a lot of tedious switching back and forth. Synergy even allows them to share a clipboard!
What this has to do with switching to the Mac. Well, Synergy uses the keyboard and mouse settings from the Synergy server, which in my case is Ubuntu Linux. I'm just now noticing some of the subtle features that I now don't have in OS X through Synergy keyboard and mouse emulation. For instance, mouse wheel scrolling acceleration. If you scroll the wheel really slowly in OS X, it only scrolls 1/2 or 1/4 lines, and the faster you scroll the wheel, the more lines it scrolls at a time. I use this all the time, and I only now realized it because it's missing! In Linux, the number of scroll lines is fixed for each scroll, so even if I scroll slowly, it still does the same number of lines as when I scroll quickly.
It's the little things like this that are hard to define when you're using a Mac that make it much nicer to use than pretty much anything else out there.
Subscribe to:
Posts (Atom)