Changeset b01abbe


Ignore:
Timestamp:
Aug 13, 2010, 4:26:11 PM (8 years ago)
Author:
Michael Seifert <mseifert@…>
Branches:
master
Children:
7c832f6
Parents:
2e067d5
Message:

sc2replay:
Support for version 3 grouping events;
action factories share read methods for individual actions by inheriting them from an abstract superclass

Location:
sc2replay/src/main/java/de/erichseifert/warp/sc2replay/actions
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • sc2replay/src/main/java/de/erichseifert/warp/sc2replay/actions/SC2ActionFactory_v1v2.java

    r2e067d5 rb01abbe  
    2424import java.io.File;
    2525import java.nio.ByteBuffer;
    26 import java.util.WeakHashMap;
    2726
    28 import de.erichseifert.warp.core.replay.GameActionFactory;
    29 import de.erichseifert.warp.sc2replay.actions.Order.OrderCode;
    3027import de.erichseifert.warp.sc2replay.util.SC2ReplayUtil;
    3128
    32 public class SC2ActionFactory_v1v2 implements GameActionFactory<SC2Action> {
     29public class SC2ActionFactory_v1v2 extends SC2ActionFactory {
    3330        private static final byte CODE_SYNC = 0x00;
    3431        private static final byte CODE_START_GAME = 0x05;
     
    4542        private static final byte CODE_SEND_RESOURCES = 0x0F;
    4643
    47         private static final WeakHashMap<File, SC2ActionFactory_v1v2> instances = new WeakHashMap<File, SC2ActionFactory_v1v2>();
    48         private int timeStamp;
    49 
    50         private SC2ActionFactory_v1v2() {
    51                 timeStamp = 0;
     44        protected SC2ActionFactory_v1v2() {
    5245        }
    5346
     
    6962                if (code == CODE_ORDER && eventTypeCode == 1) {
    7063                        action = new Order(timeStamp);
    71                         // Skip the first three bytes. Always seems to be 0x00 0x00 0x10
    72                         src.position(src.position()+3);
    73                         // Seems to be the subgroup that is targeted with the action
    74                         byte subgroup = src.get();
    75                         ((Order) action).setSubgroup(subgroup);
    76                         // Seems to be the type of the action and serves as a kind of codepage for the action IDs.
    77                         byte actionType = src.get();
    78                         short actionID = src.getShort();
    79                         OrderCode orderCode = new OrderCode(actionType, actionID);
    80                         ((Order) action).setOrderCode(orderCode);
    81 
    82                         byte unknown = src.get();
    83                         if ((unknown & 0x10) != 0) {
    84                                 src.position(src.position()+25);
    85                         }
    86                         else {
    87                                 src.position(src.position()+24);
    88                         }
    89                         //System.out.println("Order action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     64                        readOrder(src, (Order) action);
    9065                }
    9166                else if ((code & 0xF) == CODE_GROUPX) {
    9267                        action = new Group(timeStamp);
    93                         int header1 = src.get();
    94                         // This most likely means that a new group was assigned
    95                         boolean assigned = (header1 & 0x2) != 0;
    96                         ((Group) action).setAssigned(assigned);
    97                         boolean flag2 = (header1 & 0x1) != 0;
    98                         int header2 = src.get();
    99                         int bitLength = (header1 & 0xFC) + (header2 & 0x3);
    100                         bitLength -= 6;
    101                         int byteCount = Math.max(0, (int) Math.ceil(bitLength/8.0));
    102                         src.position(src.position()+byteCount);
    103                         //System.out.println("Group action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     68                        readGroup(src, (Group) action);
    10469                }
    10570                else if (code == CODE_MOVE_SCREEN) {
    10671                        action = new MoveScreen(timeStamp);
    107                         src.position(src.position()+20);
    108                         //System.out.println("Move screen action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     72                        readMoveScreen(src, (MoveScreen) action);
    10973                }
    11074                else if (code == CODE_SELECT) {
    111                         action = getSelect(timeStamp,src);
     75                        action = new Select(timeStamp);
     76                        readSelect(src, (Select) action);
    11277                }
    11378                else if ((code & 0xF) == CODE_GROUP_UPDATED) {
    11479                        if (eventTypeCode == 1) {
    115                                 action = getSelect(timeStamp,src);
     80                                action = new Select(timeStamp);
     81                                readSelect(src, (Select) action);
    11682                        }
    11783                        else {
     
    12288                else if (code == CODE_LEAVE_GAME) {
    12389                        action = new LeaveGame(timeStamp);
     90                        readLeaveGame(src, (LeaveGame) action);
    12491                        //System.out.println("Leave action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    12592                }
     
    136103                else if ((code & 0xF) == CODE_SEND_RESOURCES) {
    137104                        action = new SendResources(timeStamp);
    138                         // Skip 17 bytes
    139                         src.position(src.position()+17);
    140                         //System.out.println("Send resources action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     105                        readSendResources(src, (SendResources) action);
    141106                }
    142107                else if (code == CODE_SYNC || code == CODE_UNKNOWN3) {
    143108                        action = new Sync(timeStamp);
    144                         // Skip four bytes
    145                         src.position(src.position()+4);
    146                         //System.out.println("Sync action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     109                        readSync(src, (Sync) action);
    147110                }
    148111                else if ((code & 0xF) == CODE_ENTER_GAME && eventTypeCode == 0) {
     
    161124        }
    162125
     126        @Override
     127        protected void readMoveScreen(ByteBuffer src, MoveScreen action) {
     128                src.position(src.position()+20);
     129                //System.out.println("Move screen action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     130        }
     131
    163132        /**
    164133         * Returns an instance of this factory.
    165134         * @return Instance.
    166135         */
    167         public static GameActionFactory<SC2Action> getInstance(File file) {
    168                 SC2ActionFactory_v1v2 instance = instances.get(file);
     136        public static SC2ActionFactory getInstance(File file) {
     137                SC2ActionFactory instance = instances.get(file);
    169138                if (instance == null) {
    170139                        instance = new SC2ActionFactory_v1v2();
     
    174143        }
    175144
    176         private Select getSelect(int timeStamp, ByteBuffer src) {
    177                 Select action = new Select(timeStamp);
    178                 // FIXME: Deal with unsigned values
    179                 // Selected subgroup
    180                 byte subgroup = src.get();
    181                 // Number of units in the current selection
    182                 int deselectionCount = src.get() & 0xFF;
    183                 int shiftCount = deselectionCount % 8;
    184                 // Number of bytes following to describe the deselected bits
    185                 int deselectionByteCount = deselectionCount/8;
    186                 if (shiftCount > 0) {
    187                         deselectionByteCount += 1;
    188                 }
    189                 boolean[] deselectionMap = new boolean[deselectionCount];
    190                 byte flagByte = 0;
    191                 byte lastByte = 0;
    192                 byte nextByte = 0;
    193                 for (int i = 0; i < deselectionByteCount; i++) {
    194                         flagByte = src.get();
    195                         for (int j = 0; j < 8; j++) {
    196                                 if (8*i + j == deselectionCount) {
    197                                         lastByte = flagByte;
    198                                         break;
    199                                 }
    200                                 deselectionMap[8*i + j] = true ? ((flagByte >> j) & 0x1) != 0 : false;
    201                         }
    202                 }
    203 
    204                 if (shiftCount == 0) {
    205                         int unitTypeCount = src.get();
    206                         for (int i = 0; i < unitTypeCount; i++) {
    207                                 int unitTypeID = (src.get() << 16) + (src.get() << 8) + src.get();
    208                                 int unitCount = src.get();
    209                         }
    210                         int unitCountTotal = src.get() & 0xFF;
    211                         for (int i = 0; i < unitCountTotal; i++) {
    212                                 int unitID = src.getInt();
    213                         }
    214                 }
    215                 else {
    216                         nextByte = src.get();
    217                         // Number of different unit types
    218                         int unitTypeCount = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    219                         lastByte = nextByte;
    220                         nextByte = src.get();
    221                         for (int i = 0; i < unitTypeCount; i++) {
    222                                 // Read unit type
    223                                 int unitType = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount))) << 16;
    224                                 lastByte = nextByte;
    225                                 nextByte = src.get();
    226                                 unitType += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount))) << 8;
    227                                 lastByte = nextByte;
    228                                 nextByte = src.get();
    229                                 unitType += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    230                                 lastByte = nextByte;
    231                                 nextByte = src.get();
    232 
    233                                 // Read number of units with this type
    234                                 int unitCount = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    235                                 lastByte = nextByte;
    236                                 nextByte = src.get();
    237                         }
    238 
    239                         // Read units
    240                         int unitCountTotal = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    241                         for (int i = 0; i < unitCountTotal; i++) {
    242                                 lastByte = nextByte;
    243                                 nextByte = src.get();
    244                                 int unitID = ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 24;
    245                                 lastByte = nextByte;
    246                                 nextByte = src.get();
    247                                 unitID += ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 16;
    248                                 lastByte = nextByte;
    249                                 nextByte = src.get();
    250                                 unitID += ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 8;
    251                                 lastByte = nextByte;
    252                                 nextByte = src.get();
    253                                 unitID += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    254                         }
    255                 }
    256                 //System.out.println("Select action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    257                 return action;
     145        @Override
     146        protected void readGroup(ByteBuffer src, Group action) {
     147                int header1 = src.get();
     148                // This most likely means that a new group was assigned
     149                boolean assigned = (header1 & 0x2) != 0;
     150                action.setAssigned(assigned);
     151                boolean flag2 = (header1 & 0x1) != 0;
     152                int header2 = src.get();
     153                int bitLength = (header1 & 0xFC) + (header2 & 0x3);
     154                bitLength -= 6;
     155                int byteCount = Math.max(0, (int) Math.ceil(bitLength/8.0));
     156                src.position(src.position()+byteCount);
     157                //System.out.println("Group action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    258158        }
    259159}
  • sc2replay/src/main/java/de/erichseifert/warp/sc2replay/actions/SC2ActionFactory_v3.java

    r2e067d5 rb01abbe  
    2424import java.io.File;
    2525import java.nio.ByteBuffer;
    26 import java.util.WeakHashMap;
    2726
    28 import de.erichseifert.warp.core.replay.GameActionFactory;
    29 import de.erichseifert.warp.sc2replay.actions.Order.OrderCode;
    3027import de.erichseifert.warp.sc2replay.util.SC2ReplayUtil;
    3128
    32 public class SC2ActionFactory_v3 implements GameActionFactory<SC2Action> {
     29public class SC2ActionFactory_v3 extends SC2ActionFactory {
    3330        private static final byte CODE_SYNC = 0x00;
    3431        private static final byte CODE_START_GAME = 0x05;
     
    4542        private static final byte CODE_SEND_RESOURCES = 0x0F;
    4643
    47         private static final WeakHashMap<File, SC2ActionFactory_v3> instances = new WeakHashMap<File, SC2ActionFactory_v3>();
    48         private int timeStamp;
    49 
    50         private SC2ActionFactory_v3() {
    51                 timeStamp = 0;
     44        protected SC2ActionFactory_v3() {
    5245        }
    5346
     
    6962                if (code == CODE_ORDER && eventTypeCode == 1) {
    7063                        action = new Order(timeStamp);
    71                         // Skip the first three bytes. Always seems to be 0x00 0x00 0x10
    72                         src.position(src.position()+3);
    73                         // Seems to be the subgroup that is targeted with the action
    74                         byte subgroup = src.get();
    75                         ((Order) action).setSubgroup(subgroup);
    76                         // Seems to be the type of the action and serves as a kind of codepage for the action IDs.
    77                         byte actionType = src.get();
    78                         short actionID = src.getShort();
    79                         OrderCode orderCode = new OrderCode(actionType, actionID);
    80                         ((Order) action).setOrderCode(orderCode);
    81 
    82                         byte unknown = src.get();
    83                         if ((unknown & 0x10) != 0) {
    84                                 src.position(src.position()+25);
    85                         }
    86                         else {
    87                                 src.position(src.position()+24);
    88                         }
    89                         //System.out.println("Order action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     64                        readOrder(src, (Order) action);
    9065                }
    9166                else if ((code & 0xF) == CODE_GROUPX) {
    9267                        action = new Group(timeStamp);
    93                         int header1 = src.get();
    94                         // This most likely means that a new group was assigned
    95                         boolean assigned = (header1 & 0x2) != 0;
    96                         ((Group) action).setAssigned(assigned);
    97                         boolean flag2 = (header1 & 0x1) != 0;
    98                         int header2 = src.get();
    99                         int bitLength = (header1 & 0xFC) + (header2 & 0x3);
    100                         bitLength -= 6;
    101                         int byteCount = Math.max(0, (int) Math.ceil(bitLength/8.0));
    102                         src.position(src.position()+byteCount);
    103                         //System.out.println("Group action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     68                        readGroup(src, (Group) action);
    10469                }
    10570                else if (code == CODE_SELECT) {
    106                         action = getSelect(timeStamp,src);
     71                        action = new Select(timeStamp);
     72                        readSelect(src, (Select) action);
    10773                }
    10874                else if ((code & 0xF) == CODE_GROUP_UPDATED) {
    10975                        if (eventTypeCode == 1) {
    110                                 action = getSelect(timeStamp,src);
     76                                action = new Select(timeStamp);
     77                                readSelect(src, (Select) action);
    11178                        }
    11279                        else {
     
    11784                else if (code == CODE_LEAVE_GAME) {
    11885                        action = new LeaveGame(timeStamp);
     86                        readLeaveGame(src, (LeaveGame) action);
    11987                        //System.out.println("Leave action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    12088                }
     
    13199                else if ((code & 0xF) == CODE_SEND_RESOURCES) {
    132100                        action = new SendResources(timeStamp);
    133                         // Skip 17 bytes
    134                         src.position(src.position()+17);
    135                         //System.out.println("Send resources action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     101                        readSendResources(src, (SendResources) action);
    136102                }
    137103                else if (code == CODE_SYNC || code == CODE_UNKNOWN3) {
    138104                        action = new Sync(timeStamp);
    139                         // Skip four bytes
    140                         src.position(src.position()+4);
    141                         //System.out.println("Sync action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     105                        readSync(src, (Sync) action);
    142106                }
    143107                else if ((code & 0xF) == CODE_ENTER_GAME && eventTypeCode == 0) {
    144108                        action = new EnterGame(timeStamp);
     109                        readEnterGame(src, (EnterGame) action);
    145110                }
    146111                else if (code == CODE_START_GAME) {
    147112                        action = new StartGame(timeStamp);
     113                        readStartGame(src, (StartGame) action);
    148114                }
    149115                else if ((code & 0x0F) == CODE_MOVE_SCREEN) {
    150116                        action = new MoveScreen(timeStamp);
    151                         // Skip 3 bytes
    152                         src.position(src.position()+3);
    153                         int flagByte1 = src.get();
    154                         if ((flagByte1 & 0x10) != 0 ) {
    155                                 // Skip 1 byte
    156                                 src.position(src.position()+1);
    157                                 int flagByte2 = src.get();
    158                                 if ((flagByte2 & 0x20) != 0) {
    159                                         // Skip 1 byte
    160                                         src.position(src.position()+1);
    161                                         int flagByte3 = src.get();
    162                                         if ((flagByte3 & 0x40) != 0) {
    163                                                 // Skip 2 bytes
    164                                                 src.position(src.position()+2);
    165                                         }
    166                                 }
    167                         }
    168                         else if ((flagByte1 & 0x40) != 0) {
    169                                 // Skip 2 bytes
    170                                 src.position(src.position()+2);
    171                         }
    172                         //System.out.println("Move screen action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     117                        readMoveScreen(src, (MoveScreen) action);
    173118                }
    174119                else {
     
    181126        }
    182127
     128        @Override
     129        protected void readMoveScreen(ByteBuffer src, MoveScreen action) {
     130                // Skip 3 bytes
     131                src.position(src.position()+3);
     132                int flagByte1 = src.get();
     133                if ((flagByte1 & 0x10) != 0 ) {
     134                        // Skip 1 byte
     135                        src.position(src.position()+1);
     136                        int flagByte2 = src.get();
     137                        if ((flagByte2 & 0x20) != 0) {
     138                                // Skip 1 byte
     139                                src.position(src.position()+1);
     140                                int flagByte3 = src.get();
     141                                if ((flagByte3 & 0x40) != 0) {
     142                                        // Skip 2 bytes
     143                                        src.position(src.position()+2);
     144                                }
     145                        }
     146                }
     147                else if ((flagByte1 & 0x40) != 0) {
     148                        // Skip 2 bytes
     149                        src.position(src.position()+2);
     150                }
     151                //System.out.println("Move screen action: offset="+pos+", length="+(src.position()-pos)+" bytes");
     152        }
     153
    183154        /**
    184155         * Returns an instance of this factory.
    185156         * @return Instance.
    186157         */
    187         public static GameActionFactory<SC2Action> getInstance(File file) {
    188                 SC2ActionFactory_v3 instance = instances.get(file);
     158        public static SC2ActionFactory getInstance(File file) {
     159                SC2ActionFactory instance = instances.get(file);
    189160                if (instance == null) {
    190161                        instance = new SC2ActionFactory_v3();
     
    194165        }
    195166
    196         private Select getSelect(int timeStamp, ByteBuffer src) {
    197                 Select action = new Select(timeStamp);
    198                 // FIXME: Deal with unsigned values
    199                 // Selected subgroup
    200                 byte subgroup = src.get();
    201                 // Number of units in the current selection
    202                 int deselectionCount = src.get() & 0xFF;
    203                 int shiftCount = deselectionCount % 8;
    204                 // Number of bytes following to describe the deselected bits
    205                 int deselectionByteCount = deselectionCount/8;
    206                 if (shiftCount > 0) {
    207                         deselectionByteCount += 1;
     167        @Override
     168        protected void readGroup(ByteBuffer src, Group action) {
     169                int header1 = src.get();
     170                // This most likely means that a new group was assigned
     171                boolean assigned = (header1 & 0x02) != 0;
     172                action.setAssigned(assigned);
     173                int bitLength = (header1 & 0xF8) >> 3;
     174                if ((header1 & 0x04) != 0) {
     175                        int header2 = src.get();
     176                        bitLength = (bitLength << 3) + (header2 & 0x07) - 5;
    208177                }
    209                 boolean[] deselectionMap = new boolean[deselectionCount];
    210                 byte flagByte = 0;
    211                 byte lastByte = 0;
    212                 byte nextByte = 0;
    213                 for (int i = 0; i < deselectionByteCount; i++) {
    214                         flagByte = src.get();
    215                         for (int j = 0; j < 8; j++) {
    216                                 if (8*i + j == deselectionCount) {
    217                                         lastByte = flagByte;
    218                                         break;
    219                                 }
    220                                 deselectionMap[8*i + j] = true ? ((flagByte >> j) & 0x1) != 0 : false;
    221                         }
    222                 }
     178                int byteCount = Math.max(0, (int) Math.ceil(bitLength/8.0));
     179                src.position(src.position()+byteCount);
    223180
    224                 if (shiftCount == 0) {
    225                         int unitTypeCount = src.get();
    226                         for (int i = 0; i < unitTypeCount; i++) {
    227                                 int unitTypeID = (src.get() << 16) + (src.get() << 8) + src.get();
    228                                 int unitCount = src.get();
    229                         }
    230                         int unitCountTotal = src.get() & 0xFF;
    231                         for (int i = 0; i < unitCountTotal; i++) {
    232                                 int unitID = src.getInt();
    233                         }
    234                 }
    235                 else {
    236                         nextByte = src.get();
    237                         // Number of different unit types
    238                         int unitTypeCount = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    239                         lastByte = nextByte;
    240                         nextByte = src.get();
    241                         for (int i = 0; i < unitTypeCount; i++) {
    242                                 // Read unit type
    243                                 int unitType = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount))) << 16;
    244                                 lastByte = nextByte;
    245                                 nextByte = src.get();
    246                                 unitType += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount))) << 8;
    247                                 lastByte = nextByte;
    248                                 nextByte = src.get();
    249                                 unitType += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    250                                 lastByte = nextByte;
    251                                 nextByte = src.get();
    252 
    253                                 // Read number of units with this type
    254                                 int unitCount = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    255                                 lastByte = nextByte;
    256                                 nextByte = src.get();
    257                         }
    258 
    259                         // Read units
    260                         int unitCountTotal = (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    261                         for (int i = 0; i < unitCountTotal; i++) {
    262                                 lastByte = nextByte;
    263                                 nextByte = src.get();
    264                                 int unitID = ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 24;
    265                                 lastByte = nextByte;
    266                                 nextByte = src.get();
    267                                 unitID += ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 16;
    268                                 lastByte = nextByte;
    269                                 nextByte = src.get();
    270                                 unitID += ((lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)))) << 8;
    271                                 lastByte = nextByte;
    272                                 nextByte = src.get();
    273                                 unitID += (lastByte & (0xFF << shiftCount)) + (nextByte & (0xFF >> (8-shiftCount)));
    274                         }
    275                 }
    276                 //System.out.println("Select action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    277                 return action;
     181                //System.out.println("Group action: offset="+pos+", length="+(src.position()-pos)+" bytes");
    278182        }
    279183}
Note: See TracChangeset for help on using the changeset viewer.